/* tool.css — shared tool-page styles.
   Pages set --accent / --accent-dim to their area colour; page-local <style>
   loaded after this sheet can still override. Prefer var(--accent) here so
   amber/green/indigo/etc. all work without per-page copies of the chrome. */

*{ box-sizing:border-box; }
html{ -webkit-text-size-adjust:100%; }
svg{ user-select:none; -webkit-user-select:none; -moz-user-select:none; }
body{
  margin:0;
  background:
    radial-gradient(1200px 600px at 78% -10%, var(--bg-rad-1) 0%, transparent 55%),
    radial-gradient(900px 500px at 0% 0%, var(--bg-rad-2) 0%, transparent 50%),
    var(--ink);
  color:var(--text);
  font-family:'Inter',system-ui,sans-serif;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
.wrap{ max-width:1180px; margin:0 auto; padding:26px 20px 64px; }
@media (max-width:560px){
  .wrap{ padding:18px 14px 48px; }
  header.mast{ align-items:flex-start; }
  .mast .right{ text-align:left; width:100%; }
  .refbar{ margin:18px 0 14px; font-size:11px; }
  section.block{ margin-top:48px; }
  .grid{ gap:12px; }
  .panel{ padding:14px; border-radius:14px; }
  .hero{ padding:12px; border-radius:14px; }
  .playbar, .controls{ gap:8px; margin-top:10px; }
  .playbtn{ padding:10px 14px; min-height:44px; } /* touch target */
  .field{ margin-bottom:12px; }
  .ro{ padding:11px 12px; }
  .ro .v{ font-size:clamp(14px,4.2vw,18px); }
  /* simulators: keep the viz legible, avoid horizontal page scroll */
  .hero svg, .panel svg, #anim, #springViz, #forceChart, #step,
  #dLoad, #dShear, #dMoment, #dDefl, svg[id$="Svg"], svg[id$="Chart"]{
    max-width:100%; height:auto;
  }
}
@media (max-width:400px){
  .ro-grid,
  .ro-grid.primary,
  .ro-grid.secondary{ grid-template-columns:1fr 1fr; gap:8px; }
  .seg{ grid-template-columns:1fr 1fr; }
  .seg.seg3{ grid-template-columns:1fr 1fr 1fr; }
}

/* ---- chrome: crumb, refbar, mast ---- */
nav.crumb{
  display:flex; align-items:center; gap:8px; flex-wrap:wrap;
  padding-bottom:13px; margin-bottom:7px;
  font-family:'IBM Plex Mono',monospace; font-size:11.5px;
}
nav.crumb a{ color:var(--muted); text-decoration:none; }
nav.crumb a:hover{ color:var(--text); }
nav.crumb .sep{ color:var(--muted-2); }
nav.crumb .here{ color:var(--accent); font-weight:600; letter-spacing:.03em; }
.refbar{
  display:flex; align-items:center; gap:9px; padding:9px 13px; margin:28px 0 18px;
  background:linear-gradient(90deg,var(--banner-a),var(--banner-b));
  border:1px solid var(--line-soft); border-radius:10px;
  font-size:11.5px; color:var(--muted-2);
}
.refbar b{ color:var(--muted); font-weight:600; }
.refbar svg{ width:14px; height:14px; flex:none; color:var(--amber); }
header.mast{
  display:flex; align-items:flex-end; justify-content:space-between;
  gap:20px; flex-wrap:wrap; padding-bottom:18px;
  border-bottom:1px solid var(--line-soft); margin-bottom:20px;
}
.brand{ display:flex; align-items:center; gap:13px; }
.glyph{ width:42px; height:42px; flex:none; }
.mast h1{
  font-family:'Space Grotesk',sans-serif; font-weight:700;
  font-size:clamp(22px,3vw,30px); letter-spacing:-.02em; margin:0; line-height:1;
}
.mast .sub{ font-size:12.5px; color:var(--muted); margin-top:5px; }
.mast .kicker{
  font-size:10px; letter-spacing:.22em; text-transform:uppercase;
  color:var(--accent); font-weight:600; font-family:'IBM Plex Mono',monospace;
}
.mast .right{ font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted-2); text-align:right; }
.mast .right b{ color:var(--text); font-weight:600; }

/* ---- layout grid (sidebar + main) ---- */
.grid{ display:grid; grid-template-columns:300px 1fr; gap:18px; align-items:start; }
@media (max-width:960px){ .grid{ grid-template-columns:1fr; } }
/* CSS Grid blowout: nested content must be allowed to shrink below content min-size */
.grid > *{ min-width:0; }

