/* ═══════════════════════════════════════════════════════════════════
   CONIO — SHARED THEME FOUNDATION
   Loaded by every page: index, admin, changelog, privacy, terms,
   confirmed. Holds the design tokens (light + dark), the reset, the
   layout/type/button primitives, the nav + footer, and the motion
   layer. Page-specific CSS stays inline in each page.

   "Estimator's Instrument" — drafting-paper surfaces, hairline
   borders, one decisive engineering blue. No purple, no
   glassmorphism, no gradient CTAs.

   ── DARK MODE ──────────────────────────────────────────────────
   Tokens are declared three times on purpose:
     1. :root                      → light (the default, and the
                                     floor for browsers that match
                                     neither block below)
     2. @media (prefers-color-scheme: dark) :root:not([data-theme=light])
                                   → system preference, no choice made
     3. :root[data-theme="dark"]   → explicit user choice
   Blocks 2 and 3 are identical and MUST be edited together.
   js/theme.js sets data-theme; a tiny inline <head> script in each
   page applies it before first paint so there is no flash.
   ═══════════════════════════════════════════════════════════════════ */

/* ═══════════════════════════════════════════════
   TOKENS — LIGHT (default)
═══════════════════════════════════════════════ */
:root {
  color-scheme: light;

  /* one decisive engineering blue — the only accent */
  --blue:        #0a63d2;
  --blue-bright: #0b6ee8;
  --blue-dim:    #eef5fe;
  /* --blue-solid is the CTA/fill blue, --on-blue the text on top of it.
     Split from --blue because the dark theme needs a lighter blue for
     text-on-background but a deeper one for white-on-blue buttons. */
  --blue-solid:   #0a63d2;
  --blue-solid-h: #0b6ee8;
  --on-blue:      #ffffff;

  --green:        #1d7a3a;
  --green-dim:    #ecfdf3;
  --green-dim-h:  #dcf7e7;
  --green-border: #b7e4c7;

  --amber:        #b45309;
  --amber-dim:    #fff8ec;
  --amber-border: #f5d9a8;

  --red:     #c41e10;
  --red-dim: rgb(196 30 16 / 0.10);

  /* light, drafting-paper surfaces */
  --bg-0: #f4f5f7;
  --bg-1: #ffffff;
  --bg-2: #fbfbfd;
  --bg-3: #eef0f3;

  /* ink */
  --t1: #1a1c22;
  --t2: #5c616e;
  --t3: #8a8f9d;
  --t4: #c9cdd6;

  /* hairline discipline */
  --border:   #e4e6eb;
  --border-h: #c9cdd6;
  --border-p: #b6d4f8;

  /* solid chip (tier pills) — inverted ink plate */
  --chip-bg: #1a1c22;
  --chip-fg: #ffffff;

  /* blueprint grid on body::before */
  --grid-line: rgba(10, 99, 210, 0.04);
  --grid-size: 24px;

  /* focus ring */
  --ring: rgb(10 99 210 / 0.35);

  /* scrims + plates */
  --scrim:      rgba(16, 18, 24, 0.72);
  --scrim-soft: rgba(16, 18, 24, 0.55);
  --scrim-hard: rgba(16, 18, 24, 0.80);
  /* Product screenshots are captures of a LIGHT app UI. In dark mode
     they sit on a deliberately light plate so they read as a lit
     screen rather than a glaring rectangle. */
  --shot-plate: #fbfbfd;
  --select-bg:  #ffffff;
  --select-fg:  #1a1c22;

  --shadow-card: 0 1px 3px rgba(16,18,24,0.06), 0 1px 2px rgba(16,18,24,0.04);
  --shadow-md:   0 4px 12px rgba(16,18,24,0.08), 0 1px 3px rgba(16,18,24,0.04);
  --shadow-pop:  0 12px 32px rgba(16,18,24,0.14), 0 2px 6px rgba(16,18,24,0.06);
  --shadow-pool: rgba(16,18,24,0.10);

  /* ── type ───────────────────────────────────── */
  --fh: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --fb: 'Plus Jakarta Sans', -apple-system, BlinkMacSystemFont, sans-serif;
  --fm: 'IBM Plex Mono', ui-monospace, SFMono-Regular, Menlo, monospace;

  --fs-display: clamp(2.6rem, 5.6vw, 4.4rem);
  --fs-h2:      clamp(1.9rem, 4.2vw, 3rem);
  --fs-h3:      clamp(1.5rem, 2.6vw, 1.75rem);
  --fs-h4:      1.05rem;
  --fs-body:    clamp(0.96rem, 0.4vw + 0.86rem, 1.05rem);
  --fs-sm:      0.875rem;
  --fs-xs:      0.8rem;
  --fs-2xs:     0.72rem;
  --fs-3xs:     0.62rem;

  /* ── space scale ────────────────────────────── */
  --sp-1:  4px;
  --sp-2:  8px;
  --sp-3:  12px;
  --sp-4:  16px;
  --sp-5:  24px;
  --sp-6:  32px;
  --sp-7:  40px;
  --sp-8:  48px;
  --sp-9:  64px;
  --sp-10: 80px;
  --sp-11: 104px;
  --sp-12: 128px;

  /* Section rhythm + measure. These drive the "spacious" feel —
     tune here, not in individual sections. */
  --sec-y:       clamp(72px, 8.5vw, 140px);
  --gutter:      clamp(18px, 4vw, 40px);
  --maxw:        1240px;
  --maxw-mid:    900px;
  --maxw-narrow: 760px;
  --maxw-prose:  660px;
  --gap-card:    clamp(16px, 1.6vw, 24px);
  --hd-gap:      clamp(40px, 5vw, 68px);

  /* ── radii ──────────────────────────────────── */
  --r-sm:   6px;
  --r-md:   8px;
  --r-lg:   10px;
  --r-xl:   12px;
  --r-2xl:  16px;
  --r-pill: 100px;

  /* ── motion ─────────────────────────────────── */
  --ease:     cubic-bezier(0.22, 1, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --dur-1: 0.18s;
  --dur-2: 0.3s;
  --dur-3: 0.55s;
  --dur-4: 0.8s;

  --nav-h:       66px;
  --nav-h-small: 56px;
}

/* ═══════════════════════════════════════════════
   TOKENS — DARK (system preference, no explicit choice)
   Keep in sync with :root[data-theme="dark"] below.
═══════════════════════════════════════════════ */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    color-scheme: dark;

    --blue:        #6ba5ff;
    --blue-bright: #8dbaff;
    --blue-dim:    #13253d;
    --blue-solid:   #1a66e0;
    --blue-solid-h: #2f7bf5;
    --on-blue:      #ffffff;

    --green:        #4cc97a;
    --green-dim:    #10251a;
    --green-dim-h:  #16331f;
    --green-border: #1f4a31;

    --amber:        #e0a33f;
    --amber-dim:    #221a0c;
    --amber-border: #4a3717;

    --red:     #ff7267;
    --red-dim: rgb(255 114 103 / 0.12);

    --bg-0: #0d1013;
    --bg-1: #16191f;
    --bg-2: #101419;
    --bg-3: #1e222a;

    --t1: #e9ecf2;
    --t2: #a6adbb;
    --t3: #767e8d;
    --t4: #4a515e;

    --border:   #252932;
    --border-h: #39404c;
    --border-p: #27456f;

    --chip-bg: #e9ecf2;
    --chip-fg: #14171c;

    --grid-line: rgba(140, 180, 255, 0.045);

    --ring: rgb(107 165 255 / 0.45);

    --scrim:      rgba(4, 6, 9, 0.82);
    --scrim-soft: rgba(4, 6, 9, 0.60);
    --scrim-hard: rgba(4, 6, 9, 0.90);
    --shot-plate: #e9ebf0;
    --select-bg:  #16191f;
    --select-fg:  #e9ecf2;

    --shadow-card: 0 1px 3px rgba(0,0,0,0.50), 0 1px 2px rgba(0,0,0,0.40);
    --shadow-md:   0 6px 16px rgba(0,0,0,0.55), 0 1px 3px rgba(0,0,0,0.40);
    --shadow-pop:  0 18px 44px rgba(0,0,0,0.62), 0 2px 8px rgba(0,0,0,0.45);
    --shadow-pool: rgba(0,0,0,0.55);
  }
}

