/* =========================================================================
   glimpse landing - design tokens
   Source: Figma "glimpse - Handover" (PRD s8). Contrast rules in s8 are
   enforced here at the token level, not left to per-component judgement:

     #4A3286 on white ......... 10.0:1  -> safe as text (LIGHT mode only)
     #B99CE3 on white .......... 2.35:1 -> decorative only in light mode
     #9CB3E3 on white .......... 2.11:1 -> decorative only in light mode
     #B99CE3 on #0A0A0A ........ 8.4:1  -> safe as text (DARK mode only)
     #9CB3E3 on #0A0A0A ........ 9.4:1  -> safe as text (DARK mode only)
     #8A8A8A on white .......... 3.45:1 -> large text only, never body
     #5E5E5E on white .......... 6.5:1  -> secondary body text

   Because the accent flips role between modes, --accent is defined per mode
   and every text/background pair below is pre-checked. Do not hardcode a
   brand hex anywhere outside this file.
   ========================================================================= */

:root {
  /* ---- brand ramp (raw, mode-independent) ---- */
  --brand-700: #4A3286;
  --brand-500: #6B4FB0;
  --brand-300: #B99CE3;
  --brand-100: #F0EBFA;
  --secondary-300: #9CB3E3;
  --secondary-900: #182345;

  --neutral-100: #FAFAFA;
  --neutral-200: #F1F1F1;
  --neutral-300: #DCDCDC;
  --neutral-500: #8A8A8A;
  --neutral-600: #5E5E5E;
  --neutral-800: #1F1F1F;
  --neutral-900: #0A0A0A;

  /* ---- semantic: LIGHT (default) ---- */
  color-scheme: light;
  --bg:            #FCFCFD;
  --bg-sunk:       var(--brand-100);
  --bg-raised:     #FFFFFF;
  --text:          var(--neutral-800);
  --text-muted:    var(--neutral-600);
  --text-faint:    #66666C;
  --accent:        var(--brand-700);
  --accent-soft:   #6B4FB0;
  --on-accent:     #FFFFFF;
  --decor:         var(--brand-300);
  --decor-ink:     #7A5CB8;
  --decor-2:       var(--secondary-300);
  --line:          rgba(74, 50, 134, 0.13);
  --line-strong:   rgba(74, 50, 134, 0.24);
  --field:         rgba(74, 50, 134, 0.05);
  --shadow-soft:   0 1px 2px rgba(74, 50, 134, .05), 0 12px 32px -20px rgba(74, 50, 134, .30);
  --halo:          radial-gradient(60% 60% at 50% 45%, rgba(185,156,227,.55), rgba(185,156,227,0) 72%);
  --slot-fill:     linear-gradient(168deg, #F5F0FC 0%, #EBE4F8 55%, #E3EAF8 100%);

  /* ---- shape lock: pills for interactive, 20px media, 24px surfaces ---- */
  --r-pill: 999px;
  --r-media: 20px;
  --r-surface: 24px;

  /* ---- type ---- */
  --font-display: "Schibsted Grotesk", "Sagace", ui-sans-serif, system-ui, sans-serif;
  --font-body: "Instrument Sans", "PP Neue Montreal", ui-sans-serif, system-ui, -apple-system, sans-serif;
  --font-reflect: "Instrument Serif", Georgia, "Times New Roman", serif;

  /* fluid scale, density 2 (airy) */
  --t-display: clamp(2.25rem, 1.35rem + 3.4vw, 3.5rem);
  --t-h2:      clamp(1.875rem, 1.3rem + 2.2vw, 2.85rem);
  --t-h3:      clamp(1.125rem, 1.03rem + 0.4vw, 1.3rem);
  --t-lead:    clamp(1.0625rem, 0.99rem + 0.36vw, 1.28rem);
  --t-body:    1.0625rem;
  --t-small:   0.9375rem;
  --t-label:   0.75rem;

  /* ---- rhythm ---- */
  --gutter: clamp(1.25rem, 5vw, 2.5rem);
  --section-y: clamp(5rem, 10vw, 9rem);
  --measure: 60ch;
  --shell: 1200px;

  --ease: cubic-bezier(.16, 1, .3, 1);
}

/* ---- semantic: DARK ----
   Guarded so an explicit light choice always wins over the system default. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;
    --bg:          #0A0A0C;
    --bg-sunk:     #121016;
    --bg-raised:   #16141C;
    --text:        #EDE9F5;
    --text-muted:  #B3AEC1;
    --text-faint:  #9C97A8;
    --accent:      var(--brand-300);
    --accent-soft: #C9B4EB;
    --on-accent:   #0A0A0C;
    --decor:       var(--brand-300);
    --decor-ink:   var(--brand-300);
    --decor-2:     var(--secondary-300);
    --line:        rgba(185, 156, 227, 0.16);
    --line-strong: rgba(185, 156, 227, 0.30);
    --field:       rgba(185, 156, 227, 0.07);
    --shadow-soft: 0 1px 2px rgba(0, 0, 0, .45), 0 16px 40px -24px rgba(0, 0, 0, .8);
    --halo:        radial-gradient(60% 60% at 50% 45%, rgba(185,156,227,.30), rgba(185,156,227,0) 72%);
    --slot-fill:   linear-gradient(168deg, #1B1726 0%, #171520 55%, #151A28 100%);
  }
}

:root[data-theme="dark"] {
  color-scheme: dark;
  --bg:          #0A0A0C;
  --bg-sunk:     #121016;
  --bg-raised:   #16141C;
  --text:        #EDE9F5;
  --text-muted:  #B3AEC1;
  --text-faint:  #9C97A8;
  --accent:      var(--brand-300);
  --accent-soft: #C9B4EB;
  --on-accent:   #0A0A0C;
  --decor:       var(--brand-300);
  --decor-ink:   var(--brand-300);
  --decor-2:     var(--secondary-300);
  --line:        rgba(185, 156, 227, 0.16);
  --line-strong: rgba(185, 156, 227, 0.30);
  --field:       rgba(185, 156, 227, 0.07);
  --shadow-soft: 0 1px 2px rgba(0, 0, 0, .45), 0 16px 40px -24px rgba(0, 0, 0, .8);
  --halo:        radial-gradient(60% 60% at 50% 45%, rgba(185,156,227,.30), rgba(185,156,227,0) 72%);
  --slot-fill:   linear-gradient(168deg, #1B1726 0%, #171520 55%, #151A28 100%);
}

/* =========================================================================
   glimpse landing - base, layout, components
   Author note: no framework. The page budget (PRD s7) is ~11KB of CSS,
   which leaves the byte budget to the screenshots where it belongs.
   ========================================================================= */

*, *::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(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: var(--t-body);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, svg { display: block; max-width: 100%; }
h1, h2, h3, p, ul, ol, figure, blockquote { margin: 0; }
ul, ol { padding: 0; list-style: none; }
a { color: inherit; }

/* ---- focus: one visible ring everywhere, never removed ---- */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 6px;
}

.skip-link {
  position: absolute; left: var(--gutter); top: -100px; z-index: 100;
  padding: .75rem 1.25rem; border-radius: var(--r-pill);
  background: var(--accent); color: var(--on-accent);
  font-weight: 600; text-decoration: none;
  transition: top .18s var(--ease);
}
.skip-link:focus { top: 1rem; }

.visually-hidden {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* =========================== typography =============================== */

.display, .h2 {
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: -0.028em;
  text-wrap: balance;
  color: var(--text);
}
.display { font-size: var(--t-display); line-height: 1.08; }
.h2 { font-size: var(--t-h2); line-height: 1.12; }
.h3 {
  font-family: var(--font-display);
  font-size: var(--t-h3); font-weight: 600;
  letter-spacing: -0.015em; line-height: 1.3;
}

/* Reflective sentences use the brand's serif italic. Descenders in italic
   clip at tight leading, so leading and reserve are set explicitly. */
.reflect {
  font-family: var(--font-reflect);
  font-style: italic;
  font-weight: 400;
  letter-spacing: 0;
  line-height: 1.16;
  padding-bottom: .12em;
}

.lead { font-size: var(--t-lead); line-height: 1.6; color: var(--text-muted); max-width: 52ch; }
.body { color: var(--text-muted); max-width: var(--measure); }
.body + .body { margin-top: 1.1em; }
.small { font-size: var(--t-small); color: var(--text-muted); }

.overline {
  font-size: var(--t-label);
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1.25rem;
}

/* =========================== layout =================================== */

.shell { width: min(100% - (var(--gutter) * 2), var(--shell)); margin-inline: auto; }
.section { padding-block: var(--section-y); }
.section--sunk { background: var(--bg-sunk); }
.section__head { max-width: 46ch; margin-bottom: clamp(2.5rem, 5vw, 4rem); }

.rule { height: 1px; background: var(--line); border: 0; margin: 0; }

/* =========================== nav ====================================== */

.nav {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color .3s var(--ease);
}
.nav[data-stuck="true"] { border-bottom-color: var(--line); }
.nav__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; height: 68px;
}
/* Every standalone link carries a 44px touch target (PRD s7). */
.wordmark {
  display: inline-flex; align-items: center; min-height: 44px;
  text-decoration: none; color: var(--text);
}
/* Supplied wordmark. Its paths are set to currentColor, so one asset serves
   both themes and no second file is requested. */
.wordmark svg { height: 21px; width: auto; }
.wordmark--lg svg { height: 28px; }
.nav__links { display: flex; align-items: center; gap: clamp(.25rem, 1.2vw, 1rem); }
.nav__links a {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; min-width: 44px; padding-inline: .5rem;
  font-size: var(--t-small); color: var(--text-muted);
  text-decoration: none; transition: color .2s var(--ease);
}
.nav__links a:hover { color: var(--text); }
@media (max-width: 767px) { .nav__links { display: none; } }

.theme-toggle {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid var(--line); border-radius: var(--r-pill);
  background: transparent; color: var(--text-muted);
  cursor: pointer;
  transition: color .2s var(--ease), border-color .2s var(--ease), background-color .2s var(--ease);
}
.theme-toggle:hover { color: var(--text); border-color: var(--line-strong); background: var(--field); }
.theme-toggle .icon-moon { display: none; }
:root[data-theme="dark"] .theme-toggle .icon-moon,
:root:not([data-theme="light"]) .theme-toggle .icon-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .icon-sun { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .icon-sun { display: none; }
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) .theme-toggle .icon-moon { display: none; }
  :root:not([data-theme="dark"]) .theme-toggle .icon-sun { display: block; }
}

