/* =========================================================================
   ALPHA ATTRIBUTION - design system
   Palette and type inspired by CRED (cred.club): pure black ground, electric
   blue #0000EE accent, display serif + geometric sans + mono for figures.
   Gilroy and Denton are commercial faces, so the closest free equivalents
   are used: Outfit (for Gilroy) and Instrument Serif (for Denton).
   Overpass Mono is what CRED actually ships, and it is free.
   ========================================================================= */

@import url('https://fonts.googleapis.com/css2?family=Instrument+Serif:ital@0;1&family=Outfit:wght@200;300;400;500;600;700&family=Overpass+Mono:wght@300;400;600;700&display=swap');

:root {
  /* Tell the browser this page is light. Without it, an OS in dark mode draws
     every native surface dark: the page scrollbar, the <select> picker on touch,
     and the <select> on desktop if the custom listbox never initialises. This
     is the root cause of the dark dropdown, not just its symptom. */
  color-scheme: light;
  accent-color: #0000EE;

  /* ground - pure white */
  --bg:           #FFFFFF;
  --surface:      #FAFAFA;
  --surface-2:    #F4F4F6;
  --surface-3:    #EDEDF0;

  /* ink */
  --ink:          #000000;
  --text:         rgba(0,0,0,0.92);
  --text-dim:     rgba(0,0,0,0.62);   /* 6.20:1 on white */
  --text-faint:   rgba(0,0,0,0.56);   /* 4.94:1 on white - AA */

  /* lines */
  --line:         rgba(0,0,0,0.10);
  --line-mid:     rgba(0,0,0,0.18);
  --line-strong:  rgba(0,0,0,0.34);
  /* Borders that define an interactive control need 3:1 (WCAG 1.4.11).
     --line-mid is only 1.53:1, which is fine for decorative hairlines. */
  --line-control: rgba(0,0,0,0.42);

  /* accent - CRED electric blue, used at full strength now that the ground
     is white and it no longer needs lightening to stay legible */
  --blue:         #0000EE;
  --blue-glow:    rgba(0,0,238,0.22);

  /* data semantics - darkened so they hold contrast against white */
  --pos:          #00875A;              /* 4.55:1 on white */
  --pos-dim:      rgba(0,135,90,0.10);
  --neg:          #D91F35;              /* 5.00:1 on white */
  --neg-dim:      rgba(217,31,53,0.10);
  /* On its own tint the base colours drop to 3.99:1 and 4.27:1, so the status
     chips use darker variants. */
  --pos-on-tint:  #00694A;
  --neg-on-tint:  #B3162A;

  /* type */
  --font-display: 'Instrument Serif', Georgia, 'Times New Roman', serif;
  --font-ui:      'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', Helvetica, sans-serif;
  --font-mono:    'Overpass Mono', ui-monospace, 'SF Mono', Menlo, monospace;

  /* motion - the easing curves award sites lean on */
  --ease-out-expo:  cubic-bezier(0.16, 1, 0.30, 1);
  --ease-out-quart: cubic-bezier(0.25, 1, 0.50, 1);
  --ease-in-out:    cubic-bezier(0.76, 0, 0.24, 1);

  --gutter: clamp(20px, 5vw, 90px);
  --nav-h: 84px;
  --maxw: 1440px;
}

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

html {
  background: var(--bg);
  /* The nav is fixed and ~60px tall; without this every #anchor lands with its
     heading tucked underneath it. */
  scroll-padding-top: 88px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: var(--font-ui);
  font-weight: 300;
  color: var(--text);
  background: var(--bg);
  line-height: 1.55;
  overflow-x: hidden;
  font-size: 16px;
}

img, svg { display: block; max-width: 100%; }
button, input, select { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }

