/* tokens.css — the single source of truth for design values.
 *
 * Every value here is law from DESIGN.md. Component CSS references tokens;
 * it never restates a value. If a value you need is missing, add it here
 * first (and to DESIGN.md), then use it.
 */

@import url("fonts.css"); /* Nunito + Assistant, self-hosted in static/fonts (no network needed) */

:root {
  /* --- Color: ink ------------------------------------------------------ */
  --ink:           #231D19;   /* near-black, warm — never #000 */
  --ink-2:         #6E645C;
  --ink-3:         #766C64;
  --ink-inverse:   #FBF7F3;
  --ink-quote:     #3B322C;

  /* --- Color: surface -------------------------------------------------- */
  --ground:        #F6F2ED;
  --ground-wide:   #EDE5DA;
  --ground-glow:   #F4EDE3;
  --surface:       #FFFFFF;
  --sunk:          #F0EAE3;
  --line:          #EAE1D8;
  --line-2:        #DDD2C6;

  /* --- Color: accent (one, used sparingly) ----------------------------- */
  --accent:        #B84A5B;
  --accent-press:  #9C3A4B;
  --accent-quiet:  #FBEDEF;
  --accent-ink:    #FFFFFF;
  --accent-text:   var(--accent);   /* the accent as WORDS — a link, a count, a name. Its own token because in the dark the
                                       fill stays the brand rose under white, and words on a dark ground need a lighter one */

  /* --- Color: confirmation --------------------------------------------- */
  --good:          #3D7A57;
  --good-quiet:    #EAF4EE;
  --good-ink:      #255239;
  --good-ink-2:    #3E6B51;
  --good-line:     rgba(61, 122, 87, .16);

  /* --- Color: error (tested: 7.0:1 on white, 6.3:1 on ground) ---------- */
  --bad:           #A9271E;
  --bad-quiet:     #FBECEA;
  --bad-ink:       #7A1F1A;
  --bad-line:      rgba(169, 39, 30, .18);

  /* --- Color: translucent utilities ----------------------------------- */
  --shadow-ink:    74, 52, 40;                 /* rgb triplet; used as rgba(var(--shadow-ink), a) */
  --white-14:      rgba(255, 255, 255, .14);
  --white-24:      rgba(255, 255, 255, .24);
  --white-26:      rgba(255, 255, 255, .26);
  --white-94:      rgba(255, 255, 255, .94);
  --ground-0:      rgba(246, 242, 237, 0);
  --ground-78:     rgba(246, 242, 237, .78);   /* the middle of a fade from nothing to ground */
  --scrim:         rgba(35, 29, 25, .38);   /* behind a sheet; ink-derived, warm */
  --frame-ring:    0 0 0 1px rgba(74, 52, 40, .07), 0 0 44px rgba(74, 52, 40, .08);
  --photo-fill-dim: rgba(35, 29, 25, .18);
  --dot-off:       rgba(35, 29, 25, .2);   /* a page dot not on screen; ink-derived */
  --plate:         var(--ink);   /* a dark plate that floats over the page and carries --ink-inverse words: the undo pill,
                                    a toast, the pressed half of a segmented control. Dark in both themes. */
  --night:         var(--ink);   /* the ground behind a photo opened full-screen. Dark in both themes. */
  --flag-ground:   var(--white-94);   /* a small flag laid on a photo, carrying --ink words */
  --knob:          var(--surface);   /* a switch's knob, the dot in a ticked ring: light in both themes */
  --paper:         #FFFFFF;   /* the white a QR code is printed on: a scanner needs dark on light, in both themes */
  --bad-fill:      var(--bad);   /* the error red as a FILL under white words (a Delete button, the "!" mark) */

  /* --- Type: family ---------------------------------------------------- */
  --font-latin:    "Nunito", "Avenir Next", "Segoe UI", sans-serif;
  --font-hebrew:   "Assistant", "Arial Hebrew", "Noto Sans Hebrew", sans-serif;
  --font-mono:     "SF Mono", "Menlo", monospace;
  --font:          var(--font-latin);

  /* --- Type: scale (Latin) --------------------------------------------- */
  --text-hero:     44px;   /* one number that answers a question (admin analytics) */
  --text-display:  30px;
  --text-title:    28px;
  --text-title-sm: 26px;
  --text-heading:  19px;
  --text-subhead:  17px;
  --text-body:     16px;
  --text-body-sm:  15px;
  --text-small:    14px;
  --text-caption:  13px;
  --text-micro:    12px;

  /* --- Type: per-script scale (multiply display/title steps) ----------- */
  --script-display-scale: 1;
  --script-body-scale:    1;
  --hebrew-display-scale: .94;
  --hebrew-body-scale:    1;

  /* --- Type: weight / rhythm ------------------------------------------- */
  --weight-regular: 500;
  --weight-medium:  600;
  --weight-bold:    700;
  --weight-heavy:   800;
  --leading-display: 1.16;
  --leading-title:   1.14;
  --leading-tight:   1.10;
  --leading-snug:    1.30;
  --leading-normal:  1.45;
  --leading-loose:   1.55;
  --leading-airy:    1.60;
  --tracking-display: -.024em;
  --tracking-title:   -.022em;
  --tracking-heading: -.012em;
  --tracking-subhead: -.008em;
  --tracking-normal:  0;

  /* --- Space (4px grid) ------------------------------------------------ */
  --s1:  4px;
  --s2:  8px;
  --s3:  12px;
  --s4:  16px;
  --s5:  20px;
  --s6:  24px;
  --s8:  32px;
  --s10: 40px;
  --s12: 48px;
  --s16: 64px;
  --gutter: var(--s5);

  /* --- Radii ----------------------------------------------------------- */
  --r-card:  24px;
  --r-in:    16px;
  --r-btn:   16px;
  --r-focus: 6px;
  --r-rung:  3px;
  --r-pill:  999px;

  /* --- Lines ----------------------------------------------------------- */
  --line-w:        1px;
  --line-w-strong: 1.5px;
  --line-w-mark:   2px;

  /* --- Shadow (three warm layers) -------------------------------------- */
  --lift-1:  0 1px 1px rgba(var(--shadow-ink), .05), 0 2px 4px rgba(var(--shadow-ink), .04);
  --lift-2:  0 1px 1px rgba(var(--shadow-ink), .05), 0 4px 10px rgba(var(--shadow-ink), .05), 0 10px 22px rgba(var(--shadow-ink), .05);
  --lift-3:  0 2px 3px rgba(var(--shadow-ink), .06), 0 8px 18px rgba(var(--shadow-ink), .06), 0 20px 42px rgba(var(--shadow-ink), .07);
  --press-1: 0 1px 1px rgba(var(--shadow-ink), .06);

  /* --- Motion: curves -------------------------------------------------- */
  --spring:      cubic-bezier(.34, 1.42, .5, 1);
  --spring-soft: cubic-bezier(.32, 1.16, .5, 1);
  --out:         cubic-bezier(.4, 0, .7, .35);
  --sweep:       cubic-bezier(.5, 0, .2, 1);
  --ease:        ease;

  /* --- Motion: durations ----------------------------------------------- */
  --d-none:    1ms;
  --d-press:   120ms;
  --d-quick:   180ms;
  --d-base:    260ms;
  --d-slow:    340ms;
  --d-pop:     420ms;
  --d-arm:     520ms;
  --d-stagger: 70ms;
  --d-tick:    1s;
  --d-breathe: 4.6s;
  --d-clock:   5.2s;

  /* --- Motion: press compression --------------------------------------- */
  --press-scale:       .955;
  --press-scale-plate: .965;
  --press-scale-chip:  .94;

  /* --- Motion: choreography distances ---------------------------------- */
  --enter-y:      14px;
  --enter-scale:  .985;
  --card-in-y:    30px;
  --card-back-y:  -34px;
  --card-scale:   .93;
  --pill-in-y:    24px;
  --pill-in-scale: .9;
  --ghost-scale:  .94;
  --ghost-y:      -10px;
  --ghost-opacity: .7;

  /* --- Interaction ----------------------------------------------------- */
  --tap-min:      44px;
  --control-sm:   40px;
  --control-md:   52px;
  --control-lg:   56px;
  --focus-w:      3px;
  --focus-offset: 3px;
  --focus-color:  var(--accent);

  /* --- Component measures ---------------------------------------------- */
  /* A note thread reads like a chat: its own scroll box, opened at the newest
     (owner, 7 Sep 2026). Tall enough to hold a real exchange, short enough that the
     composer under it stays on screen. */
  --notes-max: min(48vh, 420px);
  /* A typing box (owner ruling, 13 Sep 2026): one line to start, grows with the text,
     scrolls past the cap. A message caps at six lines; anything longer-form at twelve
     lines or 40% of the screen, whichever is less. static/css/compose.css applies them. */
  --compose-min:  var(--tap-min);
  --compose-max:  calc(6 * var(--text-body) * var(--leading-normal) + 2 * var(--s3) + 2 * var(--line-w));
  --textarea-max: min(40vh, calc(12 * var(--text-body) * var(--leading-normal) + 2 * var(--s3) + 2 * var(--line-w)));
  --icon-sm:   12px;
  --icon-md:   19px;
  --icon-lg:   20px;
  --icon-xl:   24px;
  --mark:      22px;    /* radio ring, tick circle, countdown ring */
  --mark-dot:  9px;
  --dot:       7px;     /* the accent dot */
  --dot-size:  var(--s2);   /* a page dot under today's people */
  --dot-slot:  var(--s4);   /* the room each page dot takes */
  --dot-mid:   .72;         /* the second dot in from an edge with more beyond it */
  --dot-far:   .45;         /* the edge dot with more beyond it */
  --rung-h:    5px;
  --rung-gap:  5px;
  --plate-min: 104px;
  --list-inset: 52px;   /* hairline start under a row's marker */
  --clock:     104px;
  --clock-halo: 10px;
  --dock-fade: 26px;
  --ghost-h:   220px;
  --chart-h:   128px;   /* a crafted bar chart's plotting height */
  --face-strip: 4;      /* faces shown before "+N" on a drillable count */

  /* --- Photo policy ---------------------------------------------------- */
  --photo-ratio-card: 5 / 4;
  --photo-ratio-tile: 4 / 5;
  --photo-fill-scale: 1.5;
  --photo-fill-blur:  24px;
  --crop-zoom-min:    1;
  --crop-zoom-max:    3;
  --avatar-xxs: 18px;   /* calendar day clusters only — never the sole photo of a person */
  --avatar-xs: 24px;
  --avatar-sm: 32px;
  --avatar-md: 40px;
  --avatar-lg: 56px;
  --avatar-xl: 72px;

  /* --- Motion: choreography amounts ------------------------------------ */
  --card-out-x:    64px;
  --card-out-rot:  5deg;
  --card-out-y:    40px;
  --card-lift-y:   8px;
  --card-lift-scale: 1.015;
  --bump-scale:    1.34;
  --chip-pop-scale: 1.09;
  --arm-scale:     1.045;
  --arm-settle:    .992;
  --halo-min:      .92;
  --halo-max:      1.04;
  --halo-opacity:  .55;
  --muted-opacity: .62;
  --skeleton-min:  .55;

  /* --- Icon strokes ---------------------------------------------------- */
  --stroke-icon:    3px;
  --stroke-icon-lg: 3.2px;
  --stroke-chevron: 2.6px;
  --stroke-ring:    3px;
  --hand-w:   4px;
  --hand-h:   27px;
  --hand-m-w: 3px;
  --hand-m-h: 38px;
  --hub:      8px;
  --pip-w:    2px;
  --pip-h:    7px;
  --pip-top:  9px;

  /* --- Layout ---------------------------------------------------------- */
  --viewport:    390px;
  --content-max: 440px;
  --legal-measure: 62ch;   /* long-form reading (the legal pages): comfortable measure, centered on wide screens */
  --bp-wide:     520px;
  --z-dock:      4;
  --z-overlay:   10;
  --z-toast:     20;
  --z-reach:     30;    /* the offline / can't-reach-us screen: above everything, in every world */
  --getapp-w:    360px;   /* the App Store invitation card on a computer (static/js/getapp.js) */
  --getapp-icon: 48px;    /* the app's icon on that card */
  --getapp-qr:   148px;   /* its QR code — scannable from arm's length off a laptop screen */

  /* --- Layout: the shadchan's desk (professional two-pane, DESIGN §11.1) */
  --bp-desk:     900px;   /* at and above: list rail + detail pane */
  --desk-rail:   408px;   /* the list rail's inline size on the wide desk */
  --tile-min:    88px;    /* a stage-board tile's minimum inline size */
  --tab-max:     720px;   /* a full-width desk tab's content column on the wide desk */
  --bub-max:     520px;   /* one bubble's cap — with 88% it holds on a phone and stops a desk bubble spanning the room */
  --cal-cell-w:  46px;    /* a month-grid day cell — identical on every width (owner decision, 2 Sep 2026) */
  --cal-cell-h:  72px;    /* day number + two avatar rows (a duo, then a duo or "+N") */

  /* --- The onboarding stage (pages/onboarding, DESIGN §8.9) ---------------- */
  --ob-card-w:    232px;  /* the suggestion card, held in one hand above the words */
  --ob-card-min:  184px;  /* never narrower than this, whatever the height */
  --ob-who-h:     68px;   /* the card's name block, for the height-aware size */
  --ob-words-h:   208px;  /* the words strip under the stage: kicker, two-line statement, three-line lede */
  --ob-fan-1:     -5deg;  /* the deck fanned behind the card: "a few" */
  --ob-fan-2:     4deg;
  --ob-fan-x:     14px;
  --ob-fan-y:     10px;
  --ob-drag:      28px;   /* how far the stage leans with a swipe at the half-way point */
  --ob-meet-w:    32px;   /* a connector between two people on the meet row */
  --ob-av-big:    96px;   /* the shadchan on the meet row — the one avatar above --avatar-xl */
  --ob-away-scale: .24;   /* the card folding into her avatar */
  --ob-veil-blur: 14px;   /* the frosted photo on "you can't be found" */
  --ob-photo-strip: 44cqw; /* the photo frame once the stamp has unfolded: a strip, the face still centred */

  /* --- The landing (pages/landing, DESIGN §8.10): two compositions of one page ----- */
  --text-hero-lg:  52px;   /* the desktop hero's one statement (--text-hero is the phone's) */
  --leading-hero:  1.08;
  --rings:         28px;   /* the wordmark at small size: the rings alone, one colour */
  --r-stage:       32px;   /* the desktop stage plate — rounder than the card that sits on it */
  --ld-max:        1200px; /* the desktop page's content column */
  --ld-card-w:     288px;  /* the live card on the phone, dealt from the deck */
  --ld-card-w-lg:  320px;  /* the live card staged on the desktop plate */
  --ld-stage-w:    528px;  /* the desktop stage plate */
  --ld-stage-h:    616px;
  --ld-you-w:      248px;  /* your own card, frosted, beside the promises */
  --ld-you-rot:    -4deg;  /* it leans, a little, the way a card set down does */
  --ld-photo-strip: 56cqw; /* the photo once the stamp has unfolded: shorter by about the stamp, the face still centred */
  --d-live:        8.6s;   /* how long a person lives on the card before the demo decides */
  --d-hold:        1.4s;   /* the stamp is read before the card leaves */
  --d-match:       3.6s;   /* the match is shown — her, the shadchan, you — before the next card */

  /* --- The landing, v2 mock-up (pages/landing-v2): wealthsimple.com's page, copied ----------------- */
  /* Reference: wealthsimple.com (25 Sep 2026). Warm paper; a giant serif list; full-bleed coloured tiles, each
     holding one 3D object or the app on a phone; a big serif statement; a gold medallion; a giant wordmark.
     The 3D objects are built in code (art/scene.js) — no photographs, no generated images. */
  --font-ws-head:   "Hanken Grotesk", "Avenir Next", "Segoe UI", sans-serif;
  --font-ws-serif:  "Source Serif 4", "Iowan Old Style", "Georgia", serif;
  --ws-paper:       #F5F3EF;
  --ws-ink:         #1C1B1B;   /* warm near-black, never #000 */
  --ws-ink-2:       #5C5754;
  --ws-line:        rgba(28, 27, 27, .14);
  --ws-white:       #FCFCFC;
  --ws-white-2:     rgba(252, 252, 252, .78);
  --ws-white-line:  rgba(252, 252, 252, .4);
  /* the tiles: each its own warm, muted ground (Wealthsimple's mauve, taupe, forest and butter, warmed) */
  --ws-night-a:     #2A1B22;   /* the hero: deep plum into wine */
  --ws-night-b:     #5B3242;
  --ws-mauve-a:     #6A5566;
  --ws-mauve-b:     #A6899A;
  --ws-taupe-a:     #564C47;
  --ws-taupe-b:     #8F7E73;
  --ws-forest-a:    #1F3A2B;
  --ws-forest-b:    #4F6E56;
  --ws-butter:      #EEE3B1;
  --ws-blush:       #F2DDD8;
  --ws-glow:        rgba(236, 196, 130, .35);
  --ws-gold:        #D9B071;   /* the hero's kicker and rule, on the dusk scene */
  --ws-gold-2:      #EDBF8A;   /* the hero's second line: candlelight, a shade warmer */
  --ws-shade:       rgba(18, 14, 22, .55);   /* the dark laid over the scene where the words sit */
  --ws-shade-strong: rgba(18, 14, 22, .78);
  --ws-kick-track:  .22em;
  --ws-hero-h:      86svh;    /* the hero, phone: most of the first screen, the next section peeking */
  --ws-hero-h-lg:   min(88svh, 860px);
  --ws-btn:         #FCFCFC;   /* the pill on a dark tile */
  --ws-btn-ink:     #1C1B1B;
  --ws-btn-dark:    #1C1B1B;   /* the pill on paper */
  --ws-max:         1240px;
  --ws-h1:          44px;      /* phone */
  --ws-h1-lg:       72px;
  --ws-list:        52px;      /* the giant serif list */
  --ws-list-lg:     104px;
  --ws-tile-h:      30px;
  --ws-tile-h-lg:   44px;
  --ws-state:       40px;      /* the big serif statement */
  --ws-state-lg:    96px;
  --ws-word:        21px;
  --ws-word-lg:     28px;
  --ws-body:        17px;
  --ws-small:       14px;
  --ws-leading-head: 1.12;
  --ws-tile-min:    560px;     /* a tile, phone */
  --ws-tile-min-lg: 640px;
  --ws-art:         300px;     /* a 3D object in a tile, phone */
  --ws-art-lg:      480px;
  --ws-hero-art:    340px;
  --ws-hero-art-lg: 620px;
  --ws-arrow:       48px;      /* the circle arrow on each tile */
  --ws-card-r:      24px;
  --ws-band:        72px;
  --ws-band-lg:     128px;
  /* the phone the app sits in */
  --ws-phone-w:     260px;
  --ws-phone-w-lg:  300px;
  --ws-phone-r:     44px;
  --ws-bezel:       9px;
  --ws-phone-edge:  #1C1B1B;
  --ws-screen:      #F6F2ED;   /* the member app's own ground (--ground) */
  /* the 3D objects' colours (art/scene.js reads these) */
  --3d-gold:        #E2B872;
  --3d-blush:       #EBC3BE;
  --3d-cream:       #F1E6D6;
  --3d-rose:        #B84A5B;   /* the accent, as wax */
  /* the viewing room (pages/landing-v2/preview.html): the two screens the owner judges on */
  --pv-phone-w:     390px;
  --pv-phone-h:     844px;
  --pv-desk-w:      1440px;
  --pv-desk-h:      900px;
  --pv-bezel:       11px;
  --pv-phone-r:     64px;
  --pv-edge:        #2A2420;
  --pv-rim:         #8C837C;
}

