/* base.css — reset, design tokens, page shell, header, tabs.
   Extracted from index.html <style> during the Phase 0 split.
   NOTE: --rs here is the same value as setup.html's --err. If a shared
   token file is ever created, alias them. */
*,*::before,*::after{margin:0;padding:0;box-sizing:border-box}
/* --tm lightened #6b7562 -> #8f9686 for ergonomics-audit H1: the original
   failed AA (3.42-3.71:1) on both --pine and --pm surfaces. #8f9686 measures
   5.87:1 on --pine, 5.41:1 on --pm, 4.59:1 on --pl -- verified computationally
   (WCAG relative-luminance formula), not read off the token in isolation.
   --tbl-lg and --ad-bright are dedicated overrides added for H3/H5 -- see
   components.css .sp.pb and .hc-num/.hc-scoring-label for why they exist
   instead of changing the shared --tbl/--ad tokens. */
:root{--pine:#0c1a12;--pm:#142218;--pl:#1c3024;--amber:#c4873b;--al:#e0a855;--ad:#8a6228;--ad-bright:#b0904f;--cream:#f2ece0;--sand:#bfb49a;--text:#f2ece0;--ts:#a8b09e;--tm:#8f9686;--rs:#e06050;--border:rgba(196,135,59,0.12);--bs:rgba(196,135,59,0.25);--ta:#2d6b47;--tal:#4a9e6e;--tb:#7a3b2e;--tbl:#c0654e;--tbl-lg:#c87763;
/* Motion tokens (Phase 2 Task 5 — deliberately last, so it absorbs every
   hand-typed duration/easing Tasks 1-3 introduced: the :active tap-feedback
   rule, the transition:all->explicit-properties rewrite, and .gs-new's pop-in).
   --ease-out intentionally replaces the ease-out keyword app-wide (snappier
   curve) — ruled 2026-08-13 */
--dur-fast:.12s;--dur-base:.2s;--dur-slow:.3s;--ease-out:cubic-bezier(.22,.61,.36,1);--ease-in-out:cubic-bezier(.45,0,.25,1);--ease-spring:cubic-bezier(.34,1.56,.64,1);
/* Golf-notation stroke tokens (input-rework port, design/input-forge —
   Nick's cut 2026-08-14: "the lines are dominating the UX and making the
   numbers a little hard to read"). Scoped to the score pad's own notation
   glyphs (components.css .pk-glyph) — NOT retrofitted onto the older
   .gs/.gs-sm vocabulary used by the desktop grid and sealed-hole badges,
   which keep their existing hand-tuned 1.5px/2px/3.5px literals unchanged.
   Single dark theme only right now (no [data-theme] mechanism exists in
   this codebase yet) — the forge's per-theme override block is not ported;
   these are flat values, not swapped anywhere. */
--gsw:1.5px;--gsg:2.5px;
/* Star notation (worse than double-bogey) — input-forge fix (design/input-
   forge porting note: ".gs-max star is broken in production": border +
   clip-path clips the border itself away, so the star barely rendered at
   any size). Ported fix draws the same polygon as a FILLED OUTLINE instead
   — an outer star path plus a reversed, slightly-smaller inner star path
   in one clip-path (nonzero fill rule self-intersects into a ~2px ring
   rather than a solid star). Shared by components.css .gs-max and
   .gs-sm.gs-max (and the score pad's own .pk-glyph.gs-max). */
--star:polygon(50% 0%,63% 30%,98% 35%,70% 58%,79% 91%,50% 72%,21% 91%,30% 58%,2% 35%,37% 30%,50% 0%,50% 5%,38.3% 32%,6.8% 36.5%,32% 57.2%,23.9% 86.9%,50% 69.8%,76.1% 86.9%,68% 57.2%,93.2% 36.5%,61.7% 32%,50% 5%);
/* Sunlight port (Task B, design/input-forge README §Sunlight treatment).
   Border-weight token -- hairline dark-theme borders thicken on paper.
   Scoped deliberately (see components.css/setup.css comments at each
   var(--bw) call site) to the surfaces the brief named -- score pad,
   scoreboard, tabs, headers -- not swept across every divider in the app. */
--bw:1px;
/* RGB-triple shadow tokens for the many rgba(R,G,B,alpha) wash/hover/badge
   literals across components.css/setup.css/js that hand-copy a token's hex
   as a bare triple to get an alpha-blended tint -- those bypass the :root
   palette entirely (Task B token audit) because rgba() can't take a hex
   token directly. Redefining the triple here lets every such literal become
   rgba(var(--X-rgb),alpha) and re-resolve correctly under [data-theme].
   --tm-rgb consolidates a drift found in the audit: existing literals used
   107,117,98 (the OLD pre-ergonomics-audit --tm, #6b7562) while --tm itself
   was relightened to #8f9686 (143,150,134) for H1's AA fix -- every wash
   site now matches the token that's actually live. */
--amber-rgb:196,135,59;--al-rgb:224,168,85;--ta-rgb:45,107,71;--tal-rgb:74,158,110;
--tb-rgb:122,59,46;--tbl-rgb:192,101,78;--tm-rgb:143,150,134;--rs-rgb:224,96,80;
--cream-rgb:242,236,224;--pine-rgb:12,26,18;
/* The Ledger Entry's paper card (components.css .mo-*, js/moments.js) is a
   deliberate, permanent palette-invert -- Phase 3 Task 3, "the paper card
   rises" -- built by borrowing var(--cream)/var(--pine) because in the dark
   theme those two tokens already happen to sit in the ink/paper polarity
   the card wants. That's incidental, not structural: --cream and --pine
   literally SWAP semantic roles under the sunlight override below (cream
   text-light -> ink-dark, pine bg-dark -> paper-light), so a card still
   wired to var(--cream)/var(--pine) would go paper-on-paper / ink-on-ink
   the moment sunlight is on. Task B decision (recorded per the brief): the
   card stays visually constant across both themes -- a fixed printed
   document, not a themed surface -- via these two theme-invariant tokens,
   declared once and never touched by the [data-theme="sunlight"] block
   below. Secondary accents inside the card (--ad label, --amber/--rs seal
   and margin-rule hues) are left on their normal theme tokens deliberately
   -- none of them invert polarity, so they just warm up slightly in
   sunlight along with the rest of the palette, which reads as intentional
   rather than broken. */
--mo-paper:#f2ece0;--mo-ink:#0c1a12;
}
/* ══════════════════════════════════════════
   SUNLIGHT — whole-app high-contrast light theme (Task B port of
   design/input-forge/index.html's body[data-theme="sun"] block, README.md
   §Sunlight treatment). Ruled by Nick on his phone ("sunlight toggle looks
   solid") for bright-sun scoring; the treatment itself ships un-ruled ("the
   Sunlight verdict: still pending" — README §The Cut) pending his use.
   Mechanism: [data-theme="sunlight"] lands on <html> (js/prefs.js-backed
   toggle, js/main.js / index.html inline pre-paint script), so :root is the
   themed element itself -- every token below is a PLAIN value (no var()
   inside its own definition), so unlike the forge's --keybg/--padkeyline
   finding, nothing here needs to move off :root to resolve correctly.
   Values are the forge's sunlight block verbatim (paper-white ground,
   near-black ink, thick borders) plus the RGB-triple/--bw tokens this port
   added above, computed from the same hex. */
