/* c'hi — theme.css (first shared stylesheet, 2026-07-30).
   Owns: the eclipse theme toggle, the day/night circular wipe, and the dark theme.
   Dark-mode strategy: flip the design tokens on html[data-theme="dark"], then PIN every
   band that derives its darkness FROM the tokens (background: var(--ink) etc.) so the
   flip can't invert them. The dark surface language extends the tl;dr band's bento-card
   system (faint white surfaces, hairline borders) to the whole page.
   Loaded after each page's inline <style>; every dark rule is scoped under
   html[data-theme="dark"] so the light theme is byte-identical to before. */

/* ---------- 1 · Theme toggle (both themes) ---------- */

.nav-links { align-items: center; }
.nav-theme { display: flex; align-items: center; }

.theme-toggle {
  display: inline-grid; place-items: center;
  width: 2.35rem; height: 2.35rem; padding: 0;
  border-radius: 50%;
  border: 1px solid rgba(255,255,255,0.28);
  background: transparent;
  color: rgba(255,255,255,0.92);
  cursor: pointer;
  transition: color 0.25s ease, border-color 0.25s ease, background 0.25s ease, transform 0.2s ease;
}
.theme-toggle:hover { color: var(--teal-mid); border-color: rgba(93,202,165,0.55); background: rgba(255,255,255,0.05); }
.theme-toggle:active { transform: scale(0.9); }
.theme-toggle:focus-visible { outline: 2px solid var(--teal-mid); outline-offset: 2px; }
.theme-toggle svg { display: block; overflow: visible; }

/* Sun ↔ moon eclipse: transform + opacity only (site performance rule). */
.tt-sun, .tt-moon { transform-origin: 12px 12px; transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1), opacity 0.3s ease; }
.tt-moon { opacity: 0; transform: rotate(100deg) scale(0.5); }
.tt-rays { transform-origin: 12px 12px; transition: transform 0.55s cubic-bezier(0.22, 1, 0.36, 1); }
.theme-toggle:hover .tt-rays { transform: rotate(40deg); }
html[data-theme="dark"] .tt-sun { opacity: 0; transform: rotate(-100deg) scale(0.4); }
html[data-theme="dark"] .tt-moon { opacity: 1; transform: none; }

/* ✦ stars pop in after the moon lands (echoes the dock/tl;dr ✦ motif). */
.tt-star { opacity: 0; transform: scale(0); transform-box: fill-box; transform-origin: center; transition: transform 0.4s cubic-bezier(0.34, 1.56, 0.64, 1), opacity 0.3s ease; }
html[data-theme="dark"] .tt-star { opacity: 1; transform: scale(1); }
html[data-theme="dark"] .tt-star.s1 { transition-delay: 0.28s; }
html[data-theme="dark"] .tt-star.s2 { transition-delay: 0.4s; }
html[data-theme="dark"] .theme-toggle:hover .tt-star.s1 { animation: tt-twinkle 1.6s ease-in-out infinite 0.1s; }
html[data-theme="dark"] .theme-toggle:hover .tt-star.s2 { animation: tt-twinkle 1.6s ease-in-out infinite 0.5s; }
@keyframes tt-twinkle {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.35; transform: scale(0.6); }
}

@media (max-width: 480px) {
  .nav-links { gap: 0.9rem; }
  .nav-links a { font-size: 0.875rem; } /* 14px — the UI-chrome type floor */
  .theme-toggle { width: 2.1rem; height: 2.1rem; }
}

/* ---------- 2 · Day/night circular wipe (View Transitions API) ---------- */
/* theme.js animates clip-path on the snapshots; kill the default crossfade.
   mix-blend-mode: normal REMOVES the UA's default blending (allowed — the site ban
   is on ADDING blend modes). */
::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
/* Switching back to light: the OLD (dark) snapshot sits on top and contracts. */
html.vt-to-light::view-transition-old(root) { z-index: 2; }

