/* ============================================================
   PREVOW — token layer  ·  v2.0
   Authority: UI & Brand Kit v1.0 + Logo Standards v2.0, Aug 2026.
   Rationale for every web-only value: docs/design-kit-web.md

   This is the only :root in the codebase. Every page loads it first and
   prevow.css / direction-1.css consume it — do not redeclare tokens below.
   ============================================================ */

/* WOFF2, not TTF. Same outlines, Brotli-compressed: 185.7 KB -> 66.7 KB for the
   three weights. Regenerate with scripts/build-fonts.py. */
@font-face{
  font-family:"Plus Jakarta Sans";
  src:url("../assets/fonts/plus-jakarta-sans-500.woff2") format("woff2");
  font-style:normal;
  font-weight:500;
  font-display:swap;
}
@font-face{
  font-family:"Plus Jakarta Sans";
  src:url("../assets/fonts/plus-jakarta-sans-700.woff2") format("woff2");
  font-style:normal;
  font-weight:700;
  font-display:swap;
}
@font-face{
  font-family:"Plus Jakarta Sans";
  src:url("../assets/fonts/plus-jakarta-sans-800.woff2") format("woff2");
  font-style:normal;
  font-weight:800;
  font-display:swap;
}

/* Fraunces — the display voice. Variable: wght 100-900, opsz 9-144, plus the
   SOFT and WONK character axes.

   DEVIATION FROM BRAND RULE §5, recorded rather than slipped in. The rule says
   "Plus Jakarta Sans only". Jakarta at 800 with -0.03em tracking is a geometric
   sans doing a display job, and that combination is precisely the house style
   of every generated startup page — the founder's objection to the current
   build is, in visual terms, an objection to this typeface in this role.

   Jakarta is not removed. It keeps everything functional: body, labels,
   buttons, form controls, navigation, metadata. What moves to Fraunces is
   display only — the lines that carry composition rather than information.
   That split is the pairing the brief asked to be researched, and it preserves
   what rule §5 was protecting (one functional voice, self-hosted, present
   offline) while giving the page a register a sans cannot reach.

   SOFT 40 takes the edge off the terminals so it reads warm rather than
   institutional; WONK 1 lets the italicised-form quirks through on the round
   letters. Both are why this is Fraunces and not Playfair — the wedding-serif
   cliché the search surfaced first. Self-hosted per §5's real requirement. */
@font-face{
  font-family:"Fraunces";
  src:url("../assets/fonts/fraunces-var.woff2") format("woff2-variations");
  font-style:normal;
  font-weight:100 900;
  font-display:swap;
}