/* ---- panels ---- */
.panel{
  background:linear-gradient(180deg,var(--panel),var(--ink-2));
  border:1px solid var(--line); border-radius:16px; padding:18px;
}
.panel + .panel{ margin-top:14px; }
.panel .head{ display:flex; align-items:center; gap:9px; margin-bottom:14px; }
.panel .head .dot{
  width:8px; height:8px; border-radius:50%;
  background:var(--accent); box-shadow:0 0 10px var(--accent);
}
.panel .head h2{ font-family:'Space Grotesk',sans-serif; font-size:15px; font-weight:600; margin:0; }
.panel .head .tag{
  margin-left:auto; font-size:9.5px; letter-spacing:.14em; text-transform:uppercase;
  color:var(--muted-2); font-family:'IBM Plex Mono',monospace;
}

/* ---- fields, selects, ranges ---- */
.field{ margin-bottom:14px; }
.field:last-child{ margin-bottom:0; }
.field > label{
  display:flex; justify-content:space-between;
  font-size:10.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted-2); font-weight:600; margin-bottom:7px;
}
.field > label .vv{
  font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--text);
  text-transform:none; letter-spacing:0; font-weight:600;
}
.field > label .term{ color:var(--accent); font-family:'IBM Plex Mono',monospace; }

select{
  width:100%; background:var(--ink); border:1px solid var(--line); border-radius:9px;
  color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:12.5px;
  padding:9px 9px; outline:none; cursor:pointer;
}
select:focus{
  border-color:var(--accent);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 22%,transparent);
}

.slider{ display:flex; align-items:center; gap:11px; }
.slider .val{
  font-family:'IBM Plex Mono',monospace; font-size:12.5px; color:var(--text);
  min-width:54px; text-align:right;
}

/* Range fill: --fill is 0%–100% of value (set by rot.js). Paint with background-size so
   the coloured bar is exactly as wide as the value fraction — no dual track layers that
   can drift from the thumb. Firefox uses native ::-moz-range-progress instead. */
input[type="range"]{
  -webkit-appearance:none; appearance:none; width:100%; height:4px; border-radius:3px;
  background-color:var(--line);
  background-image:linear-gradient(var(--c,var(--accent)), var(--c,var(--accent)));
  background-size:var(--fill,0%) 100%;
  background-repeat:no-repeat;
  background-position:left center;
  outline:none; flex:1; cursor:pointer;
}
input[type="range"]::-webkit-slider-runnable-track{
  height:4px; border-radius:3px; background:transparent; /* fill lives on the input itself */
}
input[type="range"]::-webkit-slider-thumb{
  -webkit-appearance:none; width:17px; height:17px; border-radius:50%;
  background:var(--c,var(--accent)); border:2px solid var(--ink);
  box-shadow:0 0 0 3px color-mix(in srgb,var(--c,var(--accent)) 28%,transparent);
  cursor:pointer; margin-top:-6.5px; /* centre 17px thumb on 4px track */
  position:relative; z-index:1;
}
/* Firefox: native progress follows the thumb exactly — don't also paint input fill */
input[type="range"]::-moz-range-track{
  height:4px; border-radius:3px; border:none;
  background:var(--line);
}
input[type="range"]::-moz-range-progress{
  height:4px; border-radius:3px; border:none;
  background:var(--c,var(--accent));
}
input[type="range"]::-moz-range-thumb{
  width:15px; height:15px; border-radius:50%;
  background:var(--c,var(--accent)); border:2px solid var(--ink); cursor:pointer;
  box-shadow:0 0 0 3px color-mix(in srgb,var(--c,var(--accent)) 28%,transparent);
}
@supports (-moz-appearance:none){
  input[type="range"]{
    background-color:transparent;
    background-image:none;
  }
}

/* ---- presets / segment toggles ---- */
.presets{ display:flex; flex-wrap:wrap; gap:6px; }
.presets.grid2{ display:grid; grid-template-columns:repeat(2,1fr); }
.presets button{
  font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted);
  background:var(--ink); border:1px solid var(--line); border-radius:7px;
  padding:7px 10px; cursor:pointer;
}
.presets button:hover{ border-color:var(--accent); color:var(--text); }
.presets button.on{
  color:var(--ink); background:var(--accent); border-color:var(--accent); font-weight:600;
}

.seg{ display:grid; grid-template-columns:repeat(3,1fr); gap:6px; }
.seg.seg2{ grid-template-columns:repeat(2,1fr); }
.seg.seg4{ grid-template-columns:repeat(4,1fr); }
.seg button{
  font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--muted);
  background:var(--ink); border:1px solid var(--line); border-radius:8px;
  padding:9px 4px; cursor:pointer;
}
.seg button.on{
  color:var(--ink); background:var(--accent); border-color:var(--accent); font-weight:600;
}
.seg button:hover{ border-color:var(--accent); color:var(--text); }