/* =========================== buttons ================================== */

.store-row { display: flex; flex-wrap: wrap; gap: .75rem; align-items: center; }

.btn-store {
  display: inline-flex; align-items: center; gap: .7rem;
  min-height: 52px; padding: .7rem 1.4rem;
  border-radius: var(--r-pill);
  border: 1px solid var(--line-strong);
  background: transparent; color: var(--text);
  text-decoration: none; font-weight: 500;
  cursor: pointer;
  transition: transform .18s var(--ease), background-color .2s var(--ease), border-color .2s var(--ease);
}
.btn-store:hover { background: var(--field); border-color: var(--accent); }
.btn-store:active { transform: translateY(1px); }
.btn-store svg { flex: none; }
.btn-store__text { display: flex; flex-direction: column; line-height: 1.15; text-align: left; }
.btn-store__text small { font-size: .6875rem; color: var(--text-muted); letter-spacing: .02em; }
.btn-store__text span { font-size: .975rem; white-space: nowrap; }

/* Primary = the store matching the visitor's OS. Both stay visible (PRD s6). */
.btn-store[data-primary="true"] {
  background: var(--accent); border-color: var(--accent); color: var(--on-accent);
  box-shadow: var(--shadow-soft);
}
.btn-store[data-primary="true"] .btn-store__text small { color: color-mix(in srgb, var(--on-accent) 76%, transparent); }
.btn-store[data-primary="true"]:hover { background: var(--accent-soft); border-color: var(--accent-soft); }