/* ---------- 3 · Dark theme tokens ---------- */

:root { color-scheme: light; }

html[data-theme="dark"] {
  color-scheme: dark;
  /* flipped tokens — every var() consumer follows automatically */
  --teal-light: #14332A;   /* teal surface -> deep pine (chips, insights, outcome band) */
  --teal-text: #5DCAA5;    /* small teal text = teal-mid; 7.9–9.7:1 on the dark surfaces */
  --ink: #ECEAE4;          /* text roles invert */
  --ink-mid: #C9C7BF;
  --ink-soft: #9C9A91;     /* 5.6–6.4:1 everywhere it appears — AA for its 14px floor */
  --paper: #161614;        /* page — deliberately LIGHTER than the bands */
  --paper-warm: #1D1C18;   /* alternating sections stay a distinct warm dark */
  /* --teal and --teal-mid keep their light-mode values.
     dark-only helpers (dk- prefix so they can't collide with page vars).
     Band hierarchy (Chi's call, 2026-07-30): the hero/tl;dr/proof/vision/about bands
     drop BELOW the page tone in dark mode — deepest black #0D0D0B (darker than the
     gate's #0F0F0D). Since the 2026-07-31 all-light rebuild these bands are LIGHT
     surfaces in light mode, so dark mode is where they keep their drama. */
  --dk-band: #0D0D0B;              /* pinned dark bands (heroes, tl;dr, proof…) */
  --dk-card: #23221E;              /* elevated card surface (bento language) */
  --dk-line: rgba(255,255,255,0.10);
  --dk-line-soft: rgba(255,255,255,0.08);
}

/* ---------- 4 · Pin the bands that derive darkness FROM the tokens ---------- */
/* Without these, the token flip inverts every dark band into a light one. */

html[data-theme="dark"] .cs-hero,
html[data-theme="dark"] .cs-tldr,
html[data-theme="dark"] .cs-proof,
html[data-theme="dark"] .cs-vision,
html[data-theme="dark"] .about {
  background-color: var(--dk-band);
  /* The gradient is NOT a gradient — two identical stops paint a flat colour, but they
     stop Chrome classifying the tile as a solid quad. A tile that is all one colour takes
     the solid-quad fast path while a tile holding content is rasterised to a texture, and
     on a wide-gamut display the two land ~3/255 apart — invisible at mid-tones, a visible
     horizontal band against near-black (Chrome only; Safari composites these identically).
     Same fix as the gate's tile-banding, 2026-08-04. Keep both declarations together. */
  background-image: linear-gradient(var(--dk-band), var(--dk-band));
  color: #FAFAF8;
}
/* Same reason: the page behind those bands is near-black too. */
html[data-theme="dark"] body {
  background-image: linear-gradient(var(--paper), var(--paper));
}
/* Bands slightly lighter than the page now read as elevated panels; hairlines keep
   the section rhythm where contrast used to do the job. */
html[data-theme="dark"] .cs-tldr { border-top: 1px solid var(--dk-line-soft); border-bottom: 1px solid var(--dk-line-soft); }
html[data-theme="dark"] .cs-proof,
html[data-theme="dark"] .cs-vision,
html[data-theme="dark"] .about { border-top: 1px solid var(--dk-line-soft); border-bottom: 1px solid var(--dk-line-soft); }

