/* ============================================================
   PassbackAI design tokens — single source of truth.
   Linked from every HTML entry + the React SPA. Any token used
   on this site must live here.

   THREE LAYERS:
   - :root                    light theme (default values)
   - [data-theme="dark"]      dark theme overrides — applied by the
                              boot script in <head> when the user has
                              picked Dark, or when on System and the
                              OS prefers dark
   - [data-theme="light"]     explicit light pin — beats system

   Components consume only the semantic names. Theme switching is
   a pure data flip; no component code knows which theme is active.
   ============================================================ */

:root {
  color-scheme: light;

  /* ---------- Surfaces (low → high elevation) ---------------
     New code uses --surface-N. Existing references to --bg /
     --bg-sub keep working via aliases below.

     In LIGHT: surfaces stay near-white; elevation expressed via
     shadows + borders.
     In DARK: surfaces lighten as elevation rises (Material rule);
     shadows do almost no visual work on dark canvases. */
  --surface-0: #fbfbfa;          /* recessed/inset (code wells) */
  --surface-1: #ffffff;          /* primary canvas */
  --surface-2: #fbfbfa;          /* slightly raised, hovers */
  --surface-3: #f7f7f6;          /* cards, popovers */
  --surface-4: #ffffff;          /* dialogs, top elevation */

  /* Surface aliases — the existing ~400 references go through these. */
  --bg:        var(--surface-1);
  --bg-sub:    var(--surface-2);

  /* Chip fills — promoted from the SPA shell (index.html keeps an identical
     copy) so static pages stop falling back to --bg-sub, which is invisible
     against a white popover. */
  --chip-bg:       #f1f1ef;
  --chip-bg-hover: #e8e8e6;
  --bg-cream:  #faf8f3;          /* paper-warm; doesn't flip per-theme */

  /* ---------- Ink / text -----------------------------------
     New code prefers --text-primary/secondary/muted/disabled.
     Legacy --ink/--ink-2/--muted aliased on top. Warm-neutral
     in both themes — never pure black, never pure white. */
  --text-primary:     #37352f;
  --text-secondary:   #5c5b57;
  --text-muted:       #6f6e6c;
  --text-disabled:    #b7b3ad;
  --text-on-emphasis: #ffffff;   /* ink on a dark/colored surface */

  --ink:    var(--text-primary);
  --ink-2:  var(--text-secondary);
  --muted:  var(--text-muted);

  /* ---------- Edges (borders, dividers) -------------------- */
  --edge:          #ebebea;
  --edge-strong:   #d9d9d6;
  --edge-subtle:   #f2f2f1;
  --border:        var(--edge);
  --border-strong: var(--edge-strong);
  --border-subtle: var(--edge-subtle);

  /* ---------- Brand accent — yellow highlight --------------
     The one color that's unmistakably this product. Used as
     edge and underline; never as a background for UI chrome.
     Stays warm-yellow in both themes — slightly more saturated
     in dark for stronger 3:1 focus contrast on dark surfaces. */
  --hl-fill:      #fde68a;
  --hl-fill-soft: #fef3c7;
  --hl-edge:      #f59e0b;
  /* AREA wash — table row/column/cell tints, where the highlight covers a
     SLAB of layout, not a span of text. Light: same butter as the soft fill.
     Dark: a low-alpha amber — the near-solid
     dark --hl-fill-soft is documented as "too hot as a full fill", and a
     whole highlighted column in it outshouts everything on the canvas. */
  --hl-wash:      #fef3c7;
  /* [Delete]-labelled area wash — the dusty-red slab variant of the same. */
  --hl-del-wash:  #f7e9e9;
  /* Ink ON the highlight fill. The fill stays butter-yellow in BOTH themes,
     so the text sitting on it must stay dark in both — it must NOT follow
     --ink, which flips to off-white in dark (off-white on yellow ≈ 1.5:1).
     Same literal value in every theme block, on purpose. */
  --text-on-hl:   #37352f;

  /* ---------- Deferred-delete (inline undo) ----------------
     A navigator row armed for deletion. One restrained danger
     signal — the brick-red trash mark — over a near-neutral
     warm wash so the row reads "set apart", not "alarm". The
     draining hairline tracks the mark's hue (NOT the brand
     amber, which is the affirmative accent) — solid so the
     countdown is actually legible against the row. */
  --del-wash: rgba(120, 95, 90, 0.055);
  --del-mark: #b23b34;
  --del-edge: #c0392c;

  /* ---------- Version-diff lens ----------------------------
     Convention coloring: green = added, red = removed. Kept
     editorial — low chroma, pulled toward the warm canvas — so a
     dense RTL paragraph with many marks stays calm. The CSS
     restates the encoding dual-channel (add = underline, del =
     strikethrough), so color only reinforces. Diff-red is a
     deliberate SIBLING of the brand brick --del-mark, not a reuse:
     "armed for deletion" and "word was removed" must not read as
     the same signal. -ink = the gentle word ink, -line = the
     decoration line, -rail = the whole-block spine. */
  --diff-add-ink:  #3f7d52;
  --diff-add-line: #4f9568;
  --diff-add-rail: rgba(63, 125, 82, 0.55);
  --diff-del-ink:  #a8514a;
  --diff-del-line: #b85c54;
  --diff-del-rail: rgba(168, 81, 74, 0.50);

  /* ---------- Sticky-note pastels --------------------------
     Paper fills for in-post callouts (.verdict, .pullquote)
     and the homepage audience cards. Butter is the default;
     blush and sage are editorial variants. NOT flipped per
     theme — paper stays paper. In dark mode the parent gets
     a brightness/contrast filter so they don't read as
     headlights against the near-black canvas. */
  --note-butter: #fff1c6;
  --note-blush:  #ffdcd8;
  --note-sage:   #dae9d0;

  /* ---------- Interactive accent ---------------------------
     The marker yellow. Same --hl-fill the hero uses for the
     .mark band, so every interactive hit on the site carries
     the same brand signal and nothing ever shifts to orange. */
  --link-accent:      var(--hl-fill);
  --link-accent-soft: rgba(253, 230, 138, 0.55);
  /* Focus ring. The brand butter-yellow is ~1.3:1 on a white canvas —
     keyboard focus was effectively invisible in light. amber-700, the
     darker sibling of --hl-edge, keeps the ring in the brand family at
     ~5:1 on white and ≥3:1 on the amber chips it sometimes wraps.
     Dark keeps the bright #fcd34d ring (great on near-black). */
  --ring:             #b45309;
  /* The brand amber doing INK duty (eyebrows, small labels) — darker than
     --hl-edge so it holds AA contrast as text on the light canvas; flips to
     a bright apricot in dark. Components must consume the token, not remix
     their own amber. */
  --accent-deep:      #b35900;

  /* Legacy alias — the old --accent was #2383e2, a generic blue
     that had no relationship to the rest of the palette. */
  --accent: var(--link-accent);

  /* ---------- Shadows --------------------------------------
     In light: standard cool drop-shadows do the elevation work.
     In dark: shadows are weaker but still present; tonal lift
     (lighter surface) does most of the work. */
  --shadow-small:  0 1px 2px rgba(15, 15, 15, 0.06), 0 1px 3px rgba(15, 15, 15, 0.04);
  --shadow-medium: 0 4px 12px rgba(15, 15, 15, 0.08);
  --shadow-large:  0 12px 32px rgba(15, 15, 15, 0.12);

  /* ---------- Scrim ----------------------------------------
     Backdrop behind modal dialogs. Light: a soft ink wash.
     Dark: deeper, since the canvas is already near-black and a
     light wash would do no separating work. */
  --scrim: rgba(15, 15, 15, 0.42);

  /* ---------- Image dimming -------------------------------- */
  --img-filter: none;

  /* ---------- Topbar blur background -----------------------
     Sticky topbar uses backdrop-filter over a translucent fill.
     Light: white-ish. Dark: warm near-black. */
  --topbar-blur: rgba(255, 255, 255, 0.88);

  /* ---------- Typography ----------------------------------- */
  --reading-font: 'Noto Serif', Georgia, 'Times New Roman', serif;
  --ui-font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, Menlo, monospace;

  /* ---------- Editorial scale — ONE system for content pages -----
     The single type + space + grid scale every ☰-menu content page
     (about / manifesto / privacy / connect / blog + posts / for/*)
     composes from. Before this block each page carried its OWN
     <style> and picked its own H1 size (36→52px across six pages),
     column width (640/660/680), and rhythm — so the set read as
     "slightly different everywhere." Now the sizes live here once;
     a page that wants to differ overrides the TOKEN, deliberately,
     never a raw px value inline.

     Scale is a ~1.24 minor-third off an 18px reading body. Headings
     + lede are the reading serif; kicker/byline/callouts the UI sans.
     Mobile shrinks the whole scale by re-declaring these tokens in
     one media query below — every consumer tracks it in lockstep. */
  --fs-display: 3.25rem;     /* 52px — index/landing hero ONLY */
  --fs-h1:      2.75rem;     /* 44px — canonical long-read masthead */
  --fs-h2:      1.6875rem;   /* 27px */
  --fs-h3:      1.3125rem;   /* 21px */
  --fs-lede:    1.3125rem;   /* 21px — the standfirst under every H1 */
  --fs-body:    1.125rem;    /* 18px — reading measure body */
  --fs-ui-sm:   0.9375rem;   /* 15px — byline, tldr, verdict, callouts */
  --fs-kicker:  0.71875rem;  /* 11.5px — the mono margin kicker */

  --lh-display: 1.06;
  --lh-h1:      1.1;
  --lh-h2:      1.25;
  --lh-h3:      1.3;
  --lh-lede:    1.5;
  --lh-body:    1.7;

  --ls-display: -0.022em;
  --ls-h1:      -0.021em;
  --ls-h2:      -0.01em;
  --ls-kicker:   0.14em;

  /* Long-read grid — an ASYMMETRIC two-track editorial grid: a left
     margin RAIL carries the mono kicker (and, page-permitting, section
     marks) while the reading MEASURE holds the prose. Centered as a
     unit, so the text sits anchored right-of-centre with a real spine —
     not a dead-centred blob. The rail is the page's ownable gesture;
     it echoes the app's docked-rail spine without matching it. Below
     --read-collapse the rail folds and the kicker returns above the H1.
     RTL is automatic: the rail is the inline-START track, so it mirrors
     to the right in Hebrew. */
  --measure:        42rem;     /* 672px reading column (~74ch serif) */
  --read-rail:      8.5rem;    /* 136px kicker margin */
  --read-rail-gap:  2.5rem;    /* 40px rail↔text gutter */
  --read-pad-top:   72px;      /* masthead breathing above the kicker */
  --read-pad-bottom:40px;
  --read-collapse:  62rem;     /* below this the rail folds away */

  /* Index/landing grid — the ONE wide grid: blog index, /for/* landing,
     related-reading rails. A centered max-width with a 2-up card field. */
  --wide:      70rem;          /* 1120px index shell */
  --wide-gutter: 20px;         /* card gap in the index field */

  /* ---------- Reading measure + vertical rhythm ------------
     --reading-measure caps the running text (paragraphs, lists,
     headings, quotes) via `.doc > * { max-inline-size }`; tables,
     code, and rules opt OUT and take the full column width.

     Set to `none` deliberately: the reading column is ALREADY locked
     at 760px (.review-col max-width), so a measure cap only ever
     trims ~104px (656 vs 760) — the readability gain (~77ch vs ~89ch
     line) is marginal, while the cost is visible: capped prose sits
     on a narrower grid than the full-width tables/code, which reads
     as two misaligned columns. At a 760px column we choose one grid
     for everything over a hair more measure. If the reading column is
     ever widened well past ~760px, restore a cap here (~41rem ≈ 68ch
     at the 17px body) — a LENGTH, not ch (ch resolves against each
     element's own font, so a heading and a paragraph capped at the
     same ch-count land at different widths and misalign in RTL).

     --rhythm is the single spacing step the reading column composes
     its vertical rhythm from: paragraph/list gaps are 1 step, the
     space ABOVE a heading is a larger multiple (a heading should
     bind to the text it introduces and breathe above it). The value
     here is a fallback; .doc re-derives it from --reading-size (see
     index.html) so the rhythm tracks the reading font and stays the
     same px regardless of each child's own font-size. Tuning the
     read's spacing happens here, once. */
  --reading-measure: none;
  --rhythm: 1rem;

  /* ---------- Motion --------------------------------------- */
  --ease-quiet:      cubic-bezier(.2, .8, .2, 1);
  --ease-considered: cubic-bezier(.22, 1, .36, 1);
  --ease-overshoot:  cubic-bezier(.34, 1.56, .64, 1);

  /* Duration scale — the named steps the app's ~30 magic numbers converge on.
     Migration is opportunistic: new motion uses these; existing declarations
     adopt them when their file is touched anyway (no big-bang rename).
     Pairing rule: an ENTER runs one step slower than its EXIT, and anything
     triggered many times per session stays on --dur-fast/--dur-quick.
     --dur-fast:  hover/press feedback, menu exits
     --dur-quick: exits, small state changes
     --dur-base:  the standard state change
     --dur-enter: entrances, settles
     --dur-hero:  the few earned signature moments */
  --dur-fast:  120ms;
  --dur-quick: 160ms;
  --dur-base:  200ms;
  --dur-enter: 280ms;
  --dur-hero:  420ms;

  /* Up-sheet motion — the SINGLE source of the rise/fall/fade/ease the bottom
     sheet uses. BOTH the static content-page sheet (.site-rail in
     components.css) AND the app's mobile docs sheet (.doc-nav overlay, also
     components.css) resolve these, so the two sheets can't drift on a number
     (nav-shell-v2: the side-drawer → up-sheet reconcile). Open/close are
     ASYMMETRIC — the sheet ENTERS over --sheet-rise (soft decelerate) and EXITS
     faster over --sheet-fall. cmo-motion tunes here, once.
     NOTE: --sheet-fall (220ms) is the app drawer's exit duration; the
     useExitTransition buffer in src/app.jsx must stay >= this so the slide-out
     never clips. */
  --sheet-rise: 280ms;
  --sheet-fall: 220ms;
  --sheet-ease-rise: cubic-bezier(.32, .72, 0, 1);
  /* The exit companion to --sheet-ease-rise: accelerate away decisively as the
     sheet leaves. Names the curve the sheet/scrim exits were hand-coding raw. */
  --sheet-ease-fall: cubic-bezier(.4, 0, 1, 1);
  --sheet-fade: 160ms;

  /* Docked-rail width. The app defines this inline in index.html for the
     SPA rail; mirrored here so the static content-page rail (.site-rail in
     components.css) offsets its content column by the identical width. */
  --dock-w: 300px;
}