/* ---- hero panel (main viz card) ---- */
.hero{
  background:linear-gradient(180deg,var(--panel-2),var(--ink-2));
  border:1px solid var(--line); border-radius:16px; padding:16px;
}
.hero-head{ display:flex; align-items:center; gap:10px; margin-bottom:8px; flex-wrap:wrap; }
.hero-head h2{ font-family:'Space Grotesk',sans-serif; font-size:15px; font-weight:600; margin:0; }
.hero-head .meta{ margin-left:auto; font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted-2); }

/* ---- play / transport controls ---- */
.playbar, .controls{
  display:flex; align-items:center; gap:10px; margin-top:12px; flex-wrap:wrap;
}
.playbtn{
  display:inline-flex; align-items:center; gap:7px; justify-content:center;
  font-family:'Inter',sans-serif; font-size:13px; font-weight:500;
  color:var(--ink); background:var(--accent); border:none; border-radius:9px;
  padding:9px 16px; cursor:pointer; min-width:88px;
}
.playbtn.ghost{
  color:var(--accent); background:var(--ink); border:1px solid var(--accent); min-width:auto;
}
.playbtn svg{ width:13px; height:13px; }
.speed{
  display:flex; align-items:center; gap:7px; margin-left:auto;
  font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted-2);
}
.speed select{
  width:auto; background:var(--ink); border:1px solid var(--line); border-radius:7px;
  color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:11.5px; padding:5px 8px;
}

/* ---- status pills ---- */
.warn-pill, .verdict{
  font-family:'IBM Plex Mono',monospace; font-size:11px; font-weight:600;
  padding:3px 10px; border-radius:20px; border:1px solid currentColor;
}

/* ---- result readouts ---- */
.readouts{ margin-top:16px; }
.ro-label{
  font-size:10px; letter-spacing:.16em; text-transform:uppercase;
  color:var(--muted-2); font-weight:600; margin:2px 0 9px;
}
.ro-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:11px; }
.ro-grid.primary{ display:grid; grid-template-columns:repeat(4,1fr); gap:12px; margin-bottom:14px; }
.ro-grid.secondary{ display:grid; grid-template-columns:repeat(4,1fr); gap:10px; }
@media (max-width:760px){
  .ro-grid,
  .ro-grid.primary,
  .ro-grid.secondary{ grid-template-columns:repeat(2,1fr); }
}
.ro{
  background:linear-gradient(180deg,var(--panel),var(--ink-2));
  border:1px solid var(--line); border-radius:12px; padding:13px 14px;
  position:relative; overflow:hidden; min-width:0;
}
/* Long unbreakable values must wrap inside grid tracks */
.ro-grid .ro .v{ overflow-wrap:anywhere; }
.ro.sm{ padding:11px 12px; }
.ro .k{
  font-size:10px; letter-spacing:.08em; text-transform:uppercase;
  color:var(--muted-2); font-weight:600;
}
.ro.sm .k{ font-size:9px; }
.ro .v{
  font-family:'IBM Plex Mono',monospace; font-weight:600; margin-top:7px;
  font-size:clamp(15px,2vw,20px); letter-spacing:-.01em; line-height:1; color:var(--text);
}
.ro.sm .v{ font-size:clamp(13px,1.8vw,16px); margin-top:6px; }
.ro .u{ font-size:12px; color:var(--muted); font-weight:500; margin-left:3px; }
.ro.sm .u{ font-size:10px; }
.ro .alt{
  font-family:'IBM Plex Mono',monospace; font-size:10.5px; color:var(--muted-2); margin-top:6px;
}
.ro.sm .alt{ font-size:9.5px; margin-top:4px; }

/* Lead accent bar on readouts */
.ro.lead:before{
  content:""; position:absolute; left:0; top:0; bottom:0; width:3px; opacity:.95;
}
.ro.am:before{ background:var(--amber); box-shadow:0 0 12px var(--amber); }
.ro.rd:before{ background:var(--red); box-shadow:0 0 12px var(--red); }
.ro.cy:before{ background:var(--cyan); box-shadow:0 0 12px var(--cyan); }
.ro.gr:before{ background:var(--green); box-shadow:0 0 12px var(--green); }
.ro.vi:before{ background:var(--violet); box-shadow:0 0 12px var(--violet); }
.ro.in:before{ background:var(--indigo); box-shadow:0 0 12px var(--indigo); }
.ro.pk:before{ background:var(--pink); box-shadow:0 0 12px var(--pink); }
.ro.tl:before{ background:var(--teal); box-shadow:0 0 12px var(--teal); }
.ro.cr:before{ background:var(--coral); box-shadow:0 0 12px var(--coral); }
.ro.lm:before{ background:var(--lime); box-shadow:0 0 12px var(--lime); }
.ro.az:before{ background:var(--azure); box-shadow:0 0 12px var(--azure); }