/* var(--paper)-as-text inside pinned bands (flips dark without these) */
html[data-theme="dark"] .about-heading,
html[data-theme="dark"] .expertise-title,
html[data-theme="dark"] .archive-hover-title,
html[data-theme="dark"] .about-contact:hover { color: #FAFAF8; }
html[data-theme="dark"] .challenge-problem p { color: #FAFAF8; }

/* Dark cards on (formerly light) sections: keep them dark, add a seam */
html[data-theme="dark"] .challenge-card { background: var(--dk-band); border: 1px solid var(--dk-line-soft); }

/* index inversion traps */
html[data-theme="dark"] .btn-primary { color: #1a1a18; } /* white pill on the hero keeps dark text */
html[data-theme="dark"] .work-tab { border-color: rgba(255,255,255,0.22); }
html[data-theme="dark"] .work-tab.active { background: var(--ink); border-color: var(--ink); color: #1a1a18; }

/* juniper timeline active stage: elevated surface + teal edge replaces ink-on-light */
html[data-theme="dark"] .tl-stop.active { background: #2A2923; border-color: var(--teal-mid); }
html[data-theme="dark"] .tl-stop.active::after { background: #2A2923; border-right: 1px solid var(--teal-mid); border-bottom: 1px solid var(--teal-mid); }
html[data-theme="dark"] .tl-stop.active .t { color: #FAFAF8; }

/* ---------- 4b · All-light light mode restorations (2026-07-31) ---------- */
/* The light base now paints heroes/tl;dr/proof/vision/about/challenge-cards as light
   surfaces with ink text and black-alpha hairlines (Chi's all-light call). Everything
   token-driven flips on its own; these rules put back the dark values that were
   previously the light base. */
html[data-theme="dark"] .cs-meta { border-top-color: rgba(255,255,255,0.12); }
html[data-theme="dark"] .cs-stat .num em { color: var(--teal-mid); }
html[data-theme="dark"] .cs-tldr .k { border-color: rgba(93,202,165,0.35); }
html[data-theme="dark"] .cs-tldr .cs-stat + .cs-stat { border-left-color: rgba(255,255,255,0.14); }
html[data-theme="dark"] .cs-tldr-grid .item { background: rgba(255,255,255,0.04); border-color: rgba(255,255,255,0.09); }
html[data-theme="dark"] .cs-tldr-grid .item b::before { background: var(--teal-mid); }
/* DOJO only (2026-08-10): the tl;dr scope statement that replaced that page's stat trio, and the
   hairline separating Chi's roadmap from DOJO's shipped product in 04. Same light→dark treatment as
   the bento tick above (--teal reads on paper, --teal-mid on the #0D0D0B band); everything else in
   both blocks is token-driven and flips on its own. */
html[data-theme="dark"] .cs-scope { border-left-color: var(--teal-mid); }
html[data-theme="dark"] .di-launch { border-top-color: var(--dk-line-soft); }
html[data-theme="dark"] .cs-hero-visual::before { opacity: 1; } /* light halves the device glow; dark keeps it full */
/* Hero cast shadow (juniper/babylon/dojo, 2026-08-07 v6): dark mode swaps the black shadow
   sprite for its WHITE twin — a black shadow cannot read on #161614, and the site's dark
   elevation comes from light (index card-hover precedent), so the same field renders as a
   soft light spill on the wall. Both imgs are lazy; display:none keeps the inactive theme's
   file from ever fetching (about-scene pattern). */
html[data-theme="dark"] .cs-hero-visual .hero-shadow { display: none; }
html[data-theme="dark"] .cs-hero-visual .hero-shadow--dark { display: block; }
html[data-theme="dark"] .cs-hero-visual .device { border-color: rgba(255,255,255,0.18); box-shadow: 0 2px 6px rgba(0,0,0,0.45), 0 18px 40px rgba(0,0,0,0.4), 0 48px 110px rgba(0,0,0,0.55); }
html[data-theme="dark"] .cs-hero-visual .device.ph-device { border: 1.5px dashed rgba(255,255,255,0.3); background: rgba(255,255,255,0.03); box-shadow: none; color: rgba(250,250,248,0.55); }
html[data-theme="dark"] .cs-hero-visual .ph-device b { color: rgba(250,250,248,0.85); }
html[data-theme="dark"] .challenge-fact .v b, html[data-theme="dark"] .challenge-fact .v .hl { color: #E8836B; } /* light uses rust #B14A37 on the white cards */
/* About stage (2026-08-05): theme-matched scene swap — both imgs are lazy, so
   display:none keeps the inactive theme's file from ever fetching */
html[data-theme="dark"] .about-scene.scene-light { display: none; }
html[data-theme="dark"] .about-scene.scene-dark { display: block; }
html[data-theme="dark"] .about-stage::before { background: linear-gradient(90deg, rgba(13,13,11,0.75) 0%, rgba(13,13,11,0.42) 40%, rgba(13,13,11,0) 55%); }
/* Frosted cards over the dark scene: dark glass, same blur (inherited from the base rule).
   background-color longhand on purpose — the hover teal wash is a background-image layer. */
html[data-theme="dark"] .expertise-item { background-color: rgba(23,22,19,0.4); border-color: rgba(255,255,255,0.09); }
html[data-theme="dark"] .expertise-item:hover { background-image: linear-gradient(rgba(29,158,117,0.14), rgba(29,158,117,0.14)); }
html[data-theme="dark"] .expertise-icon { color: var(--teal-mid); }
html[data-theme="dark"] .about-heading em { color: var(--teal-mid); }
html[data-theme="dark"] .company-pill { border-color: rgba(255,255,255,0.1); background-color: rgba(23,22,19,0.5); }
/* CV link's paper stack: sheets dim like every authored-on-white image
   (brightness 0.88), back sheet matches the dimmed white; text flips via tokens */
html[data-theme="dark"] .cv-peek svg { filter: brightness(0.88); border-color: rgba(255,255,255,0.14); box-shadow: 0 6px 16px -8px rgba(0,0,0,0.6); }
html[data-theme="dark"] .cv-peek::before { background: #E2E0DA; border-color: rgba(255,255,255,0.14); }
/* About easter-egg bubble in dark: a white sticker glared against the night
   scene, but --dk-card (#23221E) then vanished into it — the wall behind the
   bubble measures rgb(26,22,19), only 1.13:1 from that card. This is a
   bubble-specific literal BY DESIGN: it floats over a photo, not over the page,
   so it needs more lift than any card token carries (--dk-card 1.13:1,
   .tl-stop.active #2A2923 1.23:1 — both still read as wall). #42403A gives
   1.73:1 against the scene with text at 8.6:1. Tail fill must track the card
   colour or it orphans as a spike. Don't "unify" this back to --dk-card. */
html[data-theme="dark"] .speech-bubble { background: #42403A; color: var(--ink); }
html[data-theme="dark"] .sb-tail path { fill: #42403A; }
/* Stand Up Commuters modal: standard dark card (it sits over a dim overlay, not
   the photo, so --dk-card separates fine here). The 2011 wordmark is dark-on-
   transparent, so it gets a light backing plate (demographics-plate precedent);
   old project photos/video dim like every authored-on-light image. */
html[data-theme="dark"] .suc-card { background: var(--dk-card); }
/* No backing plate in dark (Chi's call) — the wordmark swaps to a variant whose
   secondary lettering is recoloured light, so it sits straight on the card. */
html[data-theme="dark"] .suc-logo.logo-light { display: none; }
html[data-theme="dark"] .suc-logo.logo-dark { display: block; }
html[data-theme="dark"] .suc-media img, html[data-theme="dark"] .suc-media video { filter: brightness(0.88); }
html[data-theme="dark"] .suc-close { border-color: rgba(255,255,255,0.22); }
html[data-theme="dark"] .suc-step { border-color: rgba(255,255,255,0.2); }
html[data-theme="dark"] .suc-step.active { border-color: transparent; }
html[data-theme="dark"] .suc-foot { border-top-color: rgba(255,255,255,0.12); }

/* ---------- 5 · Light surfaces -> elevated dark cards (bento language) ---------- */

html[data-theme="dark"] .imgcard,
html[data-theme="dark"] .tl-stop,
html[data-theme="dark"] .tl-panel,
html[data-theme="dark"] .result-card,
html[data-theme="dark"] .call,
html[data-theme="dark"] .route,
html[data-theme="dark"] .pain-card {
  background: var(--dk-card);
  border-color: var(--dk-line);
}
html[data-theme="dark"] .cs-section.warm .ph { background: var(--dk-card); }
html[data-theme="dark"] .ph { border-color: rgba(93,202,165,0.4); }

/* design-rail scroll cues (2026-07-31 v4, Chi's call: subtle fades + hairline only — no arrows, no screen count) */
html[data-theme="dark"] .rail-clip { --rail-fade: rgba(35,34,30,0.7); } /* 70%-alpha --dk-card */
html[data-theme="dark"] .tl-progress { background: rgba(255,255,255,0.12); }
html[data-theme="dark"] .tl-progress b { background: var(--teal-mid); }

/* light-tuned soft shadows are mud on dark — lean on borders, deepen what remains */
html[data-theme="dark"] .imgcard { box-shadow: 0 18px 48px rgba(0,0,0,0.35); }
html[data-theme="dark"] .cs-section.warm .call { box-shadow: none; }
html[data-theme="dark"] .tl-stop:hover { box-shadow: 0 10px 24px rgba(0,0,0,0.4); }
html[data-theme="dark"] .tl-strip img { border-color: var(--dk-line); box-shadow: 0 8px 20px rgba(0,0,0,0.35); }
html[data-theme="dark"] .glance-grid img { box-shadow: 0 18px 48px rgba(0,0,0,0.4); border: 1px solid var(--dk-line); }
html[data-theme="dark"] .cs-figure img { box-shadow: 0 24px 64px rgba(0,0,0,0.4); border: 1px solid var(--dk-line); }

/* amber WIP notes get a dark amber scheme */
html[data-theme="dark"] .draft-note, html[data-theme="dark"] .gap { background: #2A2417; border-color: #4A3D1E; color: #E5C878; }
html[data-theme="dark"] .draft-note b { color: #F0D9A0; }

/* hairlines drawn in black-alpha flip to white-alpha */
html[data-theme="dark"] footer,
html[data-theme="dark"] .cs-footer { border-top-color: var(--dk-line); }

/* ---------- 6 · Images authored on white: dim slightly so they don't glare ---------- */
html[data-theme="dark"] .imgcard img,
html[data-theme="dark"] .tl-strip img,
html[data-theme="dark"] .glance-grid img,
html[data-theme="dark"] .cs-figure img,
html[data-theme="dark"] .research-grid img { filter: brightness(0.88); }

/* babylon's transparent demographics chart needs a light plate to stay readable */
html[data-theme="dark"] .cs-figure img[src*="demographics"] { background: #F5F3EE; padding: 0.75rem; filter: none; }

/* Cut-out figures (real alpha, no plate) opt out of the whole authored-on-white
   treatment above: the box-shadow and hairline border trace the element BOX, so
   on a transparent image they draw a rectangle around art that is floating free,
   and brightness(0.88) exists to settle white-plate art into the dark page —
   there is no plate left to settle. Unlike the demographics chart, this art
   carries its own light device bezels, so it needs no backing plate. */
html[data-theme="dark"] .cs-figure.is-cutout img {
  box-shadow: none;
  border: 0;
  filter: none;
  background: none;
}

/* the red wax seal multiplies to black on dark — drop the blend (PNG has real alpha) */
html[data-theme="dark"] .ending .seal img { mix-blend-mode: normal; }

/* ---------- 7 · Page-specific: index ---------- */

/* project cards use the two-layer gradient-border trick — re-declare BOTH layers */
/* a black shadow is invisible on a near-black page, so dark mode gets its lift from
   light instead: a top-weighted rim on the border layer + a soft neutral halo */
html[data-theme="dark"] .project-card {
  background: linear-gradient(#23221E, #23221E) padding-box,
              linear-gradient(rgba(255,255,255,0.20), rgba(255,255,255,0.07)) border-box;
  box-shadow: 0 22px 50px -18px rgba(255,255,255,0.12), 0 20px 44px rgba(0,0,0,0.55);
}
html[data-theme="dark"] .project-card:hover {
  background: linear-gradient(#23221E, #23221E) padding-box,
              linear-gradient(120deg, #E14FD0 0%, #8A63F4 55%, #3D9BE9 100%) border-box;
  /* same wash geometry as light mode, but DARKENING like the babylon hero shadow's
     dark twin (Chi's call): the inner layer keeps the v9 blue-grey anchor (a whisper
     of green), the wider outer layer is a dark pine penumbra — the hero sprites' v10
     chromatic grammar. Still a cool shadow pooling under the card, never a glow. High
     alphas are deliberate: the page is #161614, so a darkening shadow has little
     headroom and needs strength to read at all.
     2026-08-11: the two green layers were pulled 55% back toward the (2,9,6) anchor
     along the same ramp (Chi: "tone down the green element, it looks very green") —
     same hue, less chroma; the hero sprites took the identical k=0.45 remap. Then
     re-hued 152 -> 172 deg (Chi: "a bit blue & green mixed teal") by lifting B only,
     so R/G/luminance are unchanged: (2,9,6)/(6,33,21)/(14,55,36) -> +B. Brand teal is
     160 deg; the v12 cyan Chi rejected on sight was 193 — stay inside that. */
  box-shadow: 0 28px 44px -20px rgba(2,9,8,0.85),
              0 36px 62px -24px rgba(6,33,29,0.4),
              0 46px 84px -28px rgba(14,55,50,0.15);
}
html[data-theme="dark"] .project-image { background: #2B2A24; }
html[data-theme="dark"] .project-foot { border-top-color: var(--dk-line); }
html[data-theme="dark"] .tag { background: #2B2A24; }
html[data-theme="dark"] .footer-left img { filter: none; } /* white mark stays white on the dark footer */

/* ---------- 8 · Page-specific: babylon ---------- */

/* funnel bar keeps its light-mode pair (fill was chosen FOR white text) */
html[data-theme="dark"] .funnel-bar { background: #16785A; color: #fff; }
/* rust drop-off labels fail on dark paper — move to the salmon tier (6.9:1) */
html[data-theme="dark"] .funnel-drop { color: #E8836B; }

/* design carousel (03, 2026-08-05): the slide images are authored on light grey — dim like the
   other authored-on-white art; fades and the progress track pick up dark-surface colours */
html[data-theme="dark"] .ds-track img { filter: brightness(0.88); }
html[data-theme="dark"] .ds-rail { --ds-fade: rgba(22,22,20,0.7); }
html[data-theme="dark"] .ds-progress { background: rgba(255,255,255,0.14); }
html[data-theme="dark"] .ds-progress i { background: var(--teal-mid); }

/* ---------- 8b · Page-specific: checkout ---------- */

/* research poll chart (02, 2026-08-05): card surface joins the dark-card family, the neutral
   bars flip to a white-alpha track, and the teal accents move to the on-dark tier */
html[data-theme="dark"] .pollchart { background: var(--dk-card); border: 1px solid var(--dk-line); box-shadow: 0 18px 48px rgba(0,0,0,0.4); }
html[data-theme="dark"] .pc-bar { background: rgba(255,255,255,0.14); }
html[data-theme="dark"] .pc-row.is-top .pc-bar { background: var(--teal-mid); }
html[data-theme="dark"] .pc-row.is-top .pc-val { color: var(--teal-mid); }

/* ---------- 9 · Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .theme-toggle, .tt-sun, .tt-moon, .tt-rays, .tt-star { transition: none !important; animation: none !important; }
}