:root[data-theme="sunlight"]{
  --pine:#f4efe1;--pm:#fdfaf0;--pl:#eae3cd;
  --amber:#7a4a10;--al:#5c380a;--ad:#6b4a14;--ad-bright:#553a0e;
  --cream:#181c12;--sand:#3f3a2b;--text:#181c12;--ts:#31382d;--tm:#4b5342;--rs:#9c2110;
  --border:rgba(24,28,18,0.45);--bs:rgba(24,28,18,0.65);
  --ta:#14532f;--tal:#0d4d2b;--tb:#7a2c14;--tbl:#8a2c12;
  /* --tbl-lg (base.css H3 fix, not a forge token): the dark-theme lighten
     was needed because --tbl measured 4.10:1 on --pm, under the 4.5:1
     floor. Ink-on-paper flips that problem's direction entirely -- sunlight
     --tbl alone measures 8.21:1 on sunlight --pm (verified, WCAG relative-
     luminance formula), comfortably clear -- so --tbl-lg just tracks --tbl
     here rather than needing its own lightened value. */
  --tbl-lg:#8a2c12;
  --bw:2px;--gsw:2px;--gsg:3px;
  --star:polygon(50% 0%,63% 30%,98% 35%,70% 58%,79% 91%,50% 72%,21% 91%,30% 58%,2% 35%,37% 30%,50% 0%,50% 9%,41% 36%,15% 40%,35% 56%,28% 79%,50% 63%,72% 79%,65% 56%,85% 40%,59% 36%,50% 9%);
  --amber-rgb:122,74,16;--al-rgb:92,56,10;--ta-rgb:20,83,47;--tal-rgb:13,77,43;
  --tb-rgb:122,44,20;--tbl-rgb:138,44,18;--tm-rgb:75,83,66;--rs-rgb:156,33,16;
  --cream-rgb:24,28,18;--pine-rgb:244,239,225;
}
body{font-family:'Outfit',sans-serif;background:var(--pine);color:var(--text);min-height:100vh;line-height:1.5;padding-top:env(safe-area-inset-top);overscroll-behavior-y:none;-webkit-tap-highlight-color:transparent}
body::before{content:'';position:fixed;inset:0;background:radial-gradient(ellipse at 30% 20%,rgba(196,135,59,0.03) 0%,transparent 50%),radial-gradient(ellipse at 70% 80%,rgba(45,107,71,0.04) 0%,transparent 50%);pointer-events:none;z-index:0}
/* Sunlight: the ambient dark-ground glow reads as dirt on paper -- forge
   parity (body[data-theme="sun"]::before{display:none}). */