::selection { background: var(--blue); color: #fff; }

/* --------------------------- film grain overlay -------------------------- */
/* A fixed, very low-opacity turbulence layer. Reads as texture, not noise. */
/* Kept only marginally larger than the viewport. An inset of -120% would make
   this a ~4400x2400 composited layer repainting forever, which is both wasteful
   and enough to stall the compositor. -6% gives the shift room to move without
   exposing an edge. */
.grain {
  position: fixed; inset: -6%;
  z-index: 9998; pointer-events: none;
  opacity: 0.055;
  mix-blend-mode: multiply;   /* on white the grain must darken, not lighten */
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='300' height='300' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain-shift 800ms steps(3) infinite;
}
@keyframes grain-shift {
  0%   { transform: translate3d(0,0,0); }
  33%  { transform: translate3d(-2%, 1%, 0); }
  66%  { transform: translate3d(1%, -2%, 0); }
  100% { transform: translate3d(0,0,0); }
}

/* ----------------------------- custom cursor ----------------------------- */
.cursor-dot, .cursor-ring {
  position: fixed; top: 0; left: 0;
  z-index: 9999; pointer-events: none;
  border-radius: 50%;
  /* Hidden until the pointer actually moves. These are positioned purely by
     GSAP writing x/y, so before the first pointermove they sit at 0,0 - a dot
     and a ring stuck in the corner on every load, and permanently so for
     keyboard users or when GSAP is unavailable. */
  opacity: 0;
  transition: opacity .3s ease;
}
html.cursor-live .cursor-dot, html.cursor-live .cursor-ring { opacity: 1; }
.cursor-dot  { width: 6px; height: 6px; background: var(--ink); margin: -3px 0 0 -3px; }
.cursor-ring {
  width: 38px; height: 38px; margin: -19px 0 0 -19px;
  border: 1px solid rgba(0,0,0,0.42);
  transition: width .35s var(--ease-out-expo), height .35s var(--ease-out-expo),
              margin .35s var(--ease-out-expo), border-color .35s var(--ease-out-expo),
              opacity .3s ease;
}
.cursor-ring.is-hover {
  width: 68px; height: 68px; margin: -34px 0 0 -34px;
  border-color: var(--blue);
}
@media (hover: none), (pointer: coarse) {
  .cursor-dot, .cursor-ring { display: none; }
}

/* ------------------------------ typography ------------------------------- */
.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: 0.92;
  letter-spacing: -0.025em;
}
/* Capped at 9.5rem, not 12: .wrap stops widening at 1440px while 11.5vw
   keeps growing, which broke the two-line composition on large monitors. */
h1.display { font-size: clamp(2.6rem, 11.5vw, 9.5rem); }
h2.display { font-size: clamp(2.4rem, 6.4vw, 6rem); }
h3.display { font-size: clamp(1.7rem, 3.2vw, 3rem); }
.italic { font-style: italic; }

.eyebrow {
  font-family: var(--font-mono);
  font-size: 11px; font-weight: 400;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--text-faint);
}
.lede { font-size: clamp(1.05rem, 1.55vw, 1.4rem); color: var(--text-dim); max-width: 62ch; font-weight: 300; }
.mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }
.accent { color: var(--blue); }
.pos { color: var(--pos); }
.neg { color: var(--neg); }

/* -------------------------------- layout --------------------------------- */
.wrap { width: 100%; max-width: calc(var(--maxw) + 2 * var(--gutter)); margin: 0 auto; padding: 0 var(--gutter); }
section { position: relative; }
section[id], #top { scroll-margin-top: var(--nav-h); }
/* Vertical only. Using the `padding` shorthand here would reset the
   horizontal gutter that .wrap sets on the same element. */
.section-pad { padding-top: clamp(90px, 13vh, 190px); padding-bottom: clamp(90px, 13vh, 190px); }
.rule { height: 1px; background: var(--line); width: 100%; }

.section-head { display: flex; align-items: baseline; gap: 18px; margin-bottom: 14px; }
.section-num {
  font-family: var(--font-mono); font-size: 12px;
  color: var(--blue); letter-spacing: 0.1em;
}

