/* ============ Light theme ============
   Loaded after css/styles.css, which stays the single source of truth for the
   dark design. Nothing here applies until <html> carries data-theme="light",
   so the dark site is byte-for-byte unchanged and this file is safe to revert.

   Why a whole file rather than tokens inside styles.css: styles.css writes its
   colors literally (rgba(255,255,255,.56) and friends) rather than through
   variables, so a token swap alone would not reach them. Overriding by
   component is the smaller, reviewable change — and it keeps the dark theme
   impossible to regress.

   ---- How the flip works ----

   The dark design alternates bands: dark hero, light products, dark model,
   light about, dark principles, gold contact, dark footer. That rhythm IS the
   design, so light mode inverts every band rather than making everything pale
   — otherwise the page flattens into one cream slab.

     band            dark theme          light theme
     hero            black + photo       cream + photo
     .section-light  paper   (light)  ->  ink    (dark)
     .section-dark   ink     (dark)   ->  paper  (light)
     .section-stone  stone   (light)  ->  ink-2  (dark)
     .section-black  black   (dark)   ->  cream  (light)
     .cta            gold               gold (unchanged — works on both)
     footer          black   (dark)   ->  cream  (light)

   So a band that is dark in one theme is light in the other, and the contact
   band stays gold in both as the fixed point.

   ---- Contrast ----

   Gold is the problem child: --gold-2 (#efc568) is a highlight color that
   fails WCAG AA on anything pale. On light surfaces the accent therefore
   switches to --gold-ink (#6f4f0f, 6.8:1 on cream), reusing the approach
   already proven by --eyebrow-dark in styles.css. Gold stays gold on the dark
   bands, which light mode still has.
*/

:root {
  /* Deeper than --eyebrow-dark (#755410) because it carries body-size links
     and the H1 accent word, not just 12px uppercase eyebrows. */
  --gold-ink: #6f4f0f;
  --cream: #f7f5f1;
  --cream-2: #efece4;
  --ink-2: #15181b;
  --ink-muted: #55575c; /* 6.6:1 on --cream */
  --ink-subtle: #66686d; /* 5.1:1 on --cream */
  /* Hero copy only. Everything else in this theme sits on a flat band, but the
     hero sits on a photograph: where a dark rock shows through the cream wash
     the backdrop drops to about rgb(186,185,182), and --ink-muted measures
     3.69:1 there. This clears 4.5:1 against that worst case. */
  --ink-hero: #45474c;
}

/* ============ Page base ============ */
html[data-theme='light'] {
  background: var(--cream);
  /* Overrides the `color-scheme: dark` styles.css sets on html, so UA widgets
     — scrollbars, form controls, focus rings — flip too. */
  color-scheme: light;
}
html[data-theme='light'] body {
  background: var(--cream);
  color: var(--ink);
}

/* ============ Header ============
   Same transparent-then-blurred behaviour, inverted. The scrim lives on the
   ::before for the same containing-block reason documented in styles.css. */
html[data-theme='light'] .site-header.scrolled {
  border-color: rgba(11, 12, 13, 0.1);
}
html[data-theme='light'] .site-header.scrolled::before {
  background: rgba(247, 245, 241, 0.86);
}
html[data-theme='light'] .site-nav > a:not(.button) {
  color: var(--ink-muted);
}
html[data-theme='light'] .site-nav > a:not(.button):hover,
html[data-theme='light'] .site-nav > a:not(.button):focus-visible {
  color: var(--ink);
}
html[data-theme='light'] .menu-toggle {
  color: var(--ink);
}
/* The off-canvas mobile panel is a full-bleed surface, so it needs the page
   background rather than inheriting the header's translucency. */
@media (max-width: 980px) {
  html[data-theme='light'] .site-nav {
    background: var(--cream);
  }
  html[data-theme='light'] .site-nav > a:not(.button) {
    border-bottom-color: var(--line-light);
  }
}

/* The wordmark and pillar icons are white monochrome raster/SVG loaded through
   <img>, so they cannot inherit currentColor — the exact problem styles.css
   already documents for the icons. Inverting a pure-white silhouette yields
   pure black, which is precisely the dark variant we need. */
html[data-theme='light'] .brand img,
html[data-theme='light'] .hero-points img {
  filter: invert(1);
}

/* ============ Hero ============
   The photograph stays; only the wash over it flips, so the ridgeline now
   dissolves into cream instead of black. Gradient stops mirror the dark
   original — including the top scrim that guarantees a readable band behind
   the fixed header at every viewport crop. */