.ro.am .v{ color:var(--amber); }
.ro.rd .v{ color:var(--red); }
.ro.cy .v{ color:var(--cyan); }
.ro.gr .v{ color:var(--green); }
.ro.vi .v{ color:var(--violet); }
.ro.in .v{ color:var(--indigo); }
.ro.pk .v{ color:var(--pink); }
.ro.tl .v{ color:var(--teal); }
.ro.cr .v{ color:var(--coral); }
.ro.lm .v{ color:var(--lime); }
.ro.az .v{ color:var(--azure); }

/* ---- content blocks / glossary ---- */
section.block{ margin-top:76px; }
.rhead{ display:flex; align-items:baseline; gap:12px; margin-bottom:24px; flex-wrap:wrap; }
.rhead .ey{
  font-size:10px; letter-spacing:.2em; text-transform:uppercase;
  color:var(--accent); font-weight:600; font-family:'IBM Plex Mono',monospace;
}
.rhead h2{
  font-family:'Space Grotesk',sans-serif; font-size:19px; font-weight:600;
  margin:0; letter-spacing:-.01em;
}
.rhead .hint{ margin-left:auto; font-size:11.5px; color:var(--muted-2); font-style:italic; }
.gloss{ display:grid; grid-template-columns:repeat(2,1fr); gap:14px; }
@media (max-width:760px){ .gloss{ grid-template-columns:1fr; } }
.gcard{
  background:linear-gradient(180deg,var(--panel),var(--ink-2));
  border:1px solid var(--line); border-radius:13px; padding:15px 17px;
}
.gcard h3{ font-family:'Space Grotesk',sans-serif; font-weight:600; font-size:14px; margin:0 0 6px; }
.gcard p{ font-size:12.5px; color:var(--muted); line-height:1.6; margin:0; }
.gcard b{ color:var(--text); font-weight:600; }
.gcard code{
  font-family:'IBM Plex Mono',monospace; font-size:11.5px; color:var(--accent);
  background:var(--ink); padding:1px 5px; border-radius:5px;
}
.gcard .fx{
  font-family:'IBM Plex Mono',monospace; font-size:12px; color:var(--accent);
  background:var(--ink); border:1px solid var(--line-soft); border-radius:7px;
  padding:7px 10px; margin:8px 0; display:inline-block;
}

footer{
  margin-top:34px; padding-top:18px; border-top:1px solid var(--line-soft);
  font-size:11.5px; color:var(--muted-2); line-height:1.6;
}
:focus-visible{ outline:2px solid var(--accent); outline-offset:2px; }


/* ---- Quick scenarios — one-tap setups (same chrome as .presets) ---- */
.scenario-demos{ margin:0 0 14px; }
.scenario-demos .sc-label{
  font-family:'IBM Plex Mono',monospace; font-size:10px; font-weight:600;
  letter-spacing:.06em; text-transform:uppercase; color:var(--muted-2);
  margin:0 0 7px;
}
.scenario-demos .sc-row{ display:flex; flex-wrap:wrap; gap:6px; }
.scenario-demos button{
  font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted);
  background:var(--ink); border:1px solid var(--line); border-radius:7px;
  padding:7px 10px; cursor:pointer; text-align:left;
  transition:border-color .12s, color .12s, background .12s;
}
.scenario-demos button:hover{ border-color:var(--accent,var(--amber)); color:var(--text); }
.scenario-demos button:focus-visible{ outline:2px solid var(--accent,var(--amber)); outline-offset:2px; }
.scenario-demos button .sc-kicker{
  display:block; font-size:9px; font-weight:600; letter-spacing:.06em; text-transform:uppercase;
  color:var(--muted-2); margin-bottom:2px;
}
.scenario-demos button:hover .sc-kicker{ color:var(--muted); }
@media (max-width:560px){
  .scenario-demos button{ flex:1 1 calc(50% - 6px); min-height:40px; }
}

/* ---- viz hosts: theme-aware simulator / chart plates ----
   Prefer these tokens over hardcoded #0a111e / #fff so light mode stays legible. */
.hero svg,
.panel svg,
#anim, #springViz, #forceChart, #step, #dLoad, #dShear, #dMoment, #dDefl,
svg[id$="Svg"], svg[id$="Chart"], svg[id$="Viz"], canvas.viz {
  background: var(--viz-bg, var(--ink));
}
/* ...but NOT the little inline icons inside buttons. `.hero svg` and `.panel svg` are broad
   enough to catch every icon in a play/pause/reset/share control, painting an --ink plate behind
   a glyph that is itself filled with currentColor (= --ink on an accent-coloured button). The
   result was a solid dark square where the icon should be — on every simulator's play button.
   Charts are never inside a button, so this exclusion cannot affect them. */