/* ═══════════════════════════════════════════════
   TOKENS — DARK (explicit user choice)
   Identical to the @media block above — edit both.
═══════════════════════════════════════════════ */
:root[data-theme="dark"] {
  color-scheme: dark;

  --blue:        #6ba5ff;
  --blue-bright: #8dbaff;
  --blue-dim:    #13253d;
  --blue-solid:   #1a66e0;
  --blue-solid-h: #2f7bf5;
  --on-blue:      #ffffff;

  --green:        #4cc97a;
  --green-dim:    #10251a;
  --green-dim-h:  #16331f;
  --green-border: #1f4a31;

  --amber:        #e0a33f;
  --amber-dim:    #221a0c;
  --amber-border: #4a3717;

  --red:     #ff7267;
  --red-dim: rgb(255 114 103 / 0.12);

  --bg-0: #0d1013;
  --bg-1: #16191f;
  --bg-2: #101419;
  --bg-3: #1e222a;

  --t1: #e9ecf2;
  --t2: #a6adbb;
  --t3: #767e8d;
  --t4: #4a515e;

  --border:   #252932;
  --border-h: #39404c;
  --border-p: #27456f;

  --chip-bg: #e9ecf2;
  --chip-fg: #14171c;

  --grid-line: rgba(140, 180, 255, 0.045);

  --ring: rgb(107 165 255 / 0.45);

  --scrim:      rgba(4, 6, 9, 0.82);
  --scrim-soft: rgba(4, 6, 9, 0.60);
  --scrim-hard: rgba(4, 6, 9, 0.90);
  --shot-plate: #e9ebf0;
  --select-bg:  #16191f;
  --select-fg:  #e9ecf2;

  --shadow-card: 0 1px 3px rgba(0,0,0,0.50), 0 1px 2px rgba(0,0,0,0.40);
  --shadow-md:   0 6px 16px rgba(0,0,0,0.55), 0 1px 3px rgba(0,0,0,0.40);
  --shadow-pop:  0 18px 44px rgba(0,0,0,0.62), 0 2px 8px rgba(0,0,0,0.45);
  --shadow-pool: rgba(0,0,0,0.55);
}