/* ============================================================
   Dark theme — warm editorial.
   Pairs with the existing warm ink palette and brand-yellow.
   Canvas around #1a1815 (warm near-black). Surfaces lighten
   as elevation rises. Off-white text #ece9e1 (never #ffffff).
   ============================================================ */

[data-theme="dark"] {
  color-scheme: dark;

  --surface-0: #14110e;          /* sub-canvas, code wells */
  --surface-1: #1a1815;          /* primary canvas */
  --surface-2: #22201d;          /* raised, hovers */
  --surface-3: #2c2a26;          /* cards, popovers */
  --surface-4: #36332e;          /* dialogs */

  --bg:        var(--surface-1);
  --bg-sub:    var(--surface-2);

  /* Chip fills lift via white-overlay alpha (compose on any elevation). */
  --chip-bg:       rgba(255, 255, 255, 0.06);
  --chip-bg-hover: rgba(255, 255, 255, 0.10);
  /* --bg-cream stays warm-paper. Sticky-notes get dimmed via
     filter on the parent (see components.css) so the cream
     doesn't blast as a headlight against the dark canvas. */

  --text-primary:     #ece9e1;
  --text-secondary:   #b0aaa0;
  --text-muted:       #a59e93;
  --text-disabled:    #7a7268;
  --text-on-emphasis: #1a1815;

  --ink:   var(--text-primary);
  --ink-2: var(--text-secondary);
  --muted: var(--text-muted);

  /* Edges as rgba(white, alpha) so they composite correctly
     across multiple surface elevations. */
  --edge:          rgba(255, 255, 255, 0.12);
  --edge-strong:   rgba(255, 255, 255, 0.22);
  --edge-subtle:   rgba(255, 255, 255, 0.06);

  --hl-fill:      #fcd34d;
  --hl-fill-soft: rgba(252, 211, 77, 0.78);
  --hl-edge:      #f59e0b;
  /* Area washes go translucent in dark — a slab of the near-solid soft fill
     would be the loudest object on the canvas. Body text stays --ink on top. */
  --hl-wash:      rgba(252, 211, 77, 0.16);
  --hl-del-wash:  rgba(248, 113, 113, 0.16);
  /* Non-flipping by design — text on the yellow fill stays dark. */
  --text-on-hl:   #37352f;

  --del-wash: rgba(248, 113, 113, 0.07);
  --del-mark: #f0a39d;
  --del-edge: #f0a39d;

  --diff-add-ink:  #7fc596;
  --diff-add-line: #8fd0a4;
  --diff-add-rail: rgba(127, 197, 150, 0.50);
  --diff-del-ink:  #e8a39c;
  --diff-del-line: #efb0a9;
  --diff-del-rail: rgba(232, 163, 156, 0.46);

  --link-accent:      var(--hl-fill);
  --link-accent-soft: rgba(252, 211, 77, 0.32);
  --ring:             rgba(252, 211, 77, 0.95);
  --accent-deep:      #f6b56b;

  --shadow-small:  0 1px 2px rgba(0, 0, 0, 0.45);
  --shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.55);
  --shadow-large:  0 12px 32px rgba(0, 0, 0, 0.65);

  --img-filter: brightness(0.85) contrast(1.10);

  --topbar-blur: rgba(26, 24, 21, 0.85);

  --scrim: rgba(0, 0, 0, 0.62);
}