html[data-theme='light'] .hero {
  background: var(--cream);
}
html[data-theme='light'] .hero-art {
  filter: saturate(0.72) contrast(0.96) brightness(1.06);
}
html[data-theme='light'] .hero-vignette {
  background:
    linear-gradient(
      180deg,
      rgba(247, 245, 241, 0.9) 0%,
      rgba(247, 245, 241, 0.45) 9%,
      transparent 18%
    ),
    linear-gradient(
      90deg,
      var(--cream) 0%,
      rgba(247, 245, 241, 0.98) 28%,
      rgba(247, 245, 241, 0.62) 52%,
      rgba(247, 245, 241, 0.14) 77%,
      rgba(247, 245, 241, 0.28) 100%
    ),
    linear-gradient(0deg, var(--cream) 0%, transparent 32%);
}
html[data-theme='light'] .hero h1 span {
  color: var(--gold-ink);
}
html[data-theme='light'] .hero-lede {
  color: var(--ink-hero);
}
html[data-theme='light'] .eyebrow {
  color: var(--gold-ink);
}
html[data-theme='light'] .hero-products > p {
  color: var(--ink-hero);
}
html[data-theme='light'] .hero-product-list a {
  color: var(--ink);
}
html[data-theme='light'] .hero-product-list a:hover,
html[data-theme='light'] .hero-product-list a:focus-visible {
  color: var(--gold-ink);
}
html[data-theme='light'] .hero-product-list a:not(:last-child)::after {
  background: rgba(11, 12, 13, 0.28);
}
html[data-theme='light'] .hero-points {
  border-top-color: var(--line-light);
}
html[data-theme='light'] .hero-points p {
  color: var(--ink-muted);
}

/* ---- Responsive hero washes ----
   styles.css re-draws .hero-vignette at 980px and at 640px, because the art box
   moves: it starts 33% in on desktop, 20% in on tablets, and on phones it runs
   full-bleed from the left edge, so the wash has to turn from a horizontal fade
   into a vertical one. The light override above is a single base rule, and a
   base rule of higher specificity beats a media-query rule of lower specificity
   — media queries add no specificity at all. So without these two blocks the
   light theme kept the DESKTOP wash at every width, and phones got a horizontal
   cream fade over a full-width photo: a hard vertical seam beside the headline,
   with "Scaling today." sitting on bare photo at 2.5:1.

   These mirror the dark gradients stop for stop, cream for ink. They have to
   come after the base rule, not before — same specificity, so source order is
   what settles it. */
@media (max-width: 980px) {
  html[data-theme='light'] .hero-vignette {
    background:
      linear-gradient(
        180deg,
        rgba(247, 245, 241, 0.9) 0%,
        rgba(247, 245, 241, 0.35) 9%,
        transparent 18%
      ),
      linear-gradient(
        90deg,
        var(--cream) 0%,
        rgba(247, 245, 241, 0.92) 38%,
        rgba(247, 245, 241, 0.25) 100%
      ),
      linear-gradient(0deg, var(--cream) 0%, transparent 40%);
  }
}
@media (max-width: 640px) {
  html[data-theme='light'] .hero-vignette {
    background: linear-gradient(
      180deg,
      var(--cream) 0%,
      rgba(247, 245, 241, 0.82) 44%,
      rgba(247, 245, 241, 0.2) 60%,
      var(--cream) 80%
    );
  }
}

/* ============ Band inversion ============ */

/* products — paper in the dark theme, ink here */
html[data-theme='light'] .section-light {
  background: #0c0e10;
  color: #f3f0e9;
}
html[data-theme='light'] .section-light .eyebrow-dark {
  color: var(--gold-2);
}
html[data-theme='light'] .section-light .section-heading > p:last-child {
  color: rgba(255, 255, 255, 0.56);
}

/* model — ink in the dark theme, paper here */
html[data-theme='light'] .section-dark {
  background: var(--paper);
  color: var(--ink);
}
html[data-theme='light'] .section-dark .eyebrow {
  color: var(--gold-ink);
}
html[data-theme='light'] .section-heading-dark > p:last-child {
  color: var(--ink-muted);
}
html[data-theme='light'] .model-list,
html[data-theme='light'] .model-row {
  border-color: var(--line-light);
}
html[data-theme='light'] .model-row > span {
  color: var(--gold-ink);
}
html[data-theme='light'] .model-row p {
  color: var(--ink-muted);
}

/* about — stone in the dark theme, ink here */
html[data-theme='light'] .section-stone {
  background: var(--ink-2);
  color: #f3f0e9;
}
html[data-theme='light'] .section-stone .eyebrow-dark {
  color: var(--gold-2);
}