/* --------------------------------- nav ----------------------------------- */
.nav {
  position: fixed; top: 0; left: 0; right: 0; z-index: 900;
  padding: 20px 0;
  /* No difference blending here. On a white ground it would invert dark text
     to white and make the nav disappear. */
  color: var(--text);
  background: linear-gradient(to bottom, rgba(255,255,255,0.92), rgba(255,255,255,0));
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
/* Shares .wrap's measure so the logo lines up with the content column instead
   of hugging the window edge on a wide monitor. */
.nav-inner {
  width: 100%; max-width: calc(var(--maxw) + 2 * var(--gutter));
  margin: 0 auto; padding: 0 var(--gutter);
  display: flex; align-items: center; justify-content: space-between;
}
.nav-mark { font-family: var(--font-mono); font-size: 12px; letter-spacing: 0.2em; text-transform: uppercase; }
.nav-links { display: flex; gap: 30px; }
.nav-link {
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.16em; text-transform: uppercase;
  position: relative; padding: 12px 0 3px; color: rgba(0,0,0,0.55);
  transition: color .3s ease;
}
.nav-link::after {
  content: ''; position: absolute; left: 0; bottom: 0; height: 1px; width: 100%;
  background: currentColor; transform: scaleX(0); transform-origin: right;
  transition: transform .5s var(--ease-out-expo);
}
.nav-link:hover { color: var(--ink); }
.nav-link:hover::after { transform: scaleX(1); transform-origin: left; }
@media (max-width: 720px) {
  /* Previously display:none, which left a fixed bar containing only a logo and
     no way to reach any section on the longest form of the page. */
  .nav { padding-bottom: 12px; }
  .nav-inner { gap: 14px; }
  .nav-links {
    gap: 18px; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; max-width: 58vw;
  }
  .nav-links::-webkit-scrollbar { display: none; }
  .nav-link { white-space: nowrap; font-size: 10px; }
}

/* -------------------------------- hero ----------------------------------- */
.hero { min-height: 100svh; display: flex; flex-direction: column; justify-content: center; padding-top: 80px; }
/* Block so the mask actually clips, and so each line breaks on its own.
   The padding/negative-margin pair gives descenders room inside the mask
   without adding visible space between the lines. */
.hero-line {
  display: block; overflow: hidden;
  padding-bottom: 0.14em; margin-bottom: -0.14em;
}
/* Each character sits in that mask and rises into place. */
.char { display: inline-block; will-change: transform; }
/* Dropped once the intro has played, so 30 promoted layers do not linger. */
.char.is-settled { will-change: auto; }
.hero-meta {
  display: flex; flex-wrap: wrap; gap: 40px;
  margin-top: clamp(40px, 6vh, 80px); padding-top: 28px; border-top: 1px solid var(--line);
}
.hero-meta-item { min-width: 130px; }
.hero-meta-label { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.2em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 8px; }
.hero-meta-value { font-size: 1rem; color: var(--text); }

.scroll-cue {
  position: absolute; bottom: 34px; left: 50%; transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.scroll-cue-line { width: 1px; height: 46px; background: linear-gradient(to bottom, transparent, var(--line-strong)); position: relative; overflow: hidden; }
.scroll-cue-line::after {
  content: ''; position: absolute; top: -46px; left: 0; width: 1px; height: 46px;
  background: linear-gradient(to bottom, transparent, var(--blue));
  animation: cue 2.1s var(--ease-in-out) infinite;
}
@keyframes cue { 0% { top: -46px; } 60%,100% { top: 46px; } }

/* ------------------------------- ticker ---------------------------------- */
.ticker {
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  padding: 18px 0; overflow: hidden; white-space: nowrap;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.ticker-track { display: inline-flex; gap: 56px; will-change: transform; }
.ticker-item {
  font-family: var(--font-mono); font-size: 13px; letter-spacing: 0.06em;
  display: inline-flex; align-items: center; gap: 12px; color: var(--text-dim);
}
.ticker-item b { color: var(--text); font-weight: 400; }

/* ------------------------------- controls -------------------------------- */
/* Positioned and lifted so the open dropdown paints above the metrics strip
   below it. The reveal animation leaves a transform on both elements, and a
   transform creates a stacking context - which traps the dropdown's own
   z-index inside .controls and lets the later sibling win on DOM order. */
.controls {
  display: flex; flex-wrap: wrap; gap: 12px; align-items: center;
  position: relative; z-index: 30;
}

.pill {
  position: relative; overflow: hidden; isolation: isolate;
  border: 1px solid var(--line-control); border-radius: 999px;
  padding: 11px 22px;
  font-family: var(--font-mono); font-size: 11px;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--text-dim);
  transition: color .4s var(--ease-out-expo), border-color .4s var(--ease-out-expo);
  will-change: transform;
}
/* Fill sweeps up from the bottom on hover. */
.pill::before {
  content: ''; position: absolute; inset: 0; background: var(--ink);
  transform: translateY(101%); transition: transform .55s var(--ease-out-expo); z-index: -1;
}
.pill span { position: relative; z-index: 1; }
.pill:hover { color: var(--bg); border-color: var(--ink); }
.pill:hover::before { transform: translateY(0); }
.pill[aria-pressed="true"] { color: var(--bg); border-color: var(--ink); }
.pill[aria-pressed="true"]::before { transform: translateY(0); }

.select-wrap { position: relative; display: inline-block; }
.select-wrap::after {
  content: ''; position: absolute; right: 16px; top: 50%; width: 6px; height: 6px;
  border-right: 1px solid var(--text-dim); border-bottom: 1px solid var(--text-dim);
  transform: translateY(-70%) rotate(45deg); pointer-events: none;
  transition: transform .28s var(--ease-out-expo);
}
.select-wrap.is-open::after { transform: translateY(-20%) rotate(-135deg); }
select {
  appearance: none; -webkit-appearance: none;
  background: var(--surface-2); border: 1px solid var(--line-control); border-radius: 3px;
  padding: 13px 46px 13px 17px; cursor: pointer;
  /* 16px, not 15: iOS Safari zooms the page on focus for anything smaller, and
     touch is exactly where the native select is still in use. */
  font-family: var(--font-ui); font-size: 16px; font-weight: 300;
  transition: border-color .35s ease, background .35s ease;
}
select:hover { border-color: var(--line-strong); background: var(--surface-3); }
select:focus-visible { outline: 1px solid var(--blue); outline-offset: 2px; }

/* ------------------------- custom dropdown (listbox) ---------------------- */
/* A native <select> cannot style its open popup - the OS draws that, and on a
   white page macOS renders a dark panel over it. This replaces the visual
   control while leaving the real <select> in the DOM driving everything. */
.cselect { position: relative; display: inline-block; }
/* Above any sibling control while the list is open. */
.cselect.is-open { z-index: 40; }

/* The native control stays in the accessibility tree's reach but out of sight.
   display:none would remove it from the form and break value syncing. */
.cselect-native {
  position: absolute; width: 1px; height: 1px;
  /* padding must be zeroed: with border-box the select's own 13px/46px padding
     keeps it ~63px wide no matter what width says. */
  padding: 0; border: 0; margin: -1px;
  opacity: 0; pointer-events: none;
  clip-path: inset(50%); overflow: hidden;
}

.cselect-btn {
  appearance: none;
  background: var(--surface-2);
  border: 1px solid var(--line-control);
  border-radius: 3px;
  padding: 13px 46px 13px 17px;
  font-family: var(--font-ui); font-size: 15px; font-weight: 300;
  color: var(--text);
  cursor: pointer; text-align: left; min-width: 190px;
  transition: border-color .3s ease, background .3s ease;
}
.cselect-btn:hover { border-color: var(--line-strong); background: var(--surface-3); }
.cselect.is-open .cselect-btn { border-color: var(--blue); background: var(--bg); }

.cselect-list {
  position: absolute; z-index: 300;
  top: calc(100% + 6px); left: 0; min-width: 100%;
  background: #fff;
  border: 1px solid var(--line-control);
  border-radius: 4px;
  box-shadow: 0 14px 38px rgba(0,0,0,0.15), 0 2px 6px rgba(0,0,0,0.08);
  padding: 5px; margin: 0; list-style: none;
  max-height: 300px; overflow-y: auto;
  animation: cselect-in .22s var(--ease-out-expo);
}
@keyframes cselect-in {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}

.cselect-list { scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.28) transparent; }
.cselect-list::-webkit-scrollbar { width: 8px; }
.cselect-list::-webkit-scrollbar-thumb { background: rgba(0,0,0,0.22); border-radius: 4px; }

.cselect-opt {
  padding: 11px 14px; border-radius: 3px; cursor: pointer;
  font-size: 15px; font-weight: 300; color: var(--text);
  white-space: nowrap;
}
.cselect-opt.is-active { background: var(--blue); color: #fff; }
/* A tick rather than a background, so the selected row stays readable when it
   is also the active (highlighted) one. */
.cselect-opt[aria-selected="true"] { font-weight: 500; }
.cselect-opt[aria-selected="true"]::before { content: "\2713\00a0\00a0"; }
.cselect-opt:not([aria-selected="true"])::before { content: "\00a0\00a0\00a0\00a0"; }

@media (prefers-reduced-motion: reduce) { .cselect-list { animation: none; } }

/* ------------------------------ focus states ------------------------------ */
/* Keyboard users need to see where they are. One consistent ring everywhere. */
:where(a, button, select, input, .cselect-btn, .cselect-list, [tabindex]):focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
  /* No border-radius here. :where() has zero specificity, so this rule ties
     with .pill and wins on order, which squared off the pill buttons on focus.
     Outlines already follow the element's own radius. */
}
.cselect-list:focus-visible { outline-offset: 1px; }
/* Range thumbs draw their own ring; Firefox needs it stated separately. */
input[type=range]:focus-visible::-moz-range-thumb { box-shadow: 0 0 0 7px var(--blue-glow); }

/* Stop iOS painting its own grey flash over every tap. */
a, button, select, input, .cselect-opt, [tabindex] {
  -webkit-tap-highlight-color: rgba(0,0,238,0.12);
}

/* The one horizontal scroller on the page, styled so it does not appear as a
   default dark bar. */
.table-scroll { scrollbar-width: thin; scrollbar-color: rgba(0,0,0,0.28) transparent; }
.table-scroll::-webkit-scrollbar { height: 8px; }
.table-scroll::-webkit-scrollbar-track { background: transparent; }
.table-scroll::-webkit-scrollbar-thumb {
  background: rgba(0,0,0,0.22); border-radius: 4px;
}
.table-scroll::-webkit-scrollbar-thumb:hover { background: rgba(0,0,0,0.36); }

/* -------------------------------- metrics -------------------------------- */
.metrics {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(165px, 1fr));
  border-top: 1px solid var(--line);
}
.metric {
  padding: 26px 24px 26px 0; border-right: 1px solid var(--line);
  position: relative;
}
.metric:last-child { border-right: 0; }
.metric-label {
  font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.18em;
  text-transform: uppercase; color: var(--text-faint); margin-bottom: 12px;
}
.metric-value {
  font-family: var(--font-mono); font-size: clamp(1.5rem, 2.6vw, 2.3rem);
  font-weight: 300; letter-spacing: -0.02em; font-variant-numeric: tabular-nums;
}
.metric-delta { font-family: var(--font-mono); font-size: 11px; margin-top: 7px; color: var(--text-faint); }
/* auto-fit gives 2-4 columns between 375 and 917px; without a gap the cells
   sit flush against each other once the divider is removed. */