/* ============================================================
   System preference fallback.

   When the user is on "System" the boot script removes any
   data-theme attribute. This block then takes over via the OS
   preference. The :not([data-theme]) guard keeps an explicit
   Light or Dark choice from being overridden.
   ============================================================ */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]):not([data-theme="dark"]) {
    color-scheme: dark;

    --surface-0: #14110e;
    --surface-1: #1a1815;
    --surface-2: #22201d;
    --surface-3: #2c2a26;
    --surface-4: #36332e;

    --bg:     var(--surface-1);
    --bg-sub: var(--surface-2);

    --chip-bg:       rgba(255, 255, 255, 0.06);
    --chip-bg-hover: rgba(255, 255, 255, 0.10);

    --text-primary:     #ece9e1;
    --text-secondary:   #b0aaa0;
    --text-muted:       #a59e93;
    --text-disabled:    #7a7268;
    --text-on-emphasis: #1a1815;

    --ink:   var(--text-primary);
    --ink-2: var(--text-secondary);
    --muted: var(--text-muted);

    --edge:          rgba(255, 255, 255, 0.12);
    --edge-strong:   rgba(255, 255, 255, 0.22);
    --edge-subtle:   rgba(255, 255, 255, 0.06);

    --hl-fill:      #fcd34d;
    --hl-fill-soft: rgba(252, 211, 77, 0.78);
    --hl-wash:      rgba(252, 211, 77, 0.16);
    --hl-del-wash:  rgba(248, 113, 113, 0.16);
    --text-on-hl:   #37352f;

    --del-wash: rgba(248, 113, 113, 0.07);
    --del-mark: #f0a39d;
    --del-edge: #f0a39d;

    --diff-add-ink:  #7fc596;
    --diff-add-line: #8fd0a4;
    --diff-add-rail: rgba(127, 197, 150, 0.50);
    --diff-del-ink:  #e8a39c;
    --diff-del-line: #efb0a9;
    --diff-del-rail: rgba(232, 163, 156, 0.46);

    --link-accent:      var(--hl-fill);
    --link-accent-soft: rgba(252, 211, 77, 0.32);
    --ring:             rgba(252, 211, 77, 0.95);
    --accent-deep:      #f6b56b;

    --shadow-small:  0 1px 2px rgba(0, 0, 0, 0.45);
    --shadow-medium: 0 4px 12px rgba(0, 0, 0, 0.55);
    --shadow-large:  0 12px 32px rgba(0, 0, 0, 0.65);

    --img-filter: brightness(0.85) contrast(1.10);

    --topbar-blur: rgba(26, 24, 21, 0.85);

    --scrim: rgba(0, 0, 0, 0.62);
  }
}

/* ============================================================
   Editorial scale — phone override.
   Re-declare the content-page type + rhythm tokens ONCE so the
   whole scale steps down together on a phone. Every consumer
   (.wrap article, .faq, index heroes) tracks these, so there is
   no per-page mobile <style> to drift. The rail has already
   folded away by this width (see --read-collapse), so only the
   type + padding shrink here.
   ============================================================ */
@media (max-width: 640px) {
  :root {
    --fs-display: 2.25rem;   /* 36px */
    --fs-h1:      2rem;      /* 32px */
    --fs-h2:      1.375rem;  /* 22px */
    --fs-h3:      1.125rem;  /* 18px */
    --fs-lede:    1.1875rem; /* 19px */
    --fs-body:    1.0625rem; /* 17px */

    --read-pad-top:    40px;
    --read-pad-bottom: 24px;
  }
}