/* principles — black in the dark theme, cream here */
html[data-theme='light'] .section-black {
  background: var(--cream);
  color: var(--ink);
}
html[data-theme='light'] .section-black .eyebrow {
  color: var(--gold-ink);
}
html[data-theme='light'] .principles-grid,
html[data-theme='light'] .principle {
  border-color: var(--line-light);
}
html[data-theme='light'] .principle span {
  color: var(--gold-ink);
}
html[data-theme='light'] .principle p {
  color: var(--ink-muted);
}

/* ============ Product cards ============
   The band under them is now dark, so the two solid cards and the two outline
   cards swap polarity to keep the same figure/ground relationship they have in
   the dark theme: two cards that advance, two that recede. */
html[data-theme='light'] .product-card-dark {
  background: var(--paper);
  color: var(--ink);
}
html[data-theme='light'] .product-card-dark p {
  color: var(--ink-muted);
}
html[data-theme='light'] .product-card-outline {
  border-color: rgba(255, 255, 255, 0.26);
  color: #f3f0e9;
}
html[data-theme='light'] .product-card-outline p {
  color: rgba(255, 255, 255, 0.58);
}
/* .product-card-gold is unchanged: gold works on either band. */

/* ============ Footer ============ */
html[data-theme='light'] .site-footer {
  background: var(--cream-2);
  border-top-color: var(--line-light);
}
html[data-theme='light'] .site-footer p,
html[data-theme='light'] .site-footer .footer-link {
  color: var(--ink-muted);
}
html[data-theme='light'] .site-footer .footer-link:hover,
html[data-theme='light'] .site-footer .footer-link:focus-visible {
  color: var(--gold-ink);
}

/* ============ Buttons ============ */
html[data-theme='light'] .button-ghost {
  border-color: rgba(111, 79, 15, 0.5);
  color: var(--ink);
  background: rgba(255, 255, 255, 0.4);
}
html[data-theme='light'] .button-black {
  background: var(--ink);
  color: var(--white);
}

/* ============ Focus ring ============
   styles.css pairs a dark core with a gold halo so one ring always clears 3:1.
   That logic holds on cream, but the halo is lightened-gold there and needs the
   deeper tone to stay visible. */
html[data-theme='light'] :focus-visible {
  outline-color: var(--gold-ink);
  box-shadow: 0 0 0 4px rgba(111, 79, 15, 0.32);
}

/* ============ Products page (/products) ============
   The product blocks sit on .section-black, which the band inversion above
   turns cream. Every foreground in that component set is a white-alpha value
   calibrated for #050607, so each needs a dark counterpart here — none of them
   inherit their way to legibility.

   Measured on cream: body copy 6.64:1, the 12px uppercase labels 5.12:1, the
   gold accents 6.88:1. */
html[data-theme='light'] .products-lede,
html[data-theme='light'] .product-body > p:not(.product-meta):not(.product-cta-pending),
html[data-theme='light'] .product-features li,
html[data-theme='light'] .product-meta,
html[data-theme='light'] .products-footnote {
  color: var(--ink-muted);
}
html[data-theme='light'] .product-num,
html[data-theme='light'] .product-body h3 {
  color: var(--ink-subtle);
}
html[data-theme='light'] .product-block,
html[data-theme='light'] .product-body .product-cta-pending,
html[data-theme='light'] .products-footnote {
  border-top-color: var(--line-light);
}
html[data-theme='light'] .product-body .product-cta-pending {
  color: var(--ink);
}
/* The status pill. Its border carries no information the label does not — the
   text is the state, at 6.88:1 — so it is framing rather than a 1.4.11 state
   indicator. Worth noting the dark original measures 2.38:1; 0.65 alpha here
   reaches 3.10:1, so the light pill is slightly crisper than the dark one
   rather than merely at parity. */
html[data-theme='light'] .product-status {
  border-color: rgba(111, 79, 15, 0.65);
  color: var(--gold-ink);
}
html[data-theme='light'] .product-features li::before {
  background: var(--gold-ink);
}
/* The per-app listing. Colour only — the grid and the 560px stack live in
   css/styles.css, deliberately, because a base rule here would outrank a media
   query there and pin every width to the desktop layout. That is the bug
   commit 8a41970 fixed in the hero; this file must not reintroduce it.

   The app name is --ink rather than --ink-muted: it is the heading of its row,
   and the muted tone that suits body copy reads as disabled on a name. */