/* --- Dark (DESIGN.md §12; owner, 2 October 2026) -------------------------
 * THE PERSON DECIDES: everybody is in the light until they pick "Dark mode" in the menu (static/js/theme.js sets
 * data-theme="dark" on <html>; the phone's own setting is not read). The same warm palette at night — a
 * brown-black ground, never #000; cards one step LIGHTER than the ground (in the dark, nearer is lighter); "sunk"
 * is a soft fill lighter than both, because a darker well would vanish. The rose stays the brand rose where it is
 * a FILL under white words; where it is words on the ground it is --accent-text, lighter, so it still reads.
 * Shadows go to true black and heavier, since a warm 5% shadow is invisible on a dark ground. Photos are left
 * exactly as they are. Every pair below was measured: body ink 15:1, secondary 8:1, tertiary 5.3:1 on a card,
 * accent words 7:1, white on the accent fill 4.6:1, the fill against the ground 3.9:1. */
:root { color-scheme: light; }
:root[data-theme="dark"] {
  color-scheme: dark;
  --ink:           #F4EDE6;
  --ink-2:         #B9ADA3;
  --ink-3:         #9C9087;
  --ink-inverse:   #FBF7F3;   /* unchanged on purpose: it only ever sits on a dark plate */
  --ink-quote:     #DDD3CA;

  --ground:        #181513;
  --ground-wide:   #0F0D0C;
  --ground-glow:   #201B18;
  --surface:       #231F1C;
  --sunk:          #2E2925;
  --line:          #38312C;
  --line-2:        #52483F;

  --accent:        #C24E60;
  --accent-press:  #A94053;
  --accent-quiet:  #3A2228;
  --accent-text:   #EC8496;

  --good:          #478C66;
  --good-quiet:    #1D2B23;
  --good-ink:      #B4DBC2;
  --good-ink-2:    #93C4A5;
  --good-line:     rgba(111, 184, 140, .24);

  --bad:           #E0685C;
  --bad-quiet:     #3A1E1B;
  --bad-ink:       #F6B8B0;
  --bad-line:      rgba(224, 104, 92, .32);

  --shadow-ink:    0, 0, 0;
  --ground-0:      rgba(24, 21, 19, 0);
  --ground-78:     rgba(24, 21, 19, .78);
  --scrim:         rgba(0, 0, 0, .62);
  --frame-ring:    0 0 0 1px rgba(255, 244, 232, .06), 0 0 44px rgba(0, 0, 0, .5);
  --photo-fill-dim: rgba(0, 0, 0, .28);
  --dot-off:       rgba(244, 237, 230, .26);
  --plate:         #3A332E;
  --night:         #0C0A09;
  --flag-ground:   rgba(24, 21, 19, .84);
  --knob:          #F4EDE6;
  --bad-fill:      #C9463A;

  --lift-1:  0 1px 1px rgba(0, 0, 0, .28), 0 2px 4px rgba(0, 0, 0, .22);
  --lift-2:  0 1px 1px rgba(0, 0, 0, .30), 0 4px 10px rgba(0, 0, 0, .28), 0 10px 22px rgba(0, 0, 0, .26);
  --lift-3:  0 2px 3px rgba(0, 0, 0, .34), 0 8px 18px rgba(0, 0, 0, .34), 0 20px 42px rgba(0, 0, 0, .40);
  --press-1: 0 1px 1px rgba(0, 0, 0, .30);
}

/* --- Script-aware resolution ------------------------------------------ */
:lang(he) {
  --font: var(--font-hebrew);
  --font-ws-head: var(--font-hebrew);
  --font-ws-serif: "Frank Ruhl Libre", "Arial Hebrew", serif;
  --script-display-scale: var(--hebrew-display-scale);
  --script-body-scale:    var(--hebrew-body-scale);
  --weight-heavy: 700;
  --tracking-display: 0;
  --tracking-title:   0;
  --tracking-heading: 0;
  --tracking-subhead: 0;
  --leading-display: 1.21;
  --leading-title:   1.19;
  --leading-tight:   1.15;
}

/* --- Reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  :root {
    --d-press: var(--d-none);
    --d-quick: var(--d-none);
    --d-base:  var(--d-none);
    --d-slow:  var(--d-none);
    --d-pop:   var(--d-none);
    --d-arm:   var(--d-none);
    --d-stagger: 0ms;
    --d-breathe: var(--d-none);
    --d-clock:   var(--d-none);
    --d-live:    var(--d-none);
    --d-hold:    var(--d-none);
    --d-match:   var(--d-none);
  }
}