.trust-line {
  margin-top: 1.5rem; font-size: var(--t-small);
  color: var(--text-muted); letter-spacing: .01em;
}

.link-arrow {
  display: inline-flex; align-items: center; min-height: 44px; gap: .45rem;
  color: var(--accent); font-weight: 500; text-decoration: none;
  border-bottom: 1px solid transparent; padding-bottom: 2px;
  transition: border-color .2s var(--ease);
}
.link-arrow:hover { border-bottom-color: currentColor; }

/* =========================== app screenshots ==========================
   Real exports from the app, pre-cropped at build time by
   scripts/build-images.py so the browser downloads only the pixels it shows.
   Each screenshot carries its own near-black ground, which would vanish into
   the dark theme, so the frame supplies the edge. */

.shot {
  display: block;
  border-radius: var(--r-media);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: var(--bg-sunk);
}
.shot img { width: 100%; height: auto; display: block; }

.shot--feature { margin-top: auto; }

/* The QR slot is the one placeholder left: it cannot be drawn until the
   download URL exists. */
.slot {
  position: relative;
  border-radius: var(--r-media);
  background: var(--slot-fill);
  border: 1px solid var(--line);
  overflow: hidden;
  display: grid; place-items: center;
  padding: 1rem;
}
.slot__meta {
  text-align: center; max-width: 24ch;
  font-size: .7rem; line-height: 1.5; letter-spacing: .04em;
  /* Sits on the light slot gradient, so it takes the darker muted tone. */
  color: var(--neutral-600);
}
.slot__meta b { display: block; color: var(--text-muted); font-weight: 600; letter-spacing: .06em; text-transform: uppercase; font-size: .6875rem; margin-bottom: .3rem; }

/* =========================== hero ===================================== */