[data-theme="sunlight"] body::before{display:none}
.c{max-width:1100px;margin:0 auto;padding:0 24px;position:relative;z-index:1}
header{text-align:center;padding:48px 0 0}
.he{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:5px;text-transform:uppercase;color:var(--ad);margin-bottom:8px}
header h1{font-family:'Cormorant Garamond',serif;font-size:clamp(48px,8vw,80px);font-weight:700;color:var(--cream);letter-spacing:-2px;line-height:1}
header h1 em{font-style:italic;color:var(--amber);font-weight:400}
.hv{font-family:'Cormorant Garamond',serif;font-size:clamp(16px,2.5vw,22px);color:var(--sand);margin-top:6px;font-style:italic}
/* ── THE CREST (Phase 3 Task 4) — ported from design/motion-forge/
   personality.html: variant A's breathe-in for the everyday load, variant
   C's ASSEMBLING entrance (Nick's cut, README.md §The Cut, 2026-08-13)
   reserved for once per session. Built from the real
   logos/pine-dunes-icon-texy-colors.svg, split into 4 layers by js/logos.js
   (CREST_SVG) -- same source paths, just grouped/recolored for this dark
   ground exactly as the prototype did. #headerLogo used to be an <img>
   pointed at EDITION_LOGOS[2026] (js/state.js); it is now this inline SVG,
   so the entrance can animate individual layers. History's own per-edition
   EDITION_LOGOS usage (js/ui-history.js) is untouched. */