.metrics { column-gap: 22px; }
@media (max-width: 640px) {
  .metrics { grid-template-columns: repeat(2, 1fr); }
  .metric { border-right: 0; border-bottom: 1px solid var(--line); padding-right: 0; }
}
@media (max-width: 400px) { .metrics { grid-template-columns: 1fr; } }

/* -------------------------------- table ---------------------------------- */
.table-scroll { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-family: var(--font-mono); font-size: 13px; }
thead th {
  text-align: right; padding: 12px 14px; font-weight: 400; font-size: 10px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--text-faint);
  border-bottom: 1px solid var(--line-mid); white-space: nowrap;
}
thead th:first-child, tbody td:first-child { text-align: left; }
tbody td {
  text-align: right; padding: 14px; border-bottom: 1px solid var(--line);
  font-variant-numeric: tabular-nums; white-space: nowrap;
  transition: background .3s ease;
}
/* An inline background is written on the numeric cells by heat(), which
   beats any background here - shade with a shadow instead. */
tbody tr:hover td { box-shadow: inset 0 0 0 999px rgba(0,0,0,0.030); }
tbody td:first-child { font-family: var(--font-ui); font-size: 14px; }

/* -------------------------------- charts --------------------------------- */
.chart-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(16px, 2vw, 30px); }
@media (max-width: 900px) { .chart-grid { grid-template-columns: 1fr; } }
.chart-title { font-size: 14px; color: var(--text); margin-bottom: 3px; }
.chart-sub { font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-faint); margin-bottom: 20px; }
.chart svg { width: 100%; height: auto; overflow: visible; }
.bar { transform-box: fill-box; transform-origin: bottom center; }
.bar.is-neg { transform-origin: top center; }
.axis-label { font-family: var(--font-mono); font-size: 9.5px; fill: rgba(0,0,0,0.56); letter-spacing: 0.06em; }
.grid-line { stroke: rgba(0,0,0,0.10); stroke-width: 1; }
.zero-line { stroke: rgba(0,0,0,0.46); stroke-width: 1; }
.legend { display: flex; gap: 20px; flex-wrap: wrap; margin-bottom: 16px; }
.legend-item { display: inline-flex; align-items: center; gap: 8px; font-family: var(--font-mono); font-size: 10px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-dim); }
.swatch { width: 9px; height: 9px; border-radius: 1px; }
.note {
  font-size: 13px; color: var(--text-dim); margin-top: 16px;
  padding-left: 14px; border-left: 1px solid var(--line-mid); line-height: 1.6;
}
.note b { color: var(--text); font-weight: 400; }