.hero { padding-top: clamp(3rem, 7vw, 6rem); padding-bottom: var(--section-y); }
.hero__grid {
  display: grid; gap: clamp(2.5rem, 6vw, 4.5rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 900px) {
  .hero__grid { grid-template-columns: minmax(0, 1.25fr) minmax(0, .62fr); }
}
.hero__copy { max-width: 36ch; }
@media (min-width: 900px) { .hero__copy { max-width: none; } }
.hero .display { margin-bottom: 1.5rem; text-wrap: pretty; }
.hero .lead { margin-bottom: 2.25rem; max-width: 50ch; }

/* ---- hero stage ----
   The phone reserves its space with aspect-ratio, so the cross-fade never
   shifts layout and CLS stays at zero. A soft halo sits behind it for depth;
   it does not move, because the sequence is already the one thing in motion
   up here. */
.hero__art { position: relative; margin: 0; }
.hero__art::before {
  content: "";
  position: absolute; inset: 0;
  background: var(--halo);
  opacity: .8;
  pointer-events: none;
}

.phone {
  position: relative;
  aspect-ratio: 560 / 1212;
  max-width: 258px;
  margin-inline: auto;
  border-radius: var(--r-media);
  overflow: hidden;
  border: 1px solid var(--line-strong);
  background: var(--bg-sunk);
  box-shadow: var(--shadow-soft);
}
.phone__screen {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
}
.phone__screen.is-current { opacity: 1; }
.phone__screen img { width: 100%; height: 100%; object-fit: cover; display: block; }

.hero__caption {
  display: flex; align-items: center; justify-content: center; gap: .5rem;
  margin-top: 1.1rem;
  font-size: var(--t-small);
  color: var(--text-muted);
}
#hero-label { transition: opacity .4s var(--ease); }
.hero__caption[data-swapping="true"] #hero-label { opacity: 0; }

.hero__toggle {
  display: inline-grid; place-items: center;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid transparent; border-radius: var(--r-pill);
  background: transparent; color: var(--text-faint);
  cursor: pointer;
  transition: color .2s var(--ease), border-color .2s var(--ease);
}
.hero__toggle:hover { color: var(--text); border-color: var(--line-strong); }


/* =========================== essence (s5.2) =========================== */

.essence { text-align: center; }
.essence__body {
  margin-inline: auto; max-width: 28ch;
  font-size: clamp(1.5rem, 1rem + 2.1vw, 2.35rem);
  line-height: 1.3; color: var(--text);
}
.essence__body .reflect { color: var(--accent); }

/* The second beat is quieter than the first: the field between them carries
   the turn, so the copy does not have to shout twice. */
.essence__body--quiet {
  font-size: clamp(1.3rem, .95rem + 1.5vw, 1.9rem);
  color: var(--text-muted);
  max-width: 34ch;
}

/* ---- soul field (section 5.2) ---- */
.essence__field {
  height: clamp(132px, 20vw, 208px);
  margin-block: clamp(2.5rem, 5vw, 3.75rem);
  color: var(--decor-ink);
  /* Fades at all four edges so the population reads as continuing past the
     frame rather than stopping at a box. */
  -webkit-mask-image:
    linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent),
    linear-gradient(#000, #000);
  mask-image:
    linear-gradient(90deg, transparent, #000 14%, #000 86%, transparent),
    linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
  -webkit-mask-composite: source-in;
  mask-composite: intersect;
}
.soul-field { width: 100%; height: 100%; }
.soul-field__you { fill: var(--accent); opacity: 1; }
.soul-field__ring { stroke: var(--accent); opacity: .5; }

/* The points drift and breathe. The copy says a release "drifts quietly to
   others", so the movement is the sentence rather than decoration, and it is
   kept slow enough to read as a sky rather than as a particle effect.

   fill-opacity is animated, not opacity: each circle keeps its own authored
   opacity as a base brightness and the two multiply, so near points stay
   bright and far ones stay faint through the whole cycle. Eight nth-child
   variants with coprime durations desynchronise 125 points without a single
   per-element style. */
@media (prefers-reduced-motion: no-preference) {
  .soul-field circle:not([class]) {
    animation: soul-drift var(--soul-dur, 14s) ease-in-out var(--soul-delay, 0s) infinite alternate;
    will-change: transform, fill-opacity;
  }
  /* Paused until the section is actually on screen. 123 looping animations
     running while someone reads the FAQ is battery spent on nothing. */
  .essence__field :is(.soul-field circle, .soul-field__ring) { animation-play-state: paused; }
  .essence__field[data-live="true"] :is(.soul-field circle, .soul-field__ring) { animation-play-state: running; }
  .soul-field circle:not([class]):nth-child(8n+1) { --soul-dur: 11s;   --soul-delay: 0s;    --soul-x: 2px;    --soul-y: -1.5px; }
  .soul-field circle:not([class]):nth-child(8n+2) { --soul-dur: 17s;   --soul-delay: -3s;   --soul-x: -1.5px; --soul-y: 2px; }
  .soul-field circle:not([class]):nth-child(8n+3) { --soul-dur: 13s;   --soul-delay: -7s;   --soul-x: 1px;    --soul-y: 2.5px; }
  .soul-field circle:not([class]):nth-child(8n+4) { --soul-dur: 19s;   --soul-delay: -2s;   --soul-x: -2.5px; --soul-y: -1px; }
  .soul-field circle:not([class]):nth-child(8n+5) { --soul-dur: 15s;   --soul-delay: -9s;   --soul-x: 1.5px;  --soul-y: 1px; }
  .soul-field circle:not([class]):nth-child(8n+6) { --soul-dur: 23s;   --soul-delay: -5s;   --soul-x: -1px;   --soul-y: -2.5px; }
  .soul-field circle:not([class]):nth-child(8n+7) { --soul-dur: 12.5s; --soul-delay: -11s;  --soul-x: 2.5px;  --soul-y: 1.5px; }
  .soul-field circle:not([class]):nth-child(8n+8) { --soul-dur: 21s;   --soul-delay: -6s;   --soul-x: -2px;   --soul-y: 2px; }

  /* The one marked point breathes instead of drifting: it is you, and you
     are the fixed thing in the picture. */
  .soul-field__ring {
    transform-box: fill-box; transform-origin: center;
    animation: soul-presence 7s ease-in-out infinite alternate;
  }
}

@keyframes soul-drift {
  from { fill-opacity: .35; transform: translate(0, 0); }
  to   { fill-opacity: 1;   transform: translate(var(--soul-x, 0), var(--soul-y, 0)); }
}
@keyframes soul-presence {
  from { transform: scale(1);    opacity: .5; }
  to   { transform: scale(1.14); opacity: .26; }
}

/* --decor-ink is the denser purple the light theme needs. Decorative only:
   no text is ever set in it, so PRD s8's contrast limits are not in play. */
/* Inline, not a pill: a chip inside a running sentence leaves an awkward
   gap before the following comma. */
.soul-tag {
  font-family: var(--font-body);
  font-variant-numeric: tabular-nums;
  font-size: .88em; letter-spacing: .01em;
  color: var(--accent);
  box-shadow: inset 0 -.09em 0 var(--line-strong);
}

/* =========================== how it works (s5.3) ======================
   Three columns, no card chrome. Every column opens with the same 4:5 frame,
   so the row aligns exactly without any height tuning: the frames set one
   shared baseline and the copy hangs beneath it. */

.steps {
  display: grid;
  gap: clamp(2rem, 4vw, 3rem);
  grid-template-columns: 1fr;
  list-style: none;
  counter-reset: step;
}
@media (min-width: 760px) { .steps { grid-template-columns: repeat(3, 1fr); } }

.step {
  display: grid;
  gap: .9rem;
  align-content: start;
}
.shot--step { margin-bottom: .35rem; }

.step__head {
  display: flex; align-items: baseline; gap: .6rem;
  font-family: var(--font-display);
  font-size: var(--t-h3); font-weight: 600;
  letter-spacing: -0.015em; line-height: 1.3;
}
/* The numeral is the sequence, so it is set in the page's reflective serif
   rather than boxed into a badge. */
.step__index {
  font-family: var(--font-reflect); font-style: italic; font-weight: 400;
  font-size: 1.15em; line-height: 1; color: var(--accent);
  flex: none;
}
.step__text { color: var(--text-muted); font-size: var(--t-small); max-width: 34ch; }

/* =========================== inside (s5.4) ============================
   Bento: exactly four items, four cells, two of them carrying real
   surface treatment rather than another white box. */

.bento { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .bento { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) {
  .bento { grid-template-columns: repeat(6, 1fr); }
  .bento__cell:nth-child(1) { grid-column: span 4; }
  .bento__cell:nth-child(2) { grid-column: span 2; }
  .bento__cell:nth-child(3) { grid-column: span 2; }
  .bento__cell:nth-child(4) { grid-column: span 4; }
}
.bento__cell {
  display: flex; flex-direction: column; gap: 1rem;
  padding: clamp(1.5rem, 3vw, 2.25rem);
  border-radius: var(--r-surface);
  border: 1px solid var(--line);
  background: var(--bg-raised);
}
.bento__cell[data-fill="tint"] { background: var(--bg-sunk); }
.bento__cell[data-fill="gradient"] {
  background: var(--slot-fill);
}
.bento__cell .body { font-size: var(--t-small); max-width: 38ch; }

/* =========================== limited feed (s5.5) ====================== */

.limit { text-align: center; }
.limit__mark {
  font-family: var(--font-display);
  font-size: clamp(5rem, 16vw, 11rem);
  line-height: .85; font-weight: 500;
  letter-spacing: -0.06em;
  color: var(--accent);
  opacity: .15;
  margin-bottom: -.04em;
  user-select: none;
}
.limit .h2 { margin-bottom: 1.75rem; }
.limit .body { margin-inline: auto; text-align: center; max-width: 44ch; }

/* =========================== breathe (s5.6) ===========================
   Names the four models and points at the app. No practice here.
   Hairline-separated cells rather than cards: the bento above already uses
   cards, and these are four peers, not four objects. */

.breathe__head { max-width: 58ch; }
.breathe__head .h2 { margin-bottom: 1.5rem; }
.breathe__head .body { max-width: 56ch; }

.patterns {
  display: grid; gap: 0;
  margin: clamp(2.5rem, 5vw, 3.5rem) 0 0;
  list-style: none;
}
@media (min-width: 720px) { .patterns { grid-template-columns: 1fr 1fr; } }

.pattern {
  display: grid; gap: .55rem;
  align-content: start;
  padding: clamp(1.5rem, 3vw, 2rem) 0;
  border-top: 1px solid var(--line);
}
@media (min-width: 720px) {
  .pattern { padding-inline: 0 clamp(2rem, 5vw, 4rem); }
  /* The right-hand cells keep their own gutter so the two columns do not
     read as one run-on block. */
  .pattern:nth-child(even) { padding-inline: clamp(2rem, 5vw, 4rem) 0; border-left: 1px solid var(--line); }
}
.patterns { border-bottom: 1px solid var(--line); }

/* The glyph is the fastest way to recognise a pattern, so it leads. */
.pattern__shape { width: 132px; height: 38px; color: var(--decor-ink); }
.pattern__name {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.0625rem; letter-spacing: -0.012em; color: var(--text);
}
.pattern__name span {
  color: var(--text-faint); font-weight: 400;
  margin-left: .5rem; font-variant-numeric: tabular-nums;
}
.pattern__purpose { font-size: var(--t-small); color: var(--text-muted); max-width: 34ch; }

/* =========================== privacy (s5.7) =========================== */

.privacy__grid { display: grid; gap: clamp(2rem, 5vw, 4rem); grid-template-columns: 1fr; }
@media (min-width: 900px) { .privacy__grid { grid-template-columns: .85fr 1.15fr; align-items: start; } }

.claims { display: grid; }
.claim {
  display: grid; grid-template-columns: auto 1fr; gap: 1rem;
  padding-block: 1.35rem;
  border-bottom: 1px solid var(--line);
}
.claim:first-child { border-top: 1px solid var(--line); }
.claim svg { color: var(--accent); margin-top: .28em; flex: none; }
/* A confirmed claim gets a tick. One still waiting on engineering or legal
   gets an open ring in the same warning colour as its marker, so the icon
   never asserts something the copy has not earned. */
.claim--pending svg { color: #B4531F; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .claim--pending svg { color: #E8A06A; }
}
:root[data-theme="dark"] .claim--pending svg { color: #E8A06A; }
.claim p { color: var(--text); font-size: var(--t-small); max-width: 46ch; }

/* =========================== gallery (s5.8) =========================== */

.gallery {
  display: grid; grid-auto-flow: column;
  grid-auto-columns: min(260px, 68vw);
  gap: 1.25rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* Without this the first card snaps past the inline padding and sits flush
     against the viewport edge. */
  scroll-padding-inline-start: var(--gutter);
  padding-block: .5rem 1.5rem;
  padding-inline: var(--gutter);
  margin-inline: calc(var(--gutter) * -1);
  scrollbar-width: thin;
}
.gallery > figure { scroll-snap-align: start; margin: 0; }
.gallery figcaption {
  margin-top: .85rem; font-size: var(--t-small);
  color: var(--text-muted); max-width: 30ch;
}

/* =========================== faq (s5.9) =============================== */

/* The FAQ sits as a centred column, like the other single-message sections
   on the page. The rows themselves stay left aligned: a question with a
   chevron pinned right reads badly centred, and centred answer text is
   harder to scan down. */
#faq .section__head {
  max-width: 34ch;
  margin-inline: auto;
  text-align: center;
}
.faq { max-width: 44rem; margin-inline: auto; }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__item:first-child { border-top: 1px solid var(--line); }
.faq__item summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem;
  padding-block: 1.4rem; min-height: 44px;
  cursor: pointer; list-style: none;
  font-family: var(--font-display); font-weight: 500;
  font-size: 1.0625rem; letter-spacing: -0.012em;
}
.faq__item summary::-webkit-details-marker { display: none; }
.faq__item summary::after {
  content: ""; flex: none;
  width: 11px; height: 11px;
  border-right: 1.5px solid var(--accent);
  border-bottom: 1.5px solid var(--accent);
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform .25s var(--ease);
}
.faq__item[open] summary::after { transform: rotate(225deg) translate(-2px, -2px); }
.faq__answer { padding-bottom: 1.5rem; color: var(--text-muted); font-size: var(--t-small); max-width: 56ch; }

/* =========================== final cta (s5.10) ======================== */

.final { text-align: center; }
.final .display { margin-inline: auto; max-width: 18ch; margin-bottom: 2.5rem; }
.final .store-row { justify-content: center; }

.qr {
  display: none; margin-top: 3rem;
  align-items: center; justify-content: center; gap: 1rem;
  color: var(--text-muted); font-size: var(--t-small);
}
.qr[data-visible="true"] { display: flex; }
.qr img, .qr .slot {
  width: 108px; height: 108px; aspect-ratio: 1;
  border-radius: 12px; background: #fff; padding: 8px;
}
.qr span { max-width: 18ch; text-align: left; }

/* =========================== footer (s5.11) =========================== */

.footer { border-top: 1px solid var(--line); padding-block: clamp(3rem, 6vw, 4.5rem) 2.5rem; }
.footer__grid {
  display: grid; gap: 2.5rem;
  grid-template-columns: 1fr;
}
@media (min-width: 760px) {
  /* The crisis notice sits in the footer's own grid rather than below it.
     Legal and Contact are two and one link, so the right half of the footer
     was empty while the notice ran at half width underneath: the imbalance
     was a hole in the composition, not the width of the card. */
  .footer__grid {
    grid-template-columns: 1.1fr 1fr 1fr;
    grid-template-areas:
      "brand legal contact"
      "brand crisis crisis";
    align-content: start;
  }
  .footer__grid > .footer__col:nth-child(1) { grid-area: brand; }
  .footer__grid > .footer__col:nth-child(2) { grid-area: legal; }
  .footer__grid > .footer__col:nth-child(3) { grid-area: contact; }
  .footer__grid > .crisis { grid-area: crisis; margin-top: 0; }
}
.footer__col h2 {
  font-size: var(--t-label); font-weight: 600; letter-spacing: .14em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 1rem;
}
.footer__col ul { display: grid; gap: .1rem; }
.footer__col a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-small); color: var(--text-muted); text-decoration: none;
}
.footer__col a:hover { color: var(--text); }