.hero button svg,
.panel button svg,
button svg[id$="Svg"], button svg[id$="Chart"], button svg[id$="Viz"] {
  background: none;
}
/* Common inline style on viz wrappers */
.viz-host, .sim-stage, .chart-wrap {
  background: var(--viz-bg, var(--ink));
  border: 1px solid var(--viz-border, var(--line-soft));
  border-radius: 12px;
}

/* Soften pure-black fills that some pages still hardcode when light theme is on */
:root[data-theme="light"] svg [fill="#0a111e"],
:root[data-theme="light"] svg [fill="#0e1830"],
:root[data-theme="light"] svg [fill="#111"],
:root[data-theme="light"] svg [fill="#000"],
:root[data-theme="light"] svg [fill="black"] {
  fill: var(--viz-bg);
}
:root[data-theme="light"] svg [stroke="#0a111e"],
:root[data-theme="light"] svg [stroke="#0e1830"] {
  stroke: var(--viz-border);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) svg [fill="#0a111e"],
  :root:not([data-theme="dark"]) svg [fill="#0e1830"],
  :root:not([data-theme="dark"]) svg [fill="#111"],
  :root:not([data-theme="dark"]) svg [fill="#000"],
  :root:not([data-theme="dark"]) svg [fill="black"] {
    fill: var(--viz-bg);
  }
  :root:not([data-theme="dark"]) svg [stroke="#0a111e"],
  :root:not([data-theme="dark"]) svg [stroke="#0e1830"] {
    stroke: var(--viz-border);
  }
}

/* Text drawn as SVG that used near-white fills: map to --text in light mode */
:root[data-theme="light"] svg [fill="#e9f0fb"],
:root[data-theme="light"] svg [fill="#fff"],
:root[data-theme="light"] svg [fill="#ffffff"],
:root[data-theme="light"] svg [fill="white"] {
  fill: var(--text);
}
:root[data-theme="light"] svg [stroke="#e9f0fb"],
:root[data-theme="light"] svg [stroke="#fff"],
:root[data-theme="light"] svg [stroke="#ffffff"],
:root[data-theme="light"] svg [stroke="white"] {
  stroke: var(--text);
}
@media (prefers-color-scheme: light) {
  :root:not([data-theme="dark"]) svg [fill="#e9f0fb"],
  :root:not([data-theme="dark"]) svg [fill="#fff"],
  :root:not([data-theme="dark"]) svg [fill="#ffffff"],
  :root:not([data-theme="dark"]) svg [fill="white"] {
    fill: var(--text);
  }
  :root:not([data-theme="dark"]) svg [stroke="#e9f0fb"],
  :root:not([data-theme="dark"]) svg [stroke="#fff"],
  :root:not([data-theme="dark"]) svg [stroke="#ffffff"],
  :root:not([data-theme="dark"]) svg [stroke="white"] {
    stroke: var(--text);
  }
}


/* ============================================================
   --- interaction polish ---

   Every control on a tool page reacted instantly or not at all: `.playbtn` — the play/pause/reset
   control on around forty pages, and the most-pressed thing on the site — had no hover state at all,
   and the segmented and preset buttons snapped between colours with no transition.

   Two rules followed here:

   1. Nothing that moves may change LAYOUT. The range thumb in particular is centred on its track by
      a hand-computed `margin-top:-6.5px` for its 17px size, so growing the thumb on hover would
      shift it off the track. The glow ring grows instead — it is a box-shadow, so it costs no space
      and cannot push anything out of alignment.
   2. All of it is off under `prefers-reduced-motion`, at the bottom of this block.
   ============================================================ */

.playbtn, .presets button, .seg button, .ctrlbtn, select, .catseg button{
  transition:background-color .13s ease, border-color .13s ease, color .13s ease,
             box-shadow .13s ease, filter .13s ease, transform .09s ease;
}

/* the primary transport button: lift very slightly, brighten, then press in */
.playbtn:hover{ filter:brightness(1.08); transform:translateY(-1px); }
.playbtn:active{ transform:translateY(0) scale(.985); filter:brightness(.97); }
.playbtn.ghost:hover{
  background:color-mix(in srgb,var(--accent) 12%,var(--ink));
  filter:none;
}
.playbtn.ghost:active{ background:color-mix(in srgb,var(--accent) 18%,var(--ink)); }

/* segmented / preset buttons: a hint of the accent behind them before they are chosen, and a
   real pressed state so a tap on a phone visibly registers */