/* ═══════════════════════════════════════════════
   RESET
═══════════════════════════════════════════════ */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }

html {
  scroll-behavior: smooth;
  -webkit-text-size-adjust: 100%;
  scroll-padding-top: calc(var(--nav-h) + var(--sp-5));
}

body {
  font-family: var(--fb);
  background: var(--bg-0);
  color: var(--t1);
  line-height: 1.6;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

a   { text-decoration: none; color: inherit; }
img { display: block; max-width: 100%; }
ul  { list-style: none; }
button { font-family: var(--fb); cursor: pointer; }
::selection { background: var(--blue-dim); color: var(--t1); }

/* Keyboard focus ring — CLAUDE.md documents --blue as the focus ring
   but nothing implemented one before this file existed. */
:focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 2px;
  border-radius: 3px;
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  top: -100px;
  left: var(--sp-4);
  z-index: 3000;
  padding: 10px 16px;
  background: var(--blue-solid);
  color: var(--on-blue);
  font-size: var(--fs-sm);
  font-weight: 700;
  border-radius: var(--r-md);
  transition: top var(--dur-1) ease;
}
.skip-link:focus { top: var(--sp-4); }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.mono { font-family: var(--fm); font-variant-numeric: tabular-nums; }

/* ═══════════════════════════════════════════════
   BLUEPRINT GRID — the technical engineering ground.
   Listed in CLAUDE.md as do-not-remove.
═══════════════════════════════════════════════ */
body::before {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-image:
    linear-gradient(var(--grid-line) 1px, transparent 1px),
    linear-gradient(90deg, var(--grid-line) 1px, transparent 1px);
  background-size: var(--grid-size) var(--grid-size);
}

/* ═══════════════════════════════════════════════
   LAYOUT HELPERS
═══════════════════════════════════════════════ */
.sec, .sec-sm, .sec-mid {
  margin: 0 auto;
  padding: var(--sec-y) var(--gutter);
  position: relative;
  z-index: 1;
}
.sec     { max-width: var(--maxw); }
.sec-mid { max-width: var(--maxw-mid); }
.sec-sm  { max-width: var(--maxw-narrow); }

