/* Acedia Kitchen — site styles.
   One stylesheet, no build step, no JavaScript. Palette taken from the app's
   Theme.swift and AccentColor.colorset so the page and the app agree. */

/* ---- Tokens ------------------------------------------------------------ */

:root {
  /* Paper, light. */
  --ground:  #F8F5EF;
  --surface: #FFFEFB;
  --ink:     #2B2621;
  --accent:  #B5543A;

  /* Derived. Muted ink for secondary prose, rule for hairlines. Both are the
     ink colour at low alpha rather than separate hexes, so they stay in tune
     with whichever ground is behind them. */
  --ink-muted: color-mix(in srgb, var(--ink) 66%, transparent);
  --ink-faint: color-mix(in srgb, var(--ink) 42%, transparent);
  --rule:      color-mix(in srgb, var(--ink) 14%, transparent);
  --accent-wash: color-mix(in srgb, var(--accent) 8%, transparent);

  /* The app caps its prose at 65 characters; the reasoning holds here. */
  --measure: 65ch;
  --page: 44rem;

  --serif: ui-serif, "New York", "Iowan Old Style", "Palatino Linotype",
           Palatino, Georgia, "Times New Roman", serif;
  --sans: -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui,
          "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
}

@media (prefers-color-scheme: dark) {
  :root {
    --ground:  #17120B;
    --surface: #2B241A;
    --ink:     #F0E9DF;
    --accent:  #E08560;

    --rule: color-mix(in srgb, var(--ink) 18%, transparent);
    --accent-wash: color-mix(in srgb, var(--accent) 10%, transparent);
  }
}

/* ---- Base -------------------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 1.0625rem;
  line-height: 1.6;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

.wrap {
  width: 100%;
  max-width: var(--page);
  margin-inline: auto;
  padding-inline: 1.5rem;
}

p, li { max-width: var(--measure); }

a {
  color: var(--accent);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
}

a:hover { text-decoration-thickness: 2px; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

h1, h2, h3 {
  font-family: var(--serif);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: -0.012em;
  text-wrap: balance;
  margin: 0;
}

/* ---- Masthead ---------------------------------------------------------- */

.masthead {
  padding-block: 2.25rem 0;
}

.wordmark {
  font-family: var(--serif);
  font-size: 1.0625rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
  display: inline-block;
}

.wordmark:hover { color: var(--accent); }

/* ---- Hero -------------------------------------------------------------- */

.hero {
  padding-block: 3rem 3.5rem;
  border-bottom: 1px solid var(--rule);
}

.hero h1 {
  font-size: clamp(2.5rem, 9vw, 3.75rem);
  margin-bottom: 1.25rem;
}

.lede {
  font-size: 1.1875rem;
  line-height: 1.55;
  color: var(--ink-muted);
  margin: 0 0 2rem;
}

/* ---- Hero spec line ---------------------------------------------------- */

/* The build is invite only, so there is no button here — just the quiet
   statement of what it runs on. */
.hero-meta {
  font-size: 0.9375rem;
  color: var(--ink-faint);
  margin: 0;
}

/* ---- Sections ---------------------------------------------------------- */

section { padding-block: 3.25rem; }

.eyebrow {
  font-family: var(--sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin: 0 0 0.75rem;
}

/* Descendant, not `section > h2`: the heading sits inside .wrap, so a child
   combinator matches nothing and both of these silently do not apply. */
section h2 {
  font-size: clamp(1.625rem, 5vw, 2rem);
  margin-bottom: 2rem;
}

/* ---- Features ---------------------------------------------------------- */

.features {
  display: grid;
  gap: 1.75rem;
  padding: 0;
  margin: 0;
  list-style: none;
}

.feature {
  max-width: none;
  background: var(--surface);
  border-radius: 12px;
  padding: 1.5rem;
}

/* The first feature is the one nothing else does, so it gets the emphasis. */
.feature--lead {
  background: var(--accent-wash);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 22%, transparent);
}

.feature h3 {
  font-size: 1.25rem;
  margin-bottom: 0.5rem;
}

.feature p {
  margin: 0;
  color: var(--ink-muted);
}

@media (min-width: 40rem) {
  .features { grid-template-columns: 1fr 1fr; }
  .feature--lead { grid-column: 1 / -1; }
  .feature--lead h3 { font-size: 1.5rem; }
}

/* ---- Screenshot placeholders ------------------------------------------- */

/* Real screenshots do not exist yet. These are marked placeholders, not
   invented image files — drop <img> tags in when there is something to show. */
.shots {
  display: grid;
  gap: 1rem;
  grid-template-columns: 1fr 1fr;
  /* Not stretch: while some slots hold a real screenshot and others are still
     placeholders, stretching would fight the placeholder's aspect-ratio and
     give the row two different heights. */
  align-items: start;
  padding: 0;
  margin: 0;
  list-style: none;
}

.shot {
  max-width: none;
  aspect-ratio: 9 / 19.5;
  display: grid;
  place-content: center;
  text-align: center;
  padding: 1rem;
  border: 1px dashed var(--rule);
  border-radius: 14px;
  background: var(--surface);
  color: var(--ink-faint);
  font-size: 0.8125rem;
  line-height: 1.4;
}

/* The equivalency editor is the feature nothing else does, and it is the one
   that rewards a close look — so it gets a full row to itself, held to a
   phone-ish width so it does not tower over the page. The other two sit
   beneath it and stay side by side even on a narrow screen. */
.shot--lead {
  grid-column: 1 / -1;
  justify-self: center;
  width: min(100%, 17rem);
  margin-bottom: 0.5rem;
}

/* Once a real screenshot is dropped in, the placeholder chrome gets out of the
   way on its own: no dashed border, no fixed ratio, no pulse — just the image
   with a soft shadow to lift it off the ground. */