.presets button:hover, .seg button:hover, .catseg button:hover{
  background:color-mix(in srgb,var(--accent) 9%,var(--ink));
}
.presets button:active, .seg button:active, .catseg button:active{ transform:scale(.98); }
/* the already-selected one should not pretend to be selectable */
.presets button.on:hover, .seg button.on:hover, .catseg button.on:hover{
  filter:brightness(1.06); background:var(--accent);
}

select:hover{ border-color:color-mix(in srgb,var(--accent) 55%,var(--line)); }

/* slider: widen the glow on hover and again while dragging. Size is untouched on purpose —
   see note 1 above. */
input[type="range"]{ transition:box-shadow .13s ease; }
input[type="range"]:hover::-webkit-slider-thumb{
  box-shadow:0 0 0 5px color-mix(in srgb,var(--c,var(--accent)) 30%,transparent);
}
input[type="range"]:active::-webkit-slider-thumb{
  box-shadow:0 0 0 7px color-mix(in srgb,var(--c,var(--accent)) 34%,transparent);
}
input[type="range"]:hover::-moz-range-thumb{
  box-shadow:0 0 0 5px color-mix(in srgb,var(--c,var(--accent)) 30%,transparent);
}
input[type="range"]:active::-moz-range-thumb{
  box-shadow:0 0 0 7px color-mix(in srgb,var(--c,var(--accent)) 34%,transparent);
}
input[type="range"]::-webkit-slider-thumb{ transition:box-shadow .13s ease; }
input[type="range"]::-moz-range-thumb{ transition:box-shadow .13s ease; }

/* a disabled control should look unavailable rather than merely unresponsive */
.playbtn:disabled, .ctrlbtn:disabled, .seg button:disabled, .presets button:disabled{
  opacity:.45; cursor:default; filter:none; transform:none;
}
.playbtn:disabled:hover, .ctrlbtn:disabled:hover{ filter:none; transform:none; }

/* links inside prose: underline on hover only, so body copy stays quiet until pointed at */
.rot-content a:not(.rot-btn), .rot-fieldnotes a{
  text-decoration-color:color-mix(in srgb,var(--accent) 45%,transparent);
  transition:text-decoration-color .13s ease, color .13s ease;
}
.rot-content a:not(.rot-btn):hover, .rot-fieldnotes a:hover{
  text-decoration-color:var(--accent);
}

/* Respect the reader's setting. Colour changes stay — they carry meaning and do not move —
   but nothing translates, scales or eases. */
@media (prefers-reduced-motion:reduce){
  .playbtn, .presets button, .seg button, .ctrlbtn, select, .catseg button,
  input[type="range"], input[type="range"]::-webkit-slider-thumb,
  input[type="range"]::-moz-range-thumb,
  .rot-content a, .rot-fieldnotes a{ transition:none; }
  .playbtn:hover, .playbtn:active,
  .presets button:active, .seg button:active, .catseg button:active{ transform:none; }
}

/* Chain backlinks — the reverse edge of the chain pages, generated by build-registry.py.
   Deliberately quiet: it is a wayfinding aid at the foot of a tool, not a call to action. */
.rot-chainlink{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:8px 12px;
  margin:22px 0 0; padding:12px 15px; background:var(--ink);
  border:1px solid var(--line-soft); border-radius:11px;
  font-size:13px; color:var(--muted);
}
.rot-chainlink .cl-ey{
  font-size:10px; letter-spacing:.09em; text-transform:uppercase;
  color:var(--muted-2); font-weight:600;
}
.rot-chainlink a{ color:var(--accent); text-decoration:none; }
.rot-chainlink a:hover{ text-decoration:underline; }
.rot-chainlink .cl-all{ margin-left:auto; font-size:12px; }

/* Unusual-units toggle on the converter. Quiet by design: the units behind it are real and
   correctly converted, they are just not what anyone reaches for by accident. */
.oddbar{ display:flex; flex-wrap:wrap; align-items:center; gap:10px 14px; margin-top:22px; }
.oddchk{ display:inline-flex; align-items:center; gap:8px; font-size:13px; color:var(--muted); cursor:pointer; }
.oddchk input{ width:auto; accent-color:var(--accent); }
/* opt-in rounding controls sit on the same bar as the unusual-units toggle */
.roundbar{ margin-top:12px; }
.roundsel{ width:auto; min-width:58px; padding:5px 7px; font-size:12px; }
.roundsel:disabled{ opacity:.45; cursor:not-allowed; }
.oddnote{ font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted-2); }
.allcell.odd{ border-style:dashed; }
.allcell.odd .sym{ color:var(--amber); }

/* A landmark above the modelled atmosphere. Its height is real and shown; the arrow says the
   chart cannot reach it, which is honest about a limit rather than hiding the number. */