:root{

  /* ---- brand: five colours, no sixth ---- */
  --ink:        #0B1F3A;   /* primary text · primary button · closed  */
  --teal:       #81D8D0;   /* NOW. the live thing. never decoration   */
  --blush:      #EDCDC2;   /* partner two · kept things               */
  --cloud:      #F0EEE9;   /* nav · placeholder · locked              */
  --white:      #FFFFFF;   /* page ground                             */

  /* ---- derived. do not invent more ---- */
  --muted:      #5A6B80;   /* on white / cloud / teal-pale ONLY       */
  --on-teal:    #1B4A44;   /* on teal or blush ONLY                   */
  --on-navy:    #9FB2C4;   /* on ink                                  */
  --teal-pale:  #EDF7F5;
  --line:       #E4E9EE;
  /* #8292A5 measures 3.18:1 on white — it is a RULE and ICON colour, and a
     scrollbar thumb. It is not a text colour at body or label size; --muted
     (5.46:1) is. Several small-text uses were moved off it in Aug 2026. */
  --chevron:    #8292A5;

  /* TRAPS — enforced in scripts/check.py, repeated here for whoever
     is reading the stylesheet rather than the docs:
       muted on teal  = 3.29  FAIL      muted on blush = 3.67  FAIL
       white on teal  = 1.66  FAIL      white sits only on ink.
     The symbol is INK on every light ground. Teal fill only when
     reversed on ink — the new palette has no light accent that
     clears contrast, which is why the mark stopped being coloured. */

  /* ---- type: two families with a clean split of duties ---- */
  --font: "Plus Jakarta Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Georgia is the fallback rather than a generic `serif` because it is metrically
     closest of the faces present on both Windows and macOS — the reflow when
     Fraunces swaps in is a nudge rather than a jump. */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --w-body: 500;
  --w-bold: 700;
  --w-display: 800;   /* the mark, the wordmark, numerals — things that anchor */

  /* Fraunces optical + character axes. Display type sits at the large optical
     size where the face is at its most contrasted; the small-label setting
     pulls opsz down so the same family does not go spindly at 13px. */
  --fv-display: "opsz" 96, "SOFT" 40, "WONK" 1;
  --fv-quiet:   "opsz" 20, "SOFT" 50, "WONK" 0;
  /* 380–480, never bold. Not an invention: this is the exact band ratified in
     docs/decisions/004-direction-v1.3-typography.md, where Fraunces was the
     founder-locked display face before the August kit collapsed the system to
     one family. Reintroducing the face at a weight the founder did not ratify
     would be the actual liberty — so the range comes back with it. */
  --w-editorial: 380;
  --w-editorial-mid: 460;

  /* Headlines are --w-display, per kit §3 and brand rule §5: "display lines use
     800 with tight negative tracking".

     This token briefly held 500, measured off tiffany.com, where display
     headings run 32px at weight 325–500. That was a misreading of the
     direction: the founder asked for the site to FEEL like tiffany.com, and
     what got shipped instead was their type metrics. Light, small, centred
     display type is a jeweller's signature — copying it made Prevow read as
     someone else's brand. The learning worth keeping from that reference is
     space and restraint, both of which the kit already asks for; the register
     is ours. */
  --w-headline: var(--w-display);

  /* steps at or below 26px are the kit's, unchanged.
     only the display end is new — see design-kit-web.md §3 */
  /* The display end is re-cut for the serif. Fraunces at 300 has a much lower
     visual weight than Jakarta at 800, so the same physical size reads smaller
     and quieter — it has to grow to hold the same authority. The craft floor
     caps display at 6rem/96px; --t-hero lands under that at 88px.
     Steps at or below 26px are the kit's, unchanged. */
  /* POSTER. A step above the hero, for the handful of phrases that are
     meant to BE the composition rather than head one. Derived from the
     reference comparison: Mate Libre routinely lets a display phrase take
     about a third of the viewport, while Prevow was sitting near 15% and
     reading as a document. Three lines at this step come to roughly 38%
     of a 900px viewport.
     Use sparingly — if everything is a poster, nothing is. */
  --t-poster: clamp(3rem, 1.5rem + 7vw, 7.5rem);   /* 48 -> 120 */
  --t-hero:    clamp(2.75rem,  1.4rem  + 5.4vw, 5.5rem);  /* 44 → 88 */
  --t-display: clamp(2.125rem, 1.35rem + 3.1vw, 4rem);    /* 34 → 64 */
  --t-title:   clamp(1.75rem,  1.35rem + 1.6vw, 2.75rem); /* 28 → 44 */
  --t-card:    1.3125rem;   /* 21   */
  --t-section: 1.125rem;    /* 18   */
  --t-body:    1.0625rem;   /* 17 — web only, optical. §3 */
  --t-row:     0.9375rem;   /* 15   */
  --t-small:   0.84375rem;  /* 13.5 */
  --t-meta:    0.78125rem;  /* 12.5 */
  --t-label:   0.6875rem;   /* 11 — the only uppercase on the site */

  /* An editorial serif set large wants a slightly WIDER measure of leading than
     a geometric sans did at the same size — the ascenders and descenders are
     longer, so 1.02 (what the sans used) collides. */
  --lh-display: 1.15;
  --lh-editorial: 1.04;
  --lh-body:    1.7;
  --lh-ui:      1.35;

  /* Display tracking goes to ~0. Negative tracking is a sans-serif correction:
     applied to a high-contrast serif it closes the counters and turns the
     thing into a blob. The craft floor puts the floor at -0.04em; a serif at
     72px wants the opposite end of that range. */
  --tr-display: -0.005em;
  --tr-section: -0.02em;
  --tr-row:     -0.015em;
  --tr-label:    0.12em;

  /* The seam — the page's structural motif. One hairline, one colour, one
     width, used as a division everywhere a division means something. */
  --seam: 1px;
  --seam-ink: var(--line);

  /* ---- geometry: three radii, no fourth ---- */
  --r-block: 20px;
  --r-pill:  100px;
  --r-chip:  12px;

  /* The device frame is a picture of hardware, not a Prevow surface, so its
     corners are the phone's radius and not one of the three above. Law 4
     governs our own blocks, pills and icon chips; the kit already accepts
     representational shapes outside that scale — its avatars are circles.

     An iPhone is ~393pt wide with a ~55pt corner. At our 392px frame that is
     52px on the chassis and 46px on the screen inside a 6px bezel, which keeps
     the two curves concentric. At 20px it read as a generic Android slab. */
  --r-device:        52px;
  --r-device-screen: 46px;

  /* ---- spacing: everything on the kit's 8px grid ----
     The step name is the multiplier: --s-N is N × 8px.

     --s-5 was missing while eleven rules across home.css referenced
     var(--s-5) — in the drawer, the hero padding, the footer and the marquee
     among them. An undefined custom property resolves to nothing, so each of
     those silently fell back to the property's initial value: 0 for the gaps
     and margins, which is why the nav links sat flush against each other.
     Nothing errors and nothing logs, so it survived. 40px by the same rule
     that gives every other step its value. */
  --s-1:  8px;   --s-2: 16px;  --s-3: 24px;  --s-4:  32px;
  --s-5: 40px;   --s-6: 48px;  --s-8: 64px;  --s-12: 96px; --s-16: 128px;

  /* Three section rhythms. Replaces 18 hand-tuned paddings.
     Widened at the loose end because brand rule 2 asks for it outright:
     "preserve meaningful empty space around photographs and type". The space
     is the part of the reference worth keeping — the type went back to the
     kit, this did not. Every section previously sat at exactly 128px top and
     bottom, which is what made the page feel templated rather than composed.
     --sec-loose is now the breathing room, --sec-air is the moment where a
     section is allowed to be almost entirely empty. */
  --sec-tight: clamp(3rem, 6vw,  4rem);      /* 48 → 64  */
  --sec:       clamp(4rem, 8vw,  6rem);      /* 64 → 96  */
  --sec-loose: clamp(6rem, 11vw, 10rem);     /* 96 → 160 */
  --sec-air:   clamp(7.5rem, 15vw, 14rem);   /* 120 → 224 */

  /* Four widths, not one. "Do not give every section the same max-width" is a
     composition requirement, and it needs tokens or it becomes eleven
     hand-tuned numbers. --page is the default; --page-wide is for compositions
     that should push toward the edges; --page-narrow is the reading measure
     for a single column of prose; --page-tight is the isolated kept-line. */
  --page:        1200px;
  --page-wide:   1560px;
  --page-narrow:  720px;
  --page-tight:   560px;
  --gutter: clamp(var(--s-3), 4.5vw, var(--s-6));

  /* ============================================================
     MOTION SYSTEM
     Five timing categories, four curves. The rule is that a duration
     and a curve are chosen by WHAT IS MOVING, never by habit — a
     control under a finger and a photograph crossing the viewport do
     not share a clock.

     Category      Duration   Used for
     ----------------------------------------------------------------
     micro         140ms      cursor-local feedback: arrows, marks
     quick         240ms      one control changing state
     base          420ms      a block resolving, colour and value
     cinematic     760ms      a composition rearranging itself
     reveal       1100ms      type clearing a mask, a rule drawing
     ============================================================ */
  --dur-micro:     140ms;
  --dur-quick:     240ms;
  --dur-base:      420ms;
  --dur-cinematic: 760ms;
  --dur-reveal:   1100ms;
  /* kept: older rules still name --dur-slow */
  --dur-slow: var(--dur-cinematic);

  /* ---- four curves, each with one job ----
     --ease        soft arrival. Exponential out: fast commit, long settle.
                   Anything entering the page.
     --ease-exit   decisive departure. Accelerates away — an exit that
                   eases out looks like it changed its mind.
     --ease-seam   even growth. A rule drawn down a page must not
                   overshoot and settle the way a card does.
     --ease-paper  weighted arrival with a trace of inertia, for surfaces
                   that are meant to read as physical. Controlled, never
                   bouncy — this is paper being set down, not a spring. */
  /* Softened Aug 2026. This was cubic-bezier(.16,1,.3,1) — an expo-out, whose
     control point at (.16,1) means the value is essentially AT its target
     within the first sixth of the duration and then hangs. That reads as a
     snap followed by a wait, which is the "hard" quality being reported. The
     curve below keeps a decisive arrival but spends its time accelerating and
     decelerating instead of spiking. */
  --ease:       cubic-bezier(.28,.72,.26,1);
  /* was (.7,0,.84,0), an expo-in that leaves almost vertically */
  --ease-exit:  cubic-bezier(.55,0,.78,.24);
  --ease-seam:  cubic-bezier(.65,.05,.36,1);
  --ease-paper: cubic-bezier(.22,1.04,.36,1);
  /* --ease-write  words being set down left to right. Was an inline literal
     in route.css; named here so no page invents its own. */
  --ease-write: cubic-bezier(.28,.1,.2,1);

  /* ---- travel distance ----
     Scaled to the thing moving, against the AI habit of translating
     everything 20px upward. A label does not travel at all. */
  --travel-micro:  4px;
  --travel-ui:    12px;
  --travel-block: 28px;
  --travel-scene: 72px;

  /* travel distance carries hierarchy — labels do not move at all */
  --rise-display: 24px;
  --rise-block:   16px;
  --rise-body:     8px;

  /* Parallax depths. Photography always travels SLOWER than the type in front
     of it — that difference is what reads as depth rather than as drift. */
  --par-photo: 12%;
  --par-type:   0%;

  /* the Vowbook turn, per the kit: a SOLID overlay, never a gradient */
  --turn-shade: rgba(11,31,58,.13);

  /* Type over photography. Kit §10 lists photography as UNDECIDED and says
     decide it, then add it to the kit — so this is that decision, written
     down rather than improvised per-section.

     A SOLID ink veil, never a gradient (law 3). The alpha is not taste: it is
     the measured minimum that lets white text clear 4.5:1 against the WORST
     pixel of the actual photograph, inside the region the type occupies.

     Re-derived when the statement photographs went full bleed with the words
     on them. Solved per photograph, per width, worst pixel under the text:

                        320    390    768   1280   1920
       hero            0.58   0.58   0.58   0.58   0.58
       chapter-one     0.58   0.58   0.58   0.54   0.54
       vowbook         0.61   0.61   0.61   0.61   0.61  <- binds everywhere

     0.61 at every width, so 0.62 ships with a hair of headroom. The vowbook
     frame binds because it holds a blown highlight — 255,254,254 — inside the
     text region at every crop. Against a pixel that white the alpha is
     effectively the pure-white worst case, which is why it does not move with
     the viewport the way a tiered value would.

     ONE token, not two. The chapter captions had their own --chapter-scrim,
     independently solved to the same 0.62 for the same reason: a near-white
     pixel under white type. Two tokens holding one value drift apart; if the
     chapter photography ever lands with no blown highlights it can earn a
     thinner token of its own, and that is a decision to take then.

     If a lighter photograph is wanted, the lever is a darker-graded source
     asset, not a thinner veil. Re-derive whenever the photography, the crop
     or the type scale changes — and sweep the widths, do not sample one.

     Text on this veil is WHITE, never --on-navy: on-navy is defined above as
     secondary text on navy, and a photograph is not navy. Recession over
     photography is carried by size and weight (kit §9), not by a dimmer ink. */
  --photo-scrim: rgba(11,31,58,.62);
}

/* Forbidden by rule 3, stated so it cannot creep back in:
     no gradients · no shadows · no borders on blocks.
   If a surface needs separation it gets a different solid fill
   from the five, or a 1px --line hairline. Nothing else. */