.shot:has(img) {
  aspect-ratio: auto;
  display: block;
  padding: 0;
  border: 0;
  background: none;
  overflow: hidden;
  animation: none;
  box-shadow: 0 10px 34px color-mix(in srgb, var(--ink) 16%, transparent);
}

.shot img,
.shot picture {
  display: block;
  width: 100%;
  height: auto;
  border-radius: inherit;
}

/* ---- Closing ----------------------------------------------------------- */

.closing {
  border-top: 1px solid var(--rule);
  text-align: center;
}

.closing h2 { margin-bottom: 1.5rem; }
.closing p { margin-inline: auto; }

/* ---- Prose (privacy page) ---------------------------------------------- */

.prose { padding-block: 2.5rem 1rem; }

.prose h1 {
  font-size: clamp(2rem, 7vw, 2.75rem);
  margin-bottom: 0.75rem;
}

.prose h2 {
  font-size: 1.3125rem;
  margin: 2.75rem 0 0.625rem;
}

.prose p { margin: 0 0 1rem; }

.prose ul {
  padding-left: 1.125rem;
  margin: 0 0 1rem;
}

.prose li { margin-bottom: 0.5rem; }

.updated {
  font-size: 0.9375rem;
  color: var(--ink-faint);
  margin-bottom: 2.5rem;
}

.summary {
  background: var(--surface);
  border-left: 3px solid var(--accent);
  border-radius: 0 10px 10px 0;
  padding: 1.25rem 1.375rem;
  margin: 0 0 1rem;
}

.summary p { margin: 0; }

code {
  font-family: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.875em;
  background: color-mix(in srgb, var(--ink) 7%, transparent);
  padding: 0.1em 0.35em;
  border-radius: 4px;
  overflow-wrap: anywhere;
}

/* ---- Footer ------------------------------------------------------------ */

.footer {
  border-top: 1px solid var(--rule);
  padding-block: 2rem 3rem;
  font-size: 0.9375rem;
  color: var(--ink-faint);
}

.footer p { margin: 0 0 0.375rem; }

.footer nav {
  display: flex;
  flex-wrap: wrap;
  gap: 1.25rem;
  margin-bottom: 1rem;
}

/* ---- Motion ------------------------------------------------------------ */

/* Everything below is an enhancement. The page is fully readable with JS off
   and with animations off — the reveal styles are scoped to .js, which the
   inline snippet in <head> only adds when scripting is available, so nothing
   is ever left invisible waiting for a script that did not run. */

/* Cross-document transition between index and privacy. Supporting browsers
   morph the shared wordmark; others just navigate, which is fine. */
@view-transition { navigation: auto; }

.wordmark { view-transition-name: wordmark; }

/* Hero entrance. Pure CSS, runs on load, no observer involved. */
@keyframes rise {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

.hero h1,
.hero .lede,
.hero .hero-meta {
  animation: rise 0.9s cubic-bezier(0.2, 0.6, 0.2, 1) backwards;
}

.hero h1        { animation-delay: 0.05s; }
.hero .lede     { animation-delay: 0.18s; }
.hero .hero-meta{ animation-delay: 0.3s; }

/* Scroll reveal. .reveal is inert until the observer marks it visible. */
.js .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 0.75s cubic-bezier(0.2, 0.6, 0.2, 1),
    transform 0.75s cubic-bezier(0.2, 0.6, 0.2, 1);
  transition-delay: calc(var(--i, 0) * 70ms);
  will-change: opacity, transform;
}

.js .reveal.is-visible {
  opacity: 1;
  transform: none;
  will-change: auto;
}

/* A slow settle on the hero as it leaves the viewport. Scroll-driven, so it
   costs no JavaScript; browsers without scroll timelines simply skip it. */
@supports (animation-timeline: view()) {
  @keyframes settle {
    to { opacity: 0.25; transform: translateY(-1.5rem); }
  }

  .hero .wrap {
    animation: settle linear both;
    animation-timeline: view();
    animation-range: exit -10% exit 90%;
  }
}

/* Micro-interactions. Warm and slow rather than springy — it should still
   feel like a cookbook. */
.feature {
  transition: transform 0.35s cubic-bezier(0.2, 0.6, 0.2, 1),
              box-shadow 0.35s ease;
}

.feature:hover {
  transform: translateY(-3px);
  box-shadow: 0 10px 28px color-mix(in srgb, var(--ink) 9%, transparent);
}

.feature--lead:hover {
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--accent) 30%, transparent),
    0 10px 28px color-mix(in srgb, var(--accent) 16%, transparent);
}

.wordmark { transition: color 0.25s ease; }

/* The placeholders breathe very faintly, which reads as "something goes here"
   rather than "this failed to load". */
@keyframes breathe {
  50% { border-color: color-mix(in srgb, var(--accent) 34%, transparent); }
}

.shot {
  animation: breathe 5s ease-in-out infinite;
  transition: transform 0.35s cubic-bezier(0.2, 0.6, 0.2, 1);
}

.shot:nth-child(2) { animation-delay: 0.6s; }
.shot:nth-child(3) { animation-delay: 1.2s; }
.shot:hover { transform: translateY(-4px); }

/* The one switch that turns all of it off. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: none; }

  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }

  .js .reveal {
    opacity: 1;
    transform: none;
  }

  .feature:hover,
  .shot:hover { transform: none; }

  /* The universal selector above does not match pseudo-elements, so the
     view-transition cross-fade has to be stopped by name. */
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation: none !important; }

  /* And the scroll-driven settle has to be switched off rather than sped up:
     a timeline-driven animation with `both` fill and a near-zero duration can
     snap straight to its end state and leave the hero sitting at 25% opacity. */
  .hero .wrap { animation: none !important; }
}