/* ------------------------------- sliders --------------------------------- */
/* Keyed to the container, not the viewport. The old viewport query fired at
   560px, but the real squeeze happens when the sandbox grid flips to two
   columns around 744px - the track dropped to ~84px of travel there while the
   viewport query never fired. */
#f3-sliders, #f3-shocks { container-type: inline-size; }
.slider-row { display: grid; grid-template-columns: 148px 1fr 62px; gap: 18px; align-items: center; padding: 15px 0; border-bottom: 1px solid var(--line); }
@container (max-width: 420px) {
  .slider-row { grid-template-columns: 1fr auto; gap: 4px 10px; padding: 12px 0; }
  .slider-row input[type=range] { grid-column: 1 / -1; }
  .slider-val { text-align: right; }
}
/* No container-query support: fall back to the viewport. */
@supports not (container-type: inline-size) {
  @media (max-width: 900px) { .slider-row { grid-template-columns: 110px 1fr 52px; gap: 10px; } }
}
.slider-name { font-size: 14px; color: var(--text-dim); }
.slider-val { font-family: var(--font-mono); font-size: 14px; text-align: right; font-variant-numeric: tabular-nums; }
input[type=range] {
  -webkit-appearance: none; appearance: none; width: 100%; height: 22px;
  background: transparent; cursor: grab;
}
input[type=range]:active { cursor: grabbing; }
input[type=range]::-webkit-slider-runnable-track { height: 3px; border-radius: 2px; background: rgba(0,0,0,0.34); }
input[type=range]::-moz-range-track { height: 3px; border-radius: 2px; background: rgba(0,0,0,0.34); }
input[type=range]::-webkit-slider-thumb {
  -webkit-appearance: none; width: 15px; height: 15px; border-radius: 50%;
  background: var(--ink); margin-top: -6px;
  transition: transform .3s var(--ease-out-expo), box-shadow .3s ease;
}
input[type=range]::-moz-range-thumb {
  width: 15px; height: 15px; border: 0; border-radius: 50%; background: var(--ink);
  transition: transform .3s var(--ease-out-expo), box-shadow .3s ease;
}
input[type=range]:hover::-webkit-slider-thumb { transform: scale(1.5); box-shadow: 0 0 0 7px var(--blue-glow); }
input[type=range]:hover::-moz-range-thumb    { transform: scale(1.5); box-shadow: 0 0 0 7px var(--blue-glow); }
input[type=range]:focus-visible::-webkit-slider-thumb { box-shadow: 0 0 0 7px var(--blue-glow); }