.lmbtn.beyond{ border-style:dashed; opacity:.9; }
.lmbtn.beyond .v{ color:var(--amber); }

/* ---------- paint page: picker and colour converter ---------- */
.pickwrap{ display:grid; grid-template-columns:minmax(220px,1fr) minmax(260px,1.2fr); gap:18px; }
@media (max-width:760px){ .pickwrap{ grid-template-columns:1fr; } }
.svfield{ position:relative; width:100%; aspect-ratio:1.25; border-radius:12px;
  border:1px solid var(--line); cursor:crosshair; touch-action:none; }
.svdot{ position:absolute; width:16px; height:16px; border-radius:50%; border:2px solid #fff;
  box-shadow:0 0 0 1px rgba(0,0,0,.55); transform:translate(-50%,-50%); pointer-events:none; }
.huerail{ position:relative; height:18px; margin-top:10px; border-radius:9px;
  border:1px solid var(--line); cursor:pointer; touch-action:none; }
.huedot{ position:absolute; top:50%; width:14px; height:22px; border-radius:5px; background:transparent;
  border:2px solid #fff; box-shadow:0 0 0 1px rgba(0,0,0,.55); transform:translate(-50%,-50%); pointer-events:none; }
.pickbtns{ display:flex; flex-wrap:wrap; align-items:center; gap:8px; margin-top:12px; }
.nativelab{ display:inline-flex; align-items:center; gap:7px; font-size:12px; color:var(--muted); }
.nativelab input[type="color"]{ width:34px; height:28px; padding:0; border:1px solid var(--line);
  border-radius:7px; background:var(--ink); cursor:pointer; }
.pbtn{ font-family:'Inter',sans-serif; font-size:12.5px; color:var(--text); background:var(--ink);
  border:1px solid var(--line); border-radius:9px; padding:8px 13px; cursor:pointer; }
.pbtn:hover{ border-color:var(--accent); color:var(--accent); }
.pbtn.primary{ background:var(--accent-dim); border-color:var(--accent); }
.cfprev{ height:46px; border-radius:11px; border:1px solid var(--line); margin-bottom:12px; }
.cffields{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:9px; }
.cffields label{ display:flex; flex-direction:column; gap:5px; font-size:10.5px;
  letter-spacing:.07em; text-transform:uppercase; color:var(--muted-2); font-weight:600; }
.cffields input{ background:var(--ink); border:1px solid var(--line); border-radius:8px;
  color:var(--text); font-family:'IBM Plex Mono',monospace; font-size:13px; padding:8px 10px; outline:none; }
.cffields input:focus{ border-color:var(--accent); }
.cffields input[readonly]{ color:var(--muted); }
.cfmeta{ display:flex; flex-wrap:wrap; gap:8px 14px; margin-top:11px;
  font-family:'IBM Plex Mono',monospace; font-size:11px; color:var(--muted-2); }
.cfmeta b{ color:var(--text); }
.cfnote{ font-size:11.5px; color:var(--muted-2); line-height:1.6; margin-top:11px; }
.cfnote code{ font-family:'IBM Plex Mono',monospace; color:var(--muted); }
.cfnote b{ color:var(--muted); }

/* the gamut verdict — the answer to "why does the tin look duller than my screen" */
.gamut{ margin-top:18px; padding:14px 16px; border-radius:12px; border:1px solid var(--line-soft);
  background:var(--ink); font-size:13px; color:var(--muted); }
.gamut.close{ border-color:color-mix(in srgb,var(--green) 45%,transparent);
  background:color-mix(in srgb,var(--green) 8%,transparent); }
.gamut.near{ border-color:color-mix(in srgb,var(--amber) 45%,transparent);
  background:color-mix(in srgb,var(--amber) 8%,transparent); }
.gamut.far{ border-color:color-mix(in srgb,var(--red) 45%,transparent);
  background:color-mix(in srgb,var(--red) 8%,transparent); }
.gamut .g-head{ font-family:'Space Grotesk',sans-serif; font-weight:600; font-size:15px;
  color:var(--text); margin-bottom:10px; }
.gamut .g-sw{ display:flex; gap:0; margin-bottom:11px; border-radius:9px; overflow:hidden;
  border:1px solid var(--line); }
.gamut .g-sw span{ flex:1; height:42px; }
.gamut .g-rows div{ display:flex; flex-wrap:wrap; align-items:baseline; gap:8px 12px; padding:5px 0;
  border-top:1px dashed var(--line-soft); font-family:'IBM Plex Mono',monospace; font-size:12px; }
.gamut .g-rows div:first-child{ border-top:0; }
.gamut .g-rows span{ min-width:118px; color:var(--muted-2); font-size:10.5px;
  letter-spacing:.06em; text-transform:uppercase; }
.gamut .g-rows b{ color:var(--text); }
.gamut .g-rows i{ color:var(--muted-2); font-style:normal; }
.gamut .g-why{ margin-top:11px; font-size:12.5px; line-height:1.65; }
.gamut .g-why b{ color:var(--text); }

/* hue reachability strip — screen against mixable, hue by hue */
.huestrip{ margin-top:16px; }
.huestrip svg{ width:100%; height:auto; display:block; }
.huestrip .hs-axis{ stroke:var(--line); stroke-width:1; }
.huestrip .hs-lab{ fill:var(--muted-2); font-family:'Inter',sans-serif; font-size:11px;
  text-anchor:middle; }
.huestrip .hs-mark{ stroke:var(--text); stroke-width:1.5; stroke-dasharray:3 3; opacity:.75; }
.huestrip .hs-you{ fill:var(--text); font-family:'Inter',sans-serif; font-size:10px;
  text-anchor:middle; letter-spacing:.05em; }
.huestrip .hs-key{ display:flex; flex-wrap:wrap; gap:8px 18px; margin-top:6px;
  font-size:11.5px; color:var(--muted-2); }
.huestrip .hs-key span{ display:inline-flex; align-items:center; gap:7px; }
.huestrip .hs-key i{ width:15px; height:11px; border-radius:3px; }
/* outlined vs filled, because two chips at different opacities of the same grey read as one */
.huestrip .sw-ghost{ background:transparent; border:1px dashed var(--muted-2); }
.huestrip .sw-solid{ background:var(--muted-2); }
.huestrip .hs-cap{ font-size:12px; line-height:1.65; color:var(--muted); margin-top:9px; }
.huestrip .hs-cap b{ color:var(--text); }

/* ---- colour library, saved list, gamut outline ---- */
.libsearch{ width:100%; background:var(--ink); border:1px solid var(--line); border-radius:8px;
  color:var(--text); font-family:'Inter',sans-serif; font-size:12.5px; padding:7px 10px;
  outline:none; margin-bottom:8px; }
.libsearch:focus{ border-color:var(--accent); }
.libfams{ display:flex; flex-wrap:wrap; gap:4px; margin-bottom:9px; }
.libfams button{ font-family:'IBM Plex Mono',monospace; font-size:10px; color:var(--muted-2);
  background:var(--ink); border:1px solid var(--line); border-radius:6px; padding:4px 7px;
  cursor:pointer; }
.libfams button:hover{ border-color:var(--accent); color:var(--text); }
.libfams button.on{ color:var(--ink); background:var(--accent); border-color:var(--accent);
  font-weight:600; }
.libgrid{ display:grid; grid-template-columns:repeat(9,1fr); gap:4px; }
@media (max-width:520px){ .libgrid{ grid-template-columns:repeat(7,1fr); } }
.libsw{ aspect-ratio:1; border-radius:6px; border:1.5px solid var(--line); cursor:pointer;
  padding:0; }
.libsw:hover{ border-color:var(--text); transform:translateY(-1px); }
.libempty{ font-size:11.5px; color:var(--muted-2); line-height:1.6; padding:4px 0; }

.savedlist{ display:flex; flex-direction:column; gap:5px; margin-bottom:10px; }
.savedrow{ display:flex; align-items:center; gap:9px; padding:6px 8px; border:1px solid var(--line);
  border-radius:8px; background:var(--ink); }
.savedrow .sw{ width:20px; height:20px; border-radius:5px; flex:none;
  border:1px solid var(--line-soft); }
.savedrow .nm{ font-size:12px; color:var(--text); flex:1; min-width:0; overflow:hidden;
  text-overflow:ellipsis; white-space:nowrap; }
.savedrow code{ font-family:'IBM Plex Mono',monospace; font-size:10.5px; color:var(--muted-2); }
.savedrow .rm{ flex:none; width:20px; height:20px; border-radius:5px; border:1px solid var(--line);
  background:var(--panel); color:var(--muted-2); cursor:pointer; font-size:12px; line-height:1; }
.savedrow .rm:hover{ border-color:var(--red); color:var(--red); }
.savedfoot{ display:flex; flex-wrap:wrap; gap:7px; }
.savedfoot .pbtn{ text-decoration:none; display:inline-flex; align-items:center; }

.svgamut{ position:absolute; inset:0; width:100%; height:100%; border-radius:12px;
  pointer-events:none; }
.gamtoggle{ display:flex; align-items:center; gap:7px; margin-top:9px; font-size:11.5px;
  color:var(--muted-2); cursor:pointer; }
.gamtoggle input{ accent-color:var(--accent); }