/* Hairline rule separating stacked sections. */
.section-rule { position: relative; }
.section-rule::before {
  content: '';
  position: absolute;
  top: 0; left: 0; right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent 0%, var(--border-h) 30%, var(--border-h) 70%, transparent 100%);
}

/* Centred section header block */
.sec-hd {
  text-align: center;
  max-width: var(--maxw-prose);
  margin: 0 auto var(--hd-gap);
}

/* ═══════════════════════════════════════════════
   TYPOGRAPHY COMPONENTS
═══════════════════════════════════════════════ */
.lbl {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--t3);
  margin-bottom: var(--sp-4);
}
.lbl::before {
  content: '';
  display: block;
  width: 18px;
  height: 1px;
  background: currentColor;
  flex-shrink: 0;
}
.lbl.green { color: var(--green); }

.sh {
  font-family: var(--fh);
  font-size: var(--fs-h2);
  font-weight: 800;
  line-height: 1.12;
  letter-spacing: -0.02em;
  color: var(--t1);
  margin-bottom: var(--sp-3);
  text-wrap: balance;
}
.sp { color: var(--blue); }

.sub {
  font-size: var(--fs-body);
  color: var(--t2);
  line-height: 1.7;
  text-wrap: pretty;
}

/* ═══════════════════════════════════════════════
   BUTTONS
═══════════════════════════════════════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 9px;
  padding: 11px 22px;
  border-radius: var(--r-md);
  font-family: var(--fb);
  font-size: var(--fs-sm);
  font-weight: 700;
  border: 1px solid transparent;
  transition: background var(--dur-1) ease, border-color var(--dur-1) ease,
              color var(--dur-1) ease, transform var(--dur-1) ease,
              box-shadow var(--dur-1) ease;
  white-space: nowrap;
}
.btn i { font-size: 0.8em; }
.btn:active { transform: translateY(1px) scale(0.995); }

.btn-primary, .btn-pro {
  background: var(--blue-solid);
  color: var(--on-blue);
}
.btn-primary:hover, .btn-pro:hover {
  background: var(--blue-solid-h);
  transform: translateY(-1px);
  box-shadow: var(--shadow-md);
}

.btn-ghost {
  background: var(--bg-1);
  color: var(--t1);
  border-color: var(--border-h);
}
.btn-ghost:hover {
  border-color: var(--t3);
  background: var(--bg-3);
  transform: translateY(-1px);
}

.btn-free {
  background: var(--green-dim);
  color: var(--green);
  border-color: var(--green-border);
}
.btn-free:hover {
  background: var(--green-dim-h);
  transform: translateY(-1px);
}

.btn-quiet {
  background: transparent;
  color: var(--t2);
  border-color: var(--border);
}
.btn-quiet:hover { color: var(--t1); border-color: var(--border-h); background: var(--bg-1); }

.btn-lg   { padding: 14px 28px; font-size: 1rem; border-radius: var(--r-xl); }
.btn-sm   { padding: 8px 14px; font-size: var(--fs-xs); }
.btn-full { width: 100%; }

/* ═══════════════════════════════════════════════
   ETHIOPIAN DOT BADGE — intentional, do not restyle
═══════════════════════════════════════════════ */
.eth-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
  background: conic-gradient(#078930 0 120deg, #FCDD09 120deg 240deg, #DA121A 240deg 360deg);
}
.eth-dot.lg { width: 10px; height: 10px; }

/* ═══════════════════════════════════════════════
   TIER CHIP — one solid style, no per-badge colours
═══════════════════════════════════════════════ */
.pro-chip {
  display: inline-flex;
  align-items: center;
  padding: 3px 8px;
  background: var(--chip-bg);
  color: var(--chip-fg);
  font-size: var(--fs-3xs);
  font-weight: 800;
  letter-spacing: 0.08em;
  border-radius: 3px;
  flex-shrink: 0;
  white-space: nowrap;
}
.pro-chip.mini { padding: 1px 5px; font-size: 0.5rem; }