.status {
  font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.1em;
  text-transform: uppercase; padding: 12px 16px; border-radius: 3px; margin-top: 18px;
  border: 1px solid var(--line-mid);
}
.status.ok   { color: var(--pos-on-tint); border-color: rgba(0,135,90,0.45); background: var(--pos-dim); }
.status.warn { color: var(--neg-on-tint); border-color: rgba(217,31,53,0.45); background: var(--neg-dim); }

/* ------------------------------- verdict --------------------------------- */
.verdict {
  border-left: 2px solid var(--blue);
  padding: clamp(18px, 4vw, 26px) clamp(16px, 4vw, 30px);
  background: linear-gradient(90deg, rgba(0,0,238,0.05), transparent 70%);
  font-size: clamp(1rem, 1.25vw, 1.16rem); line-height: 1.72; color: var(--text);
  font-weight: 300;
}

/* ------------------------------- formula --------------------------------- */
.formula {
  font-family: var(--font-mono); font-size: clamp(0.85rem, 1.5vw, 1.2rem);
  padding: 30px 0; border-bottom: 1px solid var(--line);
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 12px;
}
.formula-name { color: var(--text-faint); font-size: 11px; letter-spacing: 0.18em; text-transform: uppercase; min-width: 130px; }
.formula-body { color: var(--text); }
.formula-body em { color: var(--blue); font-style: normal; }