.crest{width:110px;height:110px;margin:0 auto;display:block;overflow:visible}
.crest .lyr{transform-box:fill-box;transform-origin:center}
.hd{font-family:'JetBrains Mono',monospace;font-size:11px;color:var(--tm);margin-top:12px;letter-spacing:2px}
.sync-status{font-family:'JetBrains Mono',monospace;font-size:10px;letter-spacing:1px;text-align:center;margin-top:8px;padding:4px 12px;border-radius:20px;display:inline-block;cursor:pointer}
.sync-status.ok{color:var(--tal);background:rgba(var(--ta-rgb),0.15)}.sync-status.err{color:var(--rs);background:rgba(var(--rs-rgb),0.15)}.sync-status.load{color:var(--ad);background:rgba(var(--amber-rgb),0.1)}
/* --bw: tabs -- named surface, see components.css .sb comment (Task B). */
.tabs{display:flex;justify-content:center;gap:0;margin-top:20px;border-bottom:var(--bw) solid var(--border);position:sticky;top:0;z-index:10;background:var(--pine);padding-top:calc(8px + env(safe-area-inset-top))}
.tab{font-family:'JetBrains Mono',monospace;font-size:11px;letter-spacing:2px;text-transform:uppercase;color:var(--tm);padding:12px 20px;cursor:pointer;border-bottom:2px solid transparent;transition:color var(--dur-base),border-bottom-color var(--dur-base);user-select:none}
.tab.active{color:var(--amber);border-bottom-color:var(--amber)}
.tp{display:none;padding:32px 0}.tp.active{display:block}
/* Tab cross-fade + 8px drift (Phase 3 Task 4 — design/motion-forge/
   personality.html variant A "The Club", Nick's cut, README.md §The Cut,
   2026-08-13). Replaces the old display:none snap. .tp.active still drives
   the SETTLED state above (unchanged) -- .tp-entering/.tp-leaving are
   transient classes js/main.js's switchTab() adds only for the transition
   window, cleaned up on a fixed timer (not animationend: that event bubbles
   from any staggered list child inside the pane -- see .stagger below --
   which would fire this cleanup early/repeatedly). .tp-leaving stacks the
   outgoing pane absolutely over the incoming one, positioned against `.c`
   (css/base.css, already position:relative) so the settling pane's own
   height governs page flow while the old one fades out on top of it. */
.tp-leaving{display:block;position:absolute;left:0;right:0;animation:tpLeave var(--dur-base) ease-out both;pointer-events:none}
.tp-entering{display:block;animation:tpEnter var(--dur-slow) var(--ease-out) both;animation-delay:90ms}
@keyframes tpLeave{from{opacity:1}to{opacity:0}}
@keyframes tpEnter{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
/* Reduced motion: js/main.js's switchTab() never applies .tp-leaving at all
   under prefers-reduced-motion (the outgoing pane just loses .active and
   snaps to the base display:none above, same as the prototype's own reduced
   branch) -- only .tp-entering's override below is reachable, opacity-only,
   no drift. */
@media(prefers-reduced-motion:reduce){
  .tp-entering{animation:tpFadeOnly .15s ease-out both;animation-delay:0s}
}
@keyframes tpFadeOnly{from{opacity:0}to{opacity:1}}
/* M4 fix: horizontal padding trimmed 10px->6px so the six tabs (390px
   viewport, justify-content:center) sum under 390px -- pre-fix the first tab
   clipped off-canvas at x:-9. Vertical padding untouched (tap-target height
   already clears the 44px floor). */
@media(max-width:600px){.tab{padding:10px 6px;font-size:9px;letter-spacing:1px}}
@media (hover: hover) and (pointer: fine) {
  .tab:hover{color:var(--ts)}
}
.tab:active{transform:scale(0.97);transition:transform var(--dur-fast) var(--ease-out)}
.sync-status:active{transform:scale(0.97);transition:transform var(--dur-fast) var(--ease-out)}
/* Sunlight toggle (Task B) — header control, min-height/width 44px per this
   codebase's established tap-target floor (ergonomics audit H1-H5), not the
   forge's own 32px .fb-sun (a standalone demo page without that floor). */
.theme-toggle{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;border-radius:50%;border:var(--bw) solid var(--border);background:none;color:var(--tm);font-size:16px;line-height:1;cursor:pointer;transition:color var(--dur-fast),border-color var(--dur-fast),background-color var(--dur-fast)}
.theme-toggle[aria-pressed="true"]{color:var(--al);border-color:var(--bs);background:rgba(var(--amber-rgb),0.1)}
.theme-toggle:active{transform:scale(0.93);transition:transform var(--dur-fast) var(--ease-out)}