/* ═══════════════════════════════════════════════
   BRAND LOCKUP
   The teal icon mark (#00B8A2) is brand identity and stays fixed in
   both themes (CLAUDE.md). Only the wordmark/tagline ink follows the
   theme — the inline SVG text uses fill="currentColor" so it can.
═══════════════════════════════════════════════ */
.brand {
  display: flex;
  align-items: center;
  gap: 9px;
  flex-shrink: 0;
}
.brand-mark { width: 30px; height: 30px; flex-shrink: 0; }
.brand-mark svg { width: 30px; height: 30px; }
.brand-name {
  font-family: var(--fh);
  font-weight: 800;
  font-size: 1.15rem;
  color: var(--t1);
  letter-spacing: -0.01em;
}
/* Wordmark lockup (hero): mark keeps its teal, text inherits ink. */
.brand-lockup { color: var(--t1); }
.brand-lockup .wordmark { fill: currentColor; }
.brand-lockup .tagline  { fill: var(--t3); }

/* ═══════════════════════════════════════════════
   NAVBAR
   Scoped to the direct child of <body> — a bare `nav {}` selector also
   matches <nav class="footer-nav"> in the footer, which then inherited
   position:fixed and rendered at the top of the viewport.
═══════════════════════════════════════════════ */
body > nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 900;
  padding: 0 var(--gutter);
  background: var(--bg-1);
  border-bottom: 1px solid var(--border);
  transition: box-shadow var(--dur-2) ease, background var(--dur-2) ease;
}
/* Past the fold the bar tightens and lifts off the page. Opaque, not
   blurred — glassmorphism is out per the brand spec. */
body > nav.scrolled { box-shadow: var(--shadow-md); }
body > nav.scrolled .nav-inner { height: var(--nav-h-small); }

/* Scroll progress hairline */
.nav-progress {
  position: absolute;
  left: 0; bottom: -1px;
  height: 2px;
  width: 100%;
  transform: scaleX(0);
  transform-origin: 0 50%;
  background: var(--blue);
  pointer-events: none;
}

.nav-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--nav-h);
  gap: var(--sp-5);
  transition: height var(--dur-2) ease;
}

.nav-links {
  display: flex;
  gap: var(--sp-6);
  flex: 1;
  justify-content: center;
}
.nav-links a {
  position: relative;
  font-size: var(--fs-sm);
  font-weight: 500;
  color: var(--t3);
  transition: color var(--dur-1);
  letter-spacing: 0.01em;
  padding: 4px 0;
}
.nav-links a::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: -2px;
  height: 1.5px;
  background: var(--blue);
  transform: scaleX(0);
  transform-origin: 50% 50%;
  transition: transform var(--dur-2) var(--ease);
}
.nav-links a:hover { color: var(--t1); }
.nav-links a:hover::after { transform: scaleX(1); }
/* Set by the section observer in js/theme.js */
.nav-links a.current { color: var(--t1); font-weight: 600; }
.nav-links a.current::after { transform: scaleX(1); }

.nav-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-shrink: 0;
}

/* Icon button shell — theme toggle, menu toggle, admin topbar actions */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  background: var(--bg-1);
  border: 1px solid var(--border-h);
  border-radius: var(--r-sm);
  color: var(--t2);
  font-size: 0.95rem;
  flex-shrink: 0;
  transition: color var(--dur-1), border-color var(--dur-1), background var(--dur-1);
}
.icon-btn:hover { color: var(--t1); border-color: var(--t3); background: var(--bg-3); }

/* Theme toggle — shows the icon for the theme you would switch TO. */
.theme-toggle .ico-sun  { display: none; }
.theme-toggle .ico-moon { display: block; }
:root[data-theme="dark"] .theme-toggle .ico-sun  { display: block; }
:root[data-theme="dark"] .theme-toggle .ico-moon { display: none; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .theme-toggle .ico-sun  { display: block; }
  :root:not([data-theme="light"]) .theme-toggle .ico-moon { display: none; }
}

/* Mobile menu toggle — hidden on desktop, shown at the nav breakpoint */
.nav-toggle { display: none; }

/* Dropdown panel — always in the DOM (not display:none) so the
   max-height/opacity transition can run. */