/* The crisis notice runs the full footer width. Capping it at a reading
   measure left the right half of the footer empty, which read as an unfinished
   layout on the one block that most needs to look considered. The measure is
   kept where it belongs instead: on the paragraph, inside a second column. */
.crisis {
  margin-top: 3rem;
  padding: clamp(1.4rem, 2.5vw, 2rem);
  border-radius: var(--r-media);
  border: 1px solid var(--line-strong);
  background: var(--field);
  font-size: var(--t-small); color: var(--text);
  display: grid; gap: 1rem;
  grid-template-columns: 1fr;
}
.crisis__title {
  font-family: var(--font-display);
  font-size: 1rem; font-weight: 600;
  letter-spacing: -0.012em; line-height: 1.35;
  color: var(--text);
}
.crisis__body { display: grid; gap: 1rem; }
.crisis__body p { max-width: 46ch; }

/* On the legal pages the footer has no columns to fill, so it takes the same
   measure as the document above it. The notice then spans a full, coherent
   width instead of sitting short inside a much wider footer. */
main.legal + .footer .shell { max-width: 46rem; }

/* Local crisis lines, added under the universal guidance rather than
   replacing it. Numbers are set large and tappable: someone reading this is
   not in a state to hunt for a small link. */
.crisis__local { padding-top: 1rem; border-top: 1px solid var(--line-strong); }
.crisis__head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  font-size: var(--t-label); font-weight: 600;
  letter-spacing: .12em; text-transform: uppercase;
  color: var(--text-faint);
  margin-bottom: .75rem;
}
.crisis__pick select {
  font: inherit; font-size: .8125rem; letter-spacing: normal; text-transform: none;
  min-height: 44px; padding: .25rem 1.75rem .25rem .6rem;
  color: var(--text); background: transparent;
  border: 1px solid var(--line-strong); border-radius: var(--r-pill);
  cursor: pointer;
}
.crisis__lines { display: grid; gap: .65rem; }
.crisis__lines li { display: flex; align-items: baseline; gap: .65rem; flex-wrap: wrap; }
.crisis__label { color: var(--text-muted); font-size: var(--t-small); }
.crisis__number {
  font-family: var(--font-display); font-weight: 600;
  font-size: 1.15rem; letter-spacing: .01em;
  font-variant-numeric: tabular-nums;
  color: var(--accent); text-decoration: none;
  /* A phone number someone taps in a bad moment gets a full touch target. */
  display: inline-flex; align-items: center; min-height: 44px;
}
.crisis__number:hover { text-decoration: underline; text-underline-offset: 3px; }
.crisis__note { color: var(--text-faint); font-size: var(--t-small); }