/* -------------------------------- footer --------------------------------- */
.footer { padding-top: 90px; padding-bottom: 50px; border-top: 1px solid var(--line); }
.footer-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 40px; }
.footer small { display: block; font-family: var(--font-mono); font-size: 11px; color: var(--text-faint); line-height: 1.9; }

/* ---------------------------- visually hidden ----------------------------- */
/* Present for assistive tech, absent for everyone else. Used for the chart
   data tables and the live region. */
.visually-hidden {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ------------------------------- ticker ----------------------------------- */
.ticker-wrap { position: relative; }
.ticker-toggle {
  position: absolute; right: 10px; top: 50%; transform: translateY(-50%);
  z-index: 2; padding: 7px 14px; border-radius: 999px;
  border: 1px solid var(--line-control); background: var(--bg);
  font-family: var(--font-mono); font-size: 10px;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-dim);
  transition: color .3s ease, border-color .3s ease;
}
.ticker-toggle:hover { color: var(--ink); border-color: var(--ink); }
@media (max-width: 560px) { .ticker-toggle { right: 6px; padding: 6px 10px; } }

/* --------------------------- touch and pressed ---------------------------- */
/* A tap on a touch device leaves :hover latched until the user taps elsewhere,
   so "Put it back" stays inverted black and reads as if it were selected.
   Reset the hover treatments where there is no real hover. */
@media (hover: none) {
  .pill:hover { color: var(--text-dim); border-color: var(--line-control); }
  .pill:hover::before { transform: translateY(101%); }
  .pill[aria-pressed="true"]:hover { color: var(--bg); border-color: var(--ink); }
  .pill[aria-pressed="true"]:hover::before { transform: translateY(0); }
  select:hover, .cselect-btn:hover { border-color: var(--line-control); background: var(--surface-2); }
  .cselect-opt:hover { background: transparent; }
  tbody tr:hover td { box-shadow: none; }
  input[type=range]:hover::-webkit-slider-thumb { transform: none; box-shadow: none; }
  input[type=range]:hover::-moz-range-thumb { transform: none; box-shadow: none; }
}

/* Pressed feedback. The pills carry data-magnetic, and the motion layer writes
   an inline transform on them via gsap.quickTo - a transform here would be
   silently overridden, so the inner span is scaled instead. */
.pill span { display: inline-block; transition: transform .12s ease; }
.pill:active span { transform: scale(0.95); }
.cselect-btn { transition: border-color .3s ease, background .3s ease, transform .12s ease; }
.cselect-btn:active { transform: scale(0.985); }
.cselect-opt:active { background: rgba(0,0,238,0.12); }

/* Coarse pointers need a bigger grab target than the 15px visual thumb. */
@media (pointer: coarse) {
  input[type=range] { height: 34px; }
  input[type=range]::-webkit-slider-thumb { width: 24px; height: 24px; margin-top: -11px; }
  input[type=range]::-moz-range-thumb { width: 24px; height: 24px; }
}

/* Windows High Contrast strips custom fills; keep the controls outlined. */
@media (forced-colors: active) {
  .pill, .cselect-btn, select, .cselect-list { border: 1px solid ButtonBorder; }
  .pill::before { display: none; }
  .bar { forced-color-adjust: none; }
}


/* --------------------------- chart value tooltip -------------------------- */
/* Replaces reliance on the native <title>, which never fires on a tap. */
.chart-tip {
  position: fixed; z-index: 950; pointer-events: none;
  background: var(--ink); color: #fff;
  font-family: var(--font-mono); font-size: 12px;
  padding: 8px 12px; border-radius: 4px;
  box-shadow: 0 8px 24px rgba(0,0,0,0.22);
  white-space: nowrap;
}

/* --------------------------- reveal base states --------------------------- */
/* Only applied once JS is confirmed running, so content stays visible if the
   script fails to load. GSAP animates these to their resting state. */
html.js-ready [data-reveal] { opacity: 0; }
html.js-ready .char { transform: translateY(105%); }

@media (prefers-reduced-motion: reduce) {
  html.js-ready [data-reveal], html.js-ready .char { opacity: 1 !important; transform: none !important; }
  .grain { animation: none; }
  .scroll-cue-line::after { animation: none; }
  *, *::before, *::after { transition-duration: 0.01ms !important; animation-duration: 0.01ms !important; }
}