.nav-mobile {
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  pointer-events: none;
  transition: max-height var(--dur-2) ease, opacity var(--dur-1) ease;
}
.nav-mobile-links {
  display: flex;
  flex-direction: column;
  padding: 6px 0 var(--sp-4);
  border-top: 1px solid var(--border);
}
.nav-mobile-links a {
  display: block;
  padding: 13px 2px;
  font-size: 0.95rem;
  font-weight: 600;
  color: var(--t1);
  border-bottom: 1px solid var(--border);
}
.nav-mobile-links li:last-child a { border-bottom: none; }

/* ═══════════════════════════════════════════════
   FOOTER
═══════════════════════════════════════════════ */
footer {
  background: var(--bg-2);
  border-top: 1px solid var(--border);
  padding: var(--sp-10) var(--gutter) var(--sp-7);
  position: relative;
  z-index: 1;
}
.footer-inner {
  max-width: var(--maxw);
  margin: 0 auto;
  display: grid;
  grid-template-columns: minmax(200px, 1fr) minmax(0, 2fr);
  align-items: start;
  gap: var(--sp-8);
}
.footer-brand {
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.footer-tagline {
  display: flex;
  align-items: center;
  gap: 7px;
  font-size: 0.75rem;
  color: var(--t3);
  font-style: italic;
}
.footer-nav {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(118px, 1fr));
  gap: var(--sp-3) var(--sp-5);
}
.footer-nav a {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: var(--fs-xs);
  color: var(--t3);
  transition: color var(--dur-1);
}
.footer-nav a:hover { color: var(--t1); }
.footer-nav a[hidden] { display: none; }
.footer-copy { font-size: 0.74rem; color: var(--t3); margin-top: var(--sp-2); }

.footer-credit {
  max-width: var(--maxw);
  margin: var(--sp-7) auto 0;
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 10px;
}
.footer-credit-logo { height: 16px; width: auto; display: block; opacity: 0.9; }
.footer-credit-text {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  justify-content: center;
  gap: 6px;
  font-size: 0.75rem;
  color: var(--t3);
}
.footer-credit-text a { color: var(--t3); transition: color var(--dur-1); }
.footer-credit-text a:hover { color: var(--blue); }
/* The Texsenss mark is a dark-ink logo on transparent — lift it in dark mode. */
:root[data-theme="dark"] .footer-credit-logo { filter: invert(1) brightness(1.6); opacity: 0.75; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .footer-credit-logo { filter: invert(1) brightness(1.6); opacity: 0.75; }
}

/* Small shared separator dot used in trust rows and credit lines */
.sep { color: var(--t4); }

/* ═══════════════════════════════════════════════
   MOTION LAYER

   Two mechanisms, one visual result:
   • Browsers with scroll-driven animation (Chromium 115+, Safari 26+)
     run `.reveal` off the compositor via animation-timeline: view().
     No JS, no observer, and it re-runs if you scroll back up.
   • Everywhere else (Firefox today) js/theme.js adds `.v` with an
     IntersectionObserver and the transition below takes over.

   --i on a child sets its stagger index, so a grid cascades instead of
   popping in as one block.
═══════════════════════════════════════════════ */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-3) var(--ease) var(--reveal-delay, 0s),
              transform var(--dur-3) var(--ease) var(--reveal-delay, 0s);
}
.reveal.v { opacity: 1; transform: none; }

/* Legacy stagger hooks, still used in markup */
.d1 { --reveal-delay: 0.08s; }
.d2 { --reveal-delay: 0.16s; }
.d3 { --reveal-delay: 0.24s; }
.d4 { --reveal-delay: 0.32s; }

/* Index-based stagger: set --i on each child of a .stagger container */
.stagger > * { --reveal-delay: calc(var(--i, 0) * 0.07s); }

@keyframes revealIn {
  from { opacity: 0; transform: translateY(22px); }
  to   { opacity: 1; transform: none; }
}
@keyframes fadeUp {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}
@keyframes drawLine {
  from { transform: scaleX(0); }
  to   { transform: scaleX(1); }
}
@keyframes riseFlat {
  from { transform: rotateY(-20deg) rotateX(9deg) translateY(50px); }
  to   { transform: rotateY(-7deg) rotateX(3deg) translateY(0); }
}