.footer__base {
  margin-top: 3rem; padding-top: 1.75rem; border-top: 1px solid var(--line);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: var(--t-small); color: var(--text-faint);
}

/* =========================== legal pages ==============================
   The privacy policy and terms use the same tokens as the landing page, at a
   reading measure rather than a marketing one. */

.legal { padding-block: clamp(3rem, 7vw, 5rem) var(--section-y); }
.legal .shell { max-width: 46rem; }
.legal__head { margin-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.legal__head .h2 { margin-bottom: 1rem; }
.legal__meta { font-size: var(--t-small); color: var(--text-muted); margin-bottom: 1.5rem; }

.legal__toc {
  padding: 1.5rem;
  border-radius: var(--r-surface);
  background: var(--bg-sunk);
  margin-bottom: clamp(2.5rem, 5vw, 3.5rem);
}
.legal__toc ol {
  display: grid; gap: .35rem;
  counter-reset: toc;
  margin: 0; padding: 0; list-style: none;
}
.legal__toc a {
  display: inline-flex; align-items: center; min-height: 44px;
  font-size: var(--t-small); color: var(--text-muted); text-decoration: none;
}
.legal__toc a:hover { color: var(--text); }

.legal__section { margin-bottom: clamp(2.25rem, 4vw, 3rem); }
.legal__section .h3 { margin-bottom: 1rem; }
.legal__section .body { max-width: none; }
.legal__section .body + .body { margin-top: 1rem; }
.legal__section strong { color: var(--text); font-weight: 600; }

.link-inline {
  color: var(--accent);
  text-underline-offset: 3px;
}
.legal__list {
  display: grid; gap: .7rem;
  margin-top: 1rem; padding-left: 1.15rem;
  list-style: disc;
  color: var(--text-muted);
}
.legal__list::marker, .legal__list li::marker { color: var(--accent); }
.legal__back { margin-top: clamp(2.5rem, 5vw, 3.5rem); }

/* =========================== review markers ===========================
   Two states, because they need different work from different people.
   [data-unverified] means the copy has not been written yet. [data-signoff]
   means product has confirmed the behaviour and the copy is real, but legal
   has not approved it and it has not been matched against the App Store
   privacy label or Play Data Safety entry. Both block launch; only one needs
   a writer. Either way it renders visibly, so nothing ships quietly. */

[data-unverified], [data-signoff] {
  position: relative;
  border-left: 3px solid #B4531F;
  padding-left: 1rem;
}
[data-signoff] { border-left-width: 2px; }

/* The marker is a block label above the text, including inside flex links. */
a[data-unverified], a[data-signoff] {
  flex-direction: column; align-items: flex-start; padding-block: .4rem;
}

[data-unverified]::before { content: "NEEDS VERIFICATION"; }
[data-signoff]::before { content: "AWAITING LEGAL SIGN-OFF"; }
/* The legal pages may be in Indonesian; the review marker follows the page. */
html[lang="id"] [data-unverified]::before { content: "PERLU VERIFIKASI"; }
html[lang="id"] [data-signoff]::before { content: "MENUNGGU PERSETUJUAN LEGAL"; }
[data-unverified]::before, [data-signoff]::before {
  display: block;
  font-size: .625rem; font-weight: 700; letter-spacing: .14em;
  color: #B4531F; margin-bottom: .35rem;
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) :is([data-unverified], [data-signoff]) { border-left-color: #E8A06A; }
  :root:not([data-theme="light"]) :is([data-unverified], [data-signoff])::before { color: #E8A06A; }
}
:root[data-theme="dark"] :is([data-unverified], [data-signoff]) { border-left-color: #E8A06A; }
:root[data-theme="dark"] :is([data-unverified], [data-signoff])::before { color: #E8A06A; }

/* =========================== motion ===================================
   MOTION_INTENSITY 3: entrance settle only, plus the one motivated
   animation (the breathing orb). Everything collapses under reduce. */

@media (prefers-reduced-motion: no-preference) {
}

@media (prefers-reduced-motion: reduce) {
  .soul-field circle, .soul-field__ring { animation: none !important; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
}

@media print {
  .nav, .theme-toggle, .qr { display: none; }
}