html[data-theme='light'] .app-name {
  color: var(--ink);
}
html[data-theme='light'] .app-desc,
html[data-theme='light'] .app-spec dd {
  color: var(--ink-muted);
}
html[data-theme='light'] .app-spec dt {
  color: var(--gold-ink);
}
html[data-theme='light'] .app-item {
  border-bottom-color: var(--line-light);
}
html[data-theme='light'] .app-unreleased {
  border-bottom-color: rgba(85, 87, 92, 0.45);
}
html[data-theme='light'] .products-footnote a {
  color: var(--gold-ink);
  border-bottom-color: rgba(111, 79, 15, 0.5);
}

/* .product-grid-more is the exception in this set, and the reason it is worth
   stating explicitly: it does NOT live on the products page. It is the "see
   what each product does" link under the homepage card grid, inside
   .section-light — the one band the inversion turns DARK. So its colors are
   already ink-on-paper for the dark theme, and in the light theme they need to
   go the other way. Left alone it measures 1.03:1 and is invisible. */
html[data-theme='light'] .product-grid-more a {
  color: #f3f0e9;
  border-bottom-color: rgba(255, 255, 255, 0.38);
}
html[data-theme='light'] .product-grid-more a:hover,
html[data-theme='light'] .product-grid-more a:focus-visible {
  border-color: #f3f0e9;
}

/* ============ Legal pages ============
   /terms and /accessibility are dark-only surfaces in styles.css. */
html[data-theme='light'] .legal p:not(.legal-meta),
html[data-theme='light'] .legal li {
  color: var(--ink-muted);
}
html[data-theme='light'] .legal-meta {
  color: var(--ink-subtle);
}
html[data-theme='light'] .legal a {
  color: var(--gold-ink);
  border-bottom-color: rgba(111, 79, 15, 0.45);
}
html[data-theme='light'] .legal strong {
  color: #000;
}
html[data-theme='light'] .skip-link {
  background: var(--ink);
  color: #fff;
}

/* ============ Theme switch ============
   Light / Dark / System, built by js/theme-toggle.js rather than written into
   every page's markup: the control is useless without JavaScript, so creating
   it in JavaScript means it is never present as a dead control — and a static
   file-per-page site does not have to repeat it five times.

   It is appended to .site-nav, which gives it one DOM position that works in
   both layouts: a row of icons in the header bar on desktop, and a full-width
   segmented control at the foot of the off-canvas panel below 980px. */
.theme-switch {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  padding: 3px;
  border: 1px solid var(--line-dark);
  border-radius: var(--radius);
}
.theme-switch [role='radio'] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* 38x32 clears the 24x24 target minimum with room to spare; the panel
     version below goes to a full 44px row. */
  width: 38px;
  height: 32px;
  padding: 0;
  /* Transparent by default so the checked border below does not shift layout.
     A border rather than an inset box-shadow because :focus-visible in
     styles.css already owns box-shadow — the ring would vanish on the focused
     item, which is exactly the one whose state matters most. */
  border: 1px solid transparent;
  border-radius: 1px;
  background: transparent;
  color: rgba(255, 255, 255, 0.62);
  cursor: pointer;
  transition:
    background 0.18s var(--ease),
    color 0.18s var(--ease);
}
.theme-switch [role='radio']:hover {
  color: #fff;
  background: rgba(255, 255, 255, 0.07);
}
/* The fill alone measures 1.32:1 against the header — perceivable, but far
   too weak to be the thing that says "selected", and icon color on its own
   would make state a color-only cue (WCAG 1.4.1). The accent border is the
   real indicator: 11.6:1 against the header bar, well clear of the 3:1 that
   1.4.11 asks of a state indicator. The fill just softens it. */
.theme-switch [role='radio'][aria-checked='true'] {
  background: rgba(255, 255, 255, 0.12);
  border-color: var(--gold-2);
  color: var(--gold-2);
}
.theme-switch svg {
  width: 17px;
  height: 17px;
  display: block;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

html[data-theme='light'] .theme-switch {
  border-color: var(--line-light);
}
html[data-theme='light'] .theme-switch [role='radio'] {
  color: var(--ink-muted);
}
html[data-theme='light'] .theme-switch [role='radio']:hover {
  color: var(--ink);
  background: rgba(11, 12, 13, 0.05);
}
html[data-theme='light'] .theme-switch [role='radio'][aria-checked='true'] {
  background: rgba(11, 12, 13, 0.08);
  border-color: var(--gold-ink);
  color: var(--gold-ink);
}

/* In the off-canvas panel the control spans the width and the three options
   split it evenly, matching the full-width Products button above it. */
@media (max-width: 980px) {
  .theme-switch {
    display: flex;
    width: 100%;
    margin-top: 22px;
  }
  .theme-switch [role='radio'] {
    flex: 1;
    width: auto;
    height: 44px;
  }
}