@supports (animation-timeline: view()) {
  /* The observer never runs in these browsers (js/theme.js checks the
     same feature), so .reveal is driven purely by scroll position. */
  /* Both ends of the range stay inside the single named "entry" phase —
     0%-100% of an element's OWN height transiting the viewport — rather
     than mixing in "cover" (0%-100% of the much longer viewport+element
     transit). Mixing the two used to leave items well short of opacity:1
     once comfortably at rest mid-viewport: a plain mid-page .reveal only
     needed ~230px more of scroll past "cover 26%"/"cover 30%" to finish,
     which a long stacked list (FAQ, changelog, Free Data cards) often
     never supplied before the user's scroll naturally came to rest,
     reading as a permanent grey wash over everything below the fold.
     A pure "entry" range self-scales to each element's own height, so it
     reliably completes shortly after the element is fully visible,
     regardless of viewport height or how long the section is. */
  .reveal {
    opacity: 0;
    transform: none;
    animation: revealIn linear both;
    animation-timeline: view();
    animation-range: entry 6% entry 55%;
    transition: none;
  }
  /* A staggered child starts marginally later in its own range rather
     than on a timer — keeps the cascade tied to scroll, not the clock.
     The named range keyword (`entry`) must sit OUTSIDE calc() — only the
     length/percentage operand goes inside. The previous `calc(entry 6%
     + ...)` put it inside instead, which is invalid wherever the
     expression depends on a custom property (var(--i) isn't resolved
     until computed-value time, so the browser can't reject it at parse
     time the way it would a static invalid value) — the whole
     declaration silently computed to `normal` instead, which is what
     produced the FAQ's worst, longest-stuck-grey case specifically
     (the only section using .stagger). The end point is capped at 55-60%
     (not 90-100%) across all of these rules so a grid's second/third row
     finishes well before a reasonably-paced scroll — or a single Page
     Down jump — would land it mid-viewport; 90%+ left just enough of a
     gap for that to still read as a lingering grey wash. */
  .stagger > * {
    animation-range: entry calc(6% + (var(--i, 0) * 5%)) entry 60%;
  }
  .d1 { animation-range: entry 12% entry 60%; }
  .d2 { animation-range: entry 18% entry 60%; }
  .d3 { animation-range: entry 24% entry 60%; }
  .d4 { animation-range: entry 30% entry 60%; }

  /* Section hairlines draw themselves in */
  .section-rule::before {
    transform: scaleX(0);
    transform-origin: 50% 50%;
    animation: drawLine linear both;
    animation-timeline: view();
    animation-range: entry 0% entry 60%;
  }
}

/* ═══════════════════════════════════════════════
   REDUCED MOTION — required, do not remove
═══════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation: none !important;
    transition: none !important;
    scroll-behavior: auto !important;
  }
  /* Separate rule, not folded into the list above: ::details-content is a
     very new pseudo-element (Chromium-only today) — an unknown pseudo in a
     plain comma-separated selector invalidates the WHOLE rule in browsers
     that don't recognize it, which would silently kill this kill switch
     everywhere else too. Same reason ::-webkit-scrollbar always gets its
     own rule elsewhere in this file. */
  *::details-content {
    animation: none !important;
    transition: none !important;
  }
  .reveal { opacity: 1 !important; transform: none !important; }
  .section-rule::before { transform: none !important; }
}

/* ═══════════════════════════════════════════════
   RESPONSIVE — shared chrome only.
   Page-specific breakpoints live in each page.
═══════════════════════════════════════════════ */
@media (max-width: 1000px) {
  .nav-links      { display: none; }
  .nav-office-btn { display: none; }
  .nav-toggle     { display: inline-flex; }
  .nav-mobile.open { max-height: 520px; opacity: 1; pointer-events: auto; }
}

@media (max-width: 760px) {
  .footer-inner {
    grid-template-columns: 1fr;
    gap: var(--sp-6);
  }
  .footer-nav { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 420px) {
  .nav-cta-label { display: none; }
  .nav-actions .btn-primary { padding: 10px 13px; }
}
