/* ==========================================================================
   ChemRage design system ("Instrument, readable", round 3; promoted with
   the round-6 homepage, 2026-10-25). Source of truth for the new pages:
   tokens for light + dark, type, and the components below. Ported from
   dota-draft-product/prototypes/homepage-r6-2026-10-25/system/theme.css.

   Look: aluminium or graphite hardware, one safety-orange signal, OLED lime
   on a screen that stays dark, the product drawn as a device. Legibility:
   17px body, words in sentence-case Inter, mono caps only for real data
   labels, ink rules, numbers on chips.

   OPT-IN. A page uses this system with
     <html lang="en" data-cr-theme>
     <link rel="stylesheet" href="/site.css">
     <script src="/site.js"></script>          (in <head>, before the body paints)
   site.js sets data-theme="light|dark" on <html>: #light / #dark in the URL
   wins, then the visitor's choice from the header toggle (localStorage
   cr.theme), then the default: dark inside the Windows app (it sits beside
   the game), else the system preference. A page without data-cr-theme is
   always dark. The shared header (header.js) reads these tokens on an
   opted-in page and its own dark copy everywhere else. Every public page
   opts in (home, the Assistant, party, match, Combo Finder, download,
   terms and the stats site); /chemrage.css remains only for /label, /docs
   and other out-of-scope consumers.

   FONTS are self-hosted (OFL, latin subset from the fontsource packages,
   web/fonts/LICENSE-*.txt): no request to Google from our pages.
   Fira Sans 500 is only the game's label face on the Try a build board.
   The latin subset has no U+2192: a "→" in copy falls back to the system
   face, as it did with Google's latin subset.

   WIN-RATE RAMP (data, never themed). site.js sets --wr on any element with
     data-wr="55.8" (a win rate, %)  or  data-marg="-2.5" (a marginal; winrate = 50 + m)
   and exposes CR.wr(winrate), CR.marg(m), CR.wrColor(x), CR.paint(scope).
   Rule: a ramp colour only ever sits on a dark chip, a dark tile or a .screen, in both themes.

   --------------------------------------------------------------------------
   CONTRAST (WCAG 2 ratios, computed from the tokens below with the sRGB
   relative-luminance formula; requirement: body >= 7:1, secondary text and
   labels >= 4.5:1). Columns: on --bg / on --panel / on --panel-2.
     LIGHT   --bg #ecebe7   --panel #fafaf8   --panel-2 #f3f3f0
       body        --text #1f2321         13.3 / 15.2 / 14.3
       headings    --ink #111312          15.6 / 17.9
       secondary   --text-2 #3f4541        8.2 /  9.4 /  8.8
       labels      --muted #535955         6.0 /  6.9 /  6.5   (5.5 on --bg-2 #e2e1dc)
       orange text --accent-ink #a33a0a    5.6 /  6.4
       on orange   --on-accent #120804 on #ff5a14   6.3
       ink button  #ecebe7 on #111312                15.6
     DARK    --bg #0e1110   --panel #151a17   --panel-2 #1b211e
       body        --text #dfe4de         14.7 / 13.7 / 12.7
       headings    --ink #eef1ec          16.7 / 15.5
       secondary   --text-2 #b9c1bb       10.3 /  9.6 /  8.9
       labels      --muted #939d97         6.8 /  6.3 /  5.9   (7.0 on --bg-2 #0a0c0b)
       orange text --accent-ink #ff8a52    8.1 /  7.6
       on orange   --on-accent #140803 on #ff6a26   6.9
       ink button  #0e1110 on #eef1ec                16.7
     SCREEN (dark in both themes)  --screen #0a0c0b|#050706  --screen-2 #131715|#0f1311
       text        --screen-ink #eef2ec   17.3 / 16.0  (dark: 17.8 / 16.8)
       labels      --screen-dim #949f97    7.2 /  6.6  (dark:  7.4 /  6.8)
       OLED lime   --oled #c4ff4d         16.6         (dark: 17.1)
     RAMP digits on a chip (--chip #050605) are data colours and are not tuned:
       win rate >= 47.33% (marginal >= -2.67) clears 4.5:1 (47.33% 5.1, 48% 5.8,
       50% 18.9, 60%+ ~20). Below that cut the ramp starts darkening (h < 0 in
       wrColor) and red digits on black fall to 4.3 and then 2.4:1, so those
       chips are .is-low: the ramp colour on the face with #fff digits, 4.76:1
       just below the cut and rising (8.4 at the deep-red end). site.js
       CR.paint sets .is-low from wrColor's own arithmetic, and the stats
       site's chips (stats_site.py chip, stats_ad.js chip) use the same test.
       Every chip also carries a 1px ring, digits are 800 weight, and the
       minus sign is always printed.
   --------------------------------------------------------------------------

   SHARED FOOTER (paste as the last child of <body>; web/landing.html has it):
<footer class="ftr">
  <div class="wrap ftr__in">
    <img class="ftr__mark" src="/logo-mark.svg" alt="ChemRage" width="26" height="26">
    <nav class="ftr__nav" aria-label="Footer">
      <a href="/download">Windows app</a> <a href="/stats/">Stats</a> <a href="/terms">Terms &amp; privacy</a>
    </nav>
    <p class="ftr__legal">Not affiliated with Valve Corporation. Dota 2 is a registered trademark of Valve Corporation.</p>
  </div>
</footer>
   The header is NOT markup: header.js mounts it (an empty
   <header id="cr-head" class="cr-head"></header> placeholder holds its height).

   --------------------------------------------------------------------------
   COMPONENT INDEX
     Layout     .wrap .section(.section--first) .page-top .sec-head .grid-2 .grid-3 .row .stack ; --tool-gutter
     Type       .display .h2 .h3 .lede .body .small .label(.label--led) .link .figure .num
     Chrome     .ftr  (the header and its theme toggle are styled by header.js)
     Buttons    .btn + --primary | --secondary | --ink | --quiet ; --sm --lg
     Tags       .tag (data label in a hairline box) .led
     Modules    .mgrid > .mod  (flat faces joined by 1px rules) ; .mod--inset ; .rule
     Device     .device > .device__bar + .screen + .device__foot ; .knob .screw .device__btn
     Screen     .screen (always dark) ; .screen--flat ; .screen__rule
     Icon tile  .itile > .tile(img + .tile__m + .tile__take) + .itile__name + .itile__type
                .tile--hero --ult --sm --lg --fluid --empty ; .is-taken .is-pick
     Numbers    .wr (solid chip) ; --sm --lg --xl --bare
     Bars       .bar(>i) .bar--take ; .meter(.meter__needle .meter__scale) ; .hist + .axis ; .split
     Lists      .lrows > .lrow (icon, name + sub, chip) ; .spec ; .steps ; .faq
     Keys       .kbd(--accent --sm) .keys
     Other      .tabs (segmented; --sm --block --stack, .tabs__n .tabs__ic) .gauge .stripe .is-you ; [data-cr-desktop] .no-desktop
     Status     .chip(.live .win .warn .loss .code) ; .notice(--ok --err --info)
     Toolbar    .toolbar + .toolbar__sp
     Tables     .dtable-wrap(--tall) > .dtable(--dense --bare) ; th/td .num .rk ; sortable th[data-s] | th[aria-sort] + .dir
     Tabs       .tabbar (underline, whole views; role=tab aria-selected | .is-active | .on)
     Forms      .fld(.is-error --inline) > .fld__label + .input(--sm --auto --mono --search) + .fld__hint ;
                .chk(--sm) > input[checkbox|radio] ; .filein (input[type=file]) ; .slider (input[type=range])
     Overlays   .dlg (+ <dialog> or .dlg-scrim) > .dlg__head(.dlg__title .dlg__x) .dlg__body .dlg__foot ;
                .popmenu > button[aria-checked] .popmenu__label .popmenu__sep ; .snack(--top --ok --err)
     States     .blank(__title, --bare) ; .waitline + .spinner(--lg) ; .skel(--block) ; .loadbar(style="--pct:40")
     Board      .screen.screen--board(+ --slab) > .screen__bar(.screen__title .screen__meta .screen__tools .screen__status)
                + .screen__body(--flush) + .screen__foot(.screen__key > .screen__key-k + .screen__key-i)
     Dark       .scope-dark (any subtree dark in both themes) ; .dtip(--card, .is-pinned) .dtip__k .dtip__foot ; .dcard

   MOVING A PAGE OFF /chemrage.css (same class names, different meaning here):
     .bar      there a row of controls, here a 10px data bar  -> use .toolbar
     .btn      there an outlined button by itself; here it needs a variant -> .btn--secondary
               (.btn.gold -> .btn--primary, .btn.steam -> .btn--ink)
     .tabs     index.html's own underline tabs  -> .tabbar (.tabs here is the segmented control)
     .chip     kept: the same status names work here (.live .win .warn .loss .code)
     .hint -> .small ; .eyebrow -> .label (data labels only) ; .mono -> .num ; .sp -> .toolbar__sp
     Old token names (--surface, --line, --gold, --ink-2 ...) exist ONLY inside the pinned-dark
     scopes, for the shared JS overlays (section 3b). New CSS uses the tokens below.
   ========================================================================== */

/* ---------- 0. Fonts (self-hosted, latin) ---------- */
@font-face{font-family:"Inter";font-style:normal;font-weight:400;font-display:swap;src:url(/fonts/inter-400.woff2) format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:500;font-display:optional;src:url(/fonts/inter-500.woff2) format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:600;font-display:optional;src:url(/fonts/inter-600.woff2) format("woff2")}
@font-face{font-family:"Inter";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/inter-700.woff2) format("woff2")}
@font-face{font-family:"Inter Tight";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/inter-tight-700.woff2) format("woff2")}
@font-face{font-family:"Inter Tight";font-style:normal;font-weight:800;font-display:swap;src:url(/fonts/inter-tight-800.woff2) format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/jetbrains-mono-500.woff2) format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:600;font-display:swap;src:url(/fonts/jetbrains-mono-600.woff2) format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:700;font-display:swap;src:url(/fonts/jetbrains-mono-700.woff2) format("woff2")}
@font-face{font-family:"JetBrains Mono";font-style:normal;font-weight:800;font-display:swap;src:url(/fonts/jetbrains-mono-800.woff2) format("woff2")}
@font-face{font-family:"Fira Sans";font-style:normal;font-weight:500;font-display:swap;src:url(/fonts/fira-sans-500.woff2) format("woff2")}

/* ---------- 1. Constant tokens (both themes) ---------- */
:root{
  --font-display:"Inter Tight","Inter",system-ui,sans-serif;
  --font-body:"Inter",system-ui,-apple-system,"Segoe UI",sans-serif;
  --font-mono:"JetBrains Mono",ui-monospace,"SFMono-Regular",Menlo,monospace;

  /* type scale: nothing a person reads as running text is under 14px */
  --fs-label:12px;                         /* mono caps data labels (min) */
  --fs-xs:14px;                            /* captions, microcopy, tile names */
  --fs-sm:15px;                            /* secondary running text */
  --fs-body:17px;                          /* body */
  --fs-lede:clamp(19px,1.55vw,21px);       /* hero / section intro */
  --fs-h3:clamp(20px,1.7vw,24px);          /* module titles */
  --fs-h2:clamp(30px,3.6vw,46px);          /* section titles */
  --fs-display:clamp(42px,5.9vw,82px);     /* hero headline */
  --fs-figure:clamp(40px,4.4vw,58px);      /* big numbers on the page */
  --lh-body:1.55;
  --track-display:-.025em;                 /* heavy display, letters never touch */
  --word-display:.09em;                    /* Inter Tight's space is narrow: open it so words never run together */
  --track-label:.07em;                     /* mono caps, <= .08em */

  --s1:4px; --s2:8px; --s3:12px; --s4:16px; --s5:24px; --s6:32px; --s7:48px; --s8:80px;
  --gutter:clamp(16px,3vw,32px);
  --tool-gutter:24px;                      /* the tool pages' content edge (/app, /party, /combo-finder), see section 5 */
  --maxw:1200px;
  --r-xs:4px; --r-sm:6px; --r-md:12px; --r-lg:16px; --r-xl:24px; --r-pill:999px;

  /* data colours — NOT themed */
  --ramp:linear-gradient(90deg,hsl(2 100% 31%) 0%,hsl(2 100% 31%) 40%,hsl(3 100% 36%) 42.5%,hsl(15 100% 50%) 45%,hsl(37 100% 50%) 47.5%,hsl(60 100% 50%) 50%,hsl(83 100% 50%) 52.5%,hsl(105 100% 50%) 55%,hsl(127 100% 50%) 57.5%,hsl(150 100% 50%) 60%,hsl(173 100% 50%) 62.5%,hsl(177 100% 70%) 65%,hsl(178 100% 84%) 67.5%,hsl(179 100% 92%) 70%,hsl(180 100% 96%) 72.5%,#fff 82.5%,#fff 100%); /* 30% → 70% */
  --p0:#3375ff; --p1:#66ffbf; --p2:#bf00bf; --p3:#f3f00b; --p4:#ff6b00;   /* Radiant slots */
  --p5:#fe86c2; --p6:#a1b447; --p7:#65d9f7; --p8:#008321; --p9:#a46900;   /* Dire slots */
  --chip:#050605;                         /* ground of every number chip */
  --tile-ground:#050605;                  /* ground of every icon tile */

  --ease:cubic-bezier(.2,.7,.2,1);
}

/* ---------- 2. LIGHT — bright aluminium, white module faces, ink, safety orange ---------- */
:root,
:root[data-theme="light"]{
  color-scheme:light;
  --bg:#ecebe7;            /* page ground: bright brushed aluminium */
  --bg-2:#e2e1dc;          /* sunken band, track behind tabs */
  --panel:#fafaf8;         /* module face */
  --panel-2:#f3f3f0;       /* nested face, hover */
  --rule:#a9aba4;          /* section rules + module joins: ink-tinted */
  --rule-row:#cfd0ca;      /* row rules inside a module */
  --rule-ink:#111312;      /* 1.5px top rule of a spec / sec-head tick */
  --ink:#111312;           /* headings */
  --text:#1f2321;          /* body */
  --text-2:#3f4541;        /* secondary text */
  --muted:#535955;         /* labels, captions */
  --accent:#ff5a14;        /* safety orange: fills, LEDs, needles */
  --accent-ink:#a33a0a;    /* orange used as text on light */
  --on-accent:#120804;
  --accent-glow:0 0 0 rgba(0,0,0,0);
  --oled:#c4ff4d;          /* screen-only lime */
  --radiant:#4b9330; --dire:#c0453b;
  --logo-chem:#151716;     /* "Chem" / "M" in the inline lockup */
  --hdr-bg:rgba(250,250,248,.9);

  --screen:#0a0c0b; --screen-2:#131715; --screen-line:#2a302c;
  --screen-ink:#eef2ec; --screen-dim:#949f97; --bezel:#1b1e1c;

  --dev-face:linear-gradient(180deg,#f7f7f4 0%,#e4e4df 100%);
  --dev-edge:#b2b3ac; --dev-hi:rgba(255,255,255,.95); --dev-lo:rgba(0,0,0,.2);
  --dev-shadow:0 1px 0 #fff inset,0 -2px 0 rgba(0,0,0,.08) inset,18px 22px 0 -8px rgba(17,19,18,.09),0 24px 48px -28px rgba(17,19,18,.35);

  --key-face:linear-gradient(180deg,#ffffff,#eeeeea);
  --key-edge:#a9aba4; --key-ink:#1a1c1b;
  --focus:0 0 0 3px rgba(255,90,20,.4);

  /* components (section 20+) */
  --btn-edge:#111312;      /* .btn--secondary outline */
  --field-bg:#ffffff;      /* text field / select / checkbox face */
  --field-edge:#7d817c;    /* control edge: 3.3-3.8:1 on the grounds (non-text >= 3:1) */
  --ok-ink:#2f6b1c;        /* "live", "won" as text: 5.4 / 6.2 */
  --bad-ink:#a52e25;       /* "lost", errors as text:  5.8 / 6.7 */
  --surface-3:#e9e9e5;     /* hover inside a raised menu */
  --scrim:rgba(17,19,18,.5);
  --pop-shadow:0 1px 0 rgba(255,255,255,.8) inset,0 18px 40px -14px rgba(17,19,18,.35),0 2px 6px rgba(17,19,18,.08);
  --i-chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23535955' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='7' cy='7' r='5' fill='none' stroke='%23535955' stroke-width='1.8'/%3E%3Cpath d='M11 11l3.5 3.5' stroke='%23535955' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}

/* ---------- 3. DARK — black-green graphite, the orange glows, lime on screens ----------
   The first rule is ALSO the pinned-dark set: a subtree that must be dark in
   both themes (a game board's screen, a tooltip or card drawn over one, the
   shared JS overlays) lists here and gets the dark ground/text/accent tokens,
   so every system component inside it reads dark on a light page too.
   Section 3b adds the old chemrage.css names those overlays still read.
   The screen, housing and header tokens are page-level: second rule only. */
:root[data-theme="dark"],
.scope-dark,.screen--board,.dtip,.dcard,.crb-tip,.crpt-tip,.pfx{
  color-scheme:dark;
  --bg:#0e1110; --bg-2:#0a0c0b;
  --panel:#151a17; --panel-2:#1b211e;
  --rule:#343c37; --rule-row:#262d29; --rule-ink:#dfe4de;
  --ink:#eef1ec; --text:#dfe4de; --text-2:#b9c1bb; --muted:#939d97;
  --accent:#ff6a26; --accent-ink:#ff8a52; --on-accent:#140803;
  --accent-glow:0 0 0 1px rgba(255,106,38,.5),0 0 16px rgba(255,106,38,.4);
  --oled:#c4ff4d;
  --radiant:#7cc25a; --dire:#e0645a;
  --dev-hi:rgba(255,255,255,.07);
  --key-face:linear-gradient(180deg,#2a302c,#1e2320);
  --key-edge:#060807; --key-ink:#e3e8e2;
  --focus:0 0 0 3px rgba(255,106,38,.5);
  --btn-edge:#5b645e;
  --field-bg:#0a0c0b; --field-edge:#646d67;    /* 3.1-3.6:1 */
  --ok-ink:#7cc25a; --bad-ink:#ee7a70;          /* 8.2 / 6.4 on --panel */
  --surface-3:#232a26;
  --scrim:rgba(0,0,0,.62);
  --pop-shadow:0 1px 0 rgba(255,255,255,.05) inset,0 0 0 1px #000,0 22px 48px -12px rgba(0,0,0,.8);
  --i-chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath d='M1 1.5l5 5 5-5' fill='none' stroke='%23939d97' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  --i-search:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Ccircle cx='7' cy='7' r='5' fill='none' stroke='%23939d97' stroke-width='1.8'/%3E%3Cpath d='M11 11l3.5 3.5' stroke='%23939d97' stroke-width='1.8' stroke-linecap='round'/%3E%3C/svg%3E");
}
:root[data-theme="dark"]{
  --logo-chem:#f0e6d6;
  --hdr-bg:rgba(14,17,16,.88);
  --screen:#050706; --screen-2:#0f1311; --screen-line:#242b27;
  --screen-ink:#eef2ec; --screen-dim:#949f97; --bezel:#000;
  --dev-face:linear-gradient(180deg,#202622 0%,#171b19 100%);
  --dev-edge:#323a35; --dev-lo:rgba(0,0,0,.6);
  --dev-shadow:0 1px 0 rgba(255,255,255,.06) inset,0 -2px 0 rgba(0,0,0,.5) inset,0 0 0 1px #000,0 40px 80px -30px rgba(0,0,0,.85);
}
/* 3b. Inside a pinned-dark subtree, the old chemrage.css token names that the
   shared JS overlays still read (piecetip.js's card, header.js's tooltip,
   pickfix.js's picker) point at the system's dark tokens: no warm black, no
   bronze or gold (gold maps to the orange accent), no Cinzel (the old
   display face maps to mono, which those overlays use for caps labels).
   A migration aid for those scripts, not a vocabulary for new CSS. */
.scope-dark,.screen--board,.dtip,.dcard,.crb-tip,.crpt-tip,.pfx{
  --page:var(--bg); --surface:var(--panel); --surface-2:var(--panel-2);
  --ink-2:var(--text-2); --line:var(--rule); --line-2:var(--field-edge);
  --gold:var(--accent); --gold-2:var(--accent-ink); --gold-ink:var(--on-accent);
  --display:var(--font-mono); --mono:var(--font-mono); --sans:var(--font-body); --r:var(--r-xs);
  color:var(--text);
}
/* no theme set yet (JS off) → follow the OS */
@media (prefers-color-scheme:dark){
  :root:not([data-theme]){
    color-scheme:dark;
    --bg:#0e1110; --bg-2:#0a0c0b; --panel:#151a17; --panel-2:#1b211e;
    --rule:#343c37; --rule-row:#262d29; --rule-ink:#dfe4de;
    --ink:#eef1ec; --text:#dfe4de; --text-2:#b9c1bb; --muted:#939d97;
    --accent:#ff6a26; --accent-ink:#ff8a52; --on-accent:#140803;
    --accent-glow:0 0 0 1px rgba(255,106,38,.5),0 0 16px rgba(255,106,38,.4);
    --radiant:#7cc25a; --dire:#e0645a; --logo-chem:#f0e6d6; --hdr-bg:rgba(14,17,16,.88);
    --screen:#050706; --screen-2:#0f1311; --screen-line:#242b27; --bezel:#000;
    --dev-face:linear-gradient(180deg,#202622,#171b19); --dev-edge:#323a35; --dev-hi:rgba(255,255,255,.07); --dev-lo:rgba(0,0,0,.6);
    --dev-shadow:0 0 0 1px #000,0 40px 80px -30px rgba(0,0,0,.85);
    --key-face:linear-gradient(180deg,#2a302c,#1e2320); --key-edge:#060807; --key-ink:#e3e8e2;
    --btn-edge:#5b645e; --field-bg:#0a0c0b; --field-edge:#646d67; --ok-ink:#7cc25a; --bad-ink:#ee7a70;
    --surface-3:#232a26; --scrim:rgba(0,0,0,.62);
  }
}

/* ---------- 4. Base ---------- */
*,*::before,*::after{box-sizing:border-box}
/* the scrollbar's room is kept on every page, long or short, so the centred column — and the
   header on it — sits at the same x on all of them (feedback #71; classic scrollbars) */
html{-webkit-text-size-adjust:100%;scrollbar-gutter:stable}
body{margin:0;background:var(--bg);color:var(--text);font:400 var(--fs-body)/var(--lh-body) var(--font-body);
  -webkit-font-smoothing:antialiased;overflow-x:hidden;transition:background-color .25s var(--ease),color .25s var(--ease)}
img,svg{display:block;max-width:100%}
a{color:inherit}
h1,h2,h3,h4,p,ul,ol,dl,figure{margin:0}
ul,ol{padding:0;list-style:none}
button{font:inherit;color:inherit}
b,strong{font-weight:600;color:var(--ink)}
:focus-visible{outline:none;box-shadow:var(--focus);border-radius:var(--r-xs)}
/* no blinking text caret on text you cannot type into (feedback #65): the browser's caret browsing
   (F7, sticky per browser) otherwise drops one wherever a click lands. Selecting still works. */
html{caret-color:transparent}
input,textarea,select,[contenteditable]:not([contenteditable="false"]){caret-color:auto}
::selection{background:var(--accent);color:var(--on-accent)}
.hide-sm{display:inline}
.visually-hidden{position:absolute!important;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- 5. Layout ---------- */
.wrap{max-width:var(--maxw);margin:0 auto;padding:0 var(--gutter)}                       /* centred column */
.section{padding:var(--s8) 0;border-top:1px solid var(--rule)}                          /* full-width ink rule between sections */
.section--first{border-top:0}
.sec-head{margin-bottom:var(--s6)}                                                          /* section title block */
.sec-head--split{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,.8fr);gap:var(--s4) var(--s7);align-items:end} /* H2 left, one plain line right */
.sec-head .h2{max-width:24ch}
.sec-head p{color:var(--text-2);max-width:46ch}
.grid-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5)}
.grid-3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s5)}
.row{display:flex;flex-wrap:wrap;gap:var(--s3);align-items:center}                       /* inline cluster */
.stack>*+*{margin-top:var(--s3)}
@media (max-width:860px){.grid-2,.grid-3,.sec-head--split{grid-template-columns:1fr}.section{padding:56px 0}}
/* <main class="page page-top"> or <section class="section section--first page-top">: a page's top, the ONE
   distance from the header to the page's title (Matches, Terms, Party's join, Download). A page's own
   rule for that element sets padding-bottom/left/right only, so this stays the top
   (placed after .section's phone padding, so it wins there too). */
.page-top{padding-top:clamp(var(--s5),4vw,var(--s7))}
/* THE TOOL GUTTER. The tool pages (/app, /party, /combo-finder) run wider than the 1200px column, so
   their content edge sits --tool-gutter in from the window rather than --gutter. On /app and /party the
   header row and footer stay the 1200px content column of every page, so the logo holds still moving
   between pages (feedback #61) and the tool below may run wider than them (on /combo-finder the
   full-bleed map). On a phone it is header.js's own 16px row padding. */
@media (max-width:760px){:root{--tool-gutter:16px}}

/* ---------- 6. Type ---------- */
.display{font:800 var(--fs-display)/1.02 var(--font-display);letter-spacing:var(--track-display);word-spacing:var(--word-display);color:var(--ink);text-wrap:balance} /* hero H1 */
.h2{font:800 var(--fs-h2)/1.06 var(--font-display);letter-spacing:var(--track-display);word-spacing:var(--word-display);color:var(--ink);text-wrap:balance}         /* section title */
.h3{font:700 var(--fs-h3)/1.2 var(--font-display);letter-spacing:-.01em;word-spacing:.06em;color:var(--ink)}                                          /* module title */
.lede{font-size:var(--fs-lede);line-height:1.5;color:var(--text-2);max-width:40ch}                                                  /* intro paragraph */
.body{font-size:var(--fs-body);color:var(--text)}
.small{font-size:var(--fs-xs);line-height:1.45;color:var(--muted)}                                                                   /* microcopy, >= 14px */
.label{font:600 var(--fs-label)/1.3 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted)} /* DATA labels only: BUILD WIN RATE, PATCH 7.41 */
.label--led{display:inline-flex;align-items:center;gap:10px;color:var(--text-2);font-size:13px}                                    /* data label with the orange LED square */
.label--led::before{content:"";width:8px;height:8px;border-radius:1px;background:var(--accent);box-shadow:var(--accent-glow);flex:none}
.link{display:inline-flex;align-items:center;gap:.35em;font:500 var(--fs-sm)/1.3 var(--font-body);color:var(--ink);text-decoration:underline;text-decoration-color:var(--rule);text-decoration-thickness:1.5px;text-underline-offset:4px} /* quiet text link; write the → in the copy */
.link:hover{text-decoration-color:var(--accent)}
.figure{display:block;font:800 var(--fs-figure)/1 var(--font-display);letter-spacing:-.03em;color:var(--ink);font-variant-numeric:tabular-nums} /* "~800,000" */
.num{font-family:var(--font-mono);font-variant-numeric:tabular-nums}

/* ---------- 7. Header ----------
   The shared header (.cr-head) is header.js's: it injects its own styles so
   a page that does not load this file (/label, /docs) gets the same
   header. It reads this file's tokens on an opted-in page (every public
   page). */
@media (max-width:760px){.hide-sm{display:none}}
/* the desktop app (site.js sets data-cr-desktop): no "Get the Windows app" */
[data-cr-desktop] .no-desktop{display:none!important}
.only-desktop{display:none}
[data-cr-desktop] .only-desktop{display:revert}

/* ---------- 8. Footer ---------- */
.ftr{border-top:1px solid var(--rule);margin-top:0}
.ftr__in{display:grid;grid-template-columns:auto auto minmax(0,1fr);align-items:center;gap:var(--s3) var(--s6);padding-top:var(--s6);padding-bottom:var(--s7)}
.ftr__mark{height:26px;width:auto}
.ftr__nav{display:flex;flex-wrap:wrap;gap:6px 22px}
.ftr__nav a{font:500 var(--fs-sm)/1.4 var(--font-body);color:var(--ink);text-underline-offset:4px;text-decoration-color:var(--rule)}
.ftr__legal{font-size:var(--fs-xs);line-height:1.5;color:var(--muted);justify-self:end;max-width:52ch;text-align:right}
@media (max-width:860px){.ftr__in{grid-template-columns:1fr;justify-items:start}.ftr__legal{justify-self:start;text-align:left}}

/* ---------- 9. Buttons (sentence-case Inter) ---------- */
.btn{--h:46px;display:inline-flex;align-items:center;justify-content:center;gap:.5em;height:var(--h);padding:0 22px;border-radius:var(--r-pill);border:1.5px solid transparent;font:600 15px/1 var(--font-body);text-decoration:none;cursor:pointer;white-space:nowrap;transition:background .15s,border-color .15s,filter .15s,transform .1s}
.btn:active{transform:translateY(1px)}
.btn--primary{background:var(--accent);color:var(--on-accent);box-shadow:var(--accent-glow)}   /* the signal action */
.btn--primary:hover{filter:brightness(1.06)}
.btn--secondary{background:transparent;color:var(--ink);border-color:var(--btn-edge)}        /* outlined alternative */
.btn--secondary:hover{background:var(--panel-2)}
.btn--ink{background:var(--ink);color:var(--bg)}                                               /* solid neutral (Sign in) */
.btn--ink:hover{filter:brightness(1.2)}
.btn--quiet{background:none;border-color:transparent;padding:0 4px;color:var(--ink);text-decoration:underline;text-decoration-color:var(--rule);text-underline-offset:4px}
.btn--sm{--h:36px;padding:0 15px;font-size:14px}
.btn--lg{--h:54px;padding:0 28px;font-size:16px}
.btn svg{width:18px;height:18px;flex:none}
/* focus: each button's own shadow would replace the global ring (same
   specificity, later rule), so the ring is stacked on it here. The orange
   button gets an ink ring: an orange ring is invisible on it. */
.btn:focus-visible{box-shadow:var(--focus)}
.btn--primary:focus-visible{box-shadow:0 0 0 2px var(--bg),0 0 0 4px var(--ink),var(--accent-glow)}

/* ---------- 10. Tags + LED ---------- */
.tag{display:inline-flex;align-items:center;gap:6px;height:26px;padding:0 9px;border:1px solid var(--rule);border-radius:var(--r-xs);font:600 var(--fs-label)/1 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--text-2);white-space:nowrap} /* a data label in a hairline box */
.led{display:inline-block;width:8px;height:8px;border-radius:50%;background:var(--accent);box-shadow:0 0 0 2px rgba(255,90,20,.18),0 0 10px rgba(255,106,38,.6);flex:none} /* status LED */
.led--oled{background:var(--oled);box-shadow:0 0 10px rgba(196,255,77,.6)}

/* ---------- 11. Modules + rules ---------- */
.mgrid{display:grid;grid-template-columns:repeat(var(--cols,3),minmax(0,1fr));gap:1px;background:var(--rule);border:1px solid var(--rule);border-radius:var(--r-md);overflow:hidden} /* flat module faces joined by 1px ink rules */
.mod{background:var(--panel);padding:var(--s6);min-width:0;display:flex;flex-direction:column;gap:var(--s4)}  /* one module face; no shadow */
.mod--inset{background:var(--panel-2)}
.mod--wide{grid-column:span 2}
.mod p{color:var(--text-2)}
.mod .h3+p{margin-top:-6px}
.rule{height:0;border:0;border-top:1px solid var(--rule);margin:var(--s5) 0}                                   /* standalone rule */
@media (max-width:860px){.mgrid{grid-template-columns:1fr}.mod--wide{grid-column:auto}.mod{padding:var(--s5) var(--s4)}}

/* ---------- 12. Device (the product drawn as hardware: ONE per view, the only raised element) ---------- */
.device{position:relative;background:var(--dev-face);border:1px solid var(--dev-edge);border-radius:var(--r-xl);padding:12px 14px 14px;box-shadow:var(--dev-shadow)}
@media (max-width:640px){:root:not([data-theme="dark"]) .device{box-shadow:0 1px 0 #fff inset,8px 10px 0 -4px rgba(17,19,18,.09),0 16px 32px -20px rgba(17,19,18,.35)}}
.device__bar{display:flex;align-items:center;gap:10px;padding:4px 4px 12px}
.device__title{font:600 15px/1.2 var(--font-body);color:var(--ink)}                             /* "Score a build" */
.device__btn{margin-left:auto;display:inline-flex;align-items:center;gap:6px;height:30px;padding:0 12px;border-radius:var(--r-pill);border:1px solid var(--dev-edge);background:var(--key-face);box-shadow:0 1px 0 var(--dev-hi) inset;font:500 14px/1 var(--font-body);color:var(--text-2);cursor:pointer} /* quiet control on the housing */
.device__btn:focus-visible{box-shadow:0 1px 0 var(--dev-hi) inset,var(--focus)}
.device__btn svg{width:14px;height:14px;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}
.device__foot{display:flex;align-items:center;gap:10px;padding:12px 4px 0}
.screw{width:9px;height:9px;border-radius:50%;background:radial-gradient(circle at 35% 35%,var(--dev-hi),var(--dev-edge) 70%);box-shadow:inset 0 0 0 1px var(--dev-lo);position:relative;flex:none} /* screw dot */
.screw::after{content:"";position:absolute;left:2px;right:2px;top:4px;height:1px;background:var(--dev-lo);transform:rotate(-30deg)}
.knob{width:26px;height:26px;border-radius:50%;background:var(--key-face);border:1px solid var(--key-edge);box-shadow:0 2px 0 var(--key-edge),0 1px 0 var(--dev-hi) inset;position:relative;flex:none} /* rotary knob */
.knob::after{content:"";position:absolute;left:50%;top:4px;width:2px;height:8px;margin-left:-1px;border-radius:1px;background:var(--text-2)}
.knob--accent{background:var(--accent);border-color:rgba(0,0,0,.25);box-shadow:0 2px 0 rgba(0,0,0,.3),var(--accent-glow)}
.knob--accent::after{background:var(--on-accent)}

/* ---------- 13. Screen (dark in BOTH themes; ramp colours live here) ---------- */
.screen{position:relative;background:var(--screen);color:var(--screen-ink);border:3px solid var(--bezel);border-radius:var(--r-md);padding:16px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.05),inset 0 12px 36px rgba(0,0,0,.5)}
.screen--flat{border-width:0;border-radius:var(--r-sm);box-shadow:inset 0 0 0 1px var(--screen-line)}       /* a small display inside a module (no hardware) */
.screen .label{color:var(--screen-dim)}
.screen .label--oled{color:var(--oled)}
.screen__rule{border:0;border-top:1px dashed var(--screen-line);margin:14px 0}
.oled{color:var(--oled);text-shadow:0 0 12px rgba(196,255,77,.3)}                                            /* lime text on a screen */

/* ---------- 14. Icon tile: ramp outline + marginal chip + name + type ---------- */
/* <figure class="itile"><div class="tile" data-marg="3.6"><img src="../kit/icons/KEY.png" alt=""><span class="tile__m">+3.6</span></div>
     <figcaption><span class="itile__name">Aftershock</span><span class="itile__type">Ability</span></figcaption></figure> */
.itile{display:flex;flex-direction:column;gap:12px;min-width:0}
.itile figcaption{display:grid;gap:3px;min-width:0}
.itile__name{font:600 var(--fs-xs)/1.25 var(--font-body);color:var(--ink)}                                     /* 14px, wraps rather than truncates */
.itile__type{font:600 var(--fs-label)/1.2 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted)}
.screen .itile__name{color:var(--screen-ink)}
.screen .itile__type{color:var(--screen-dim)}
.screen .itile--ult .itile__type{color:var(--oled)}
.tile{--wr:#3a3f3c;--size:56px;position:relative;width:var(--size);aspect-ratio:1;flex:none;border-radius:var(--r-xs);background:var(--tile-ground);box-shadow:0 0 0 2.5px var(--wr),0 0 0 4px var(--chip)}  /* dark ground, ramp outline */
.tile>img{width:100%;height:100%;object-fit:cover;border-radius:inherit}
.tile__m{position:absolute;right:-7px;bottom:-9px;z-index:2;padding:3px 5px 2px;border-radius:3px;background:var(--chip);color:var(--wr);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--wr) 55%,transparent),0 0 0 1.5px var(--chip);font:800 13px/1 var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:-.02em;white-space:nowrap} /* marginal chip on the corner */
.tile__take{position:absolute;left:4px;right:4px;top:4px;z-index:2;height:5px;border-radius:2px;background:rgba(5,6,5,.85);box-shadow:0 0 0 1px rgba(0,0,0,.6);overflow:hidden} /* "how soon someone takes it": neutral, not ramp */
.tile__take>i{display:block;height:100%;width:calc(var(--take,50)*1%);background:var(--screen-ink)}
.tile--sm{--size:36px;box-shadow:0 0 0 2px var(--wr),0 0 0 3px var(--chip)}.tile--sm .tile__m{font-size:11px;padding:2px 3px 1px;right:-6px;bottom:-7px}  /* board tiles: chip >= 11px */
.tile--lg{--size:76px}.tile--lg .tile__m{font-size:14px;padding:4px 6px 3px}
.tile--fluid{width:100%}
.tile--hero{aspect-ratio:16/9;width:calc(var(--size)*1.78)}
.tile--hero.tile--fluid{width:100%}
.tile--ult::before{content:"";position:absolute;top:-4px;right:-4px;z-index:3;border-style:solid;border-width:0 13px 13px 0;border-color:transparent var(--accent) transparent transparent;filter:drop-shadow(0 0 3px rgba(255,106,38,.6))} /* ultimate: orange corner */
.tile.is-taken>img{filter:grayscale(1) brightness(.42)}
.tile.is-taken{box-shadow:0 0 0 1.5px #3a403c,0 0 0 3px var(--chip)}
.tile.is-taken::after{content:"";position:absolute;inset:0;z-index:1;border-radius:inherit;background:linear-gradient(to top right,transparent calc(50% - 1px),rgba(255,255,255,.6) 50%,transparent calc(50% + 1px))}
.tile.is-taken .tile__m{color:#8a948d;box-shadow:inset 0 0 0 1px #2a302c,0 0 0 1.5px var(--chip)}
.tile.is-pick{box-shadow:0 0 0 2.5px var(--wr),0 0 0 5px var(--chip),0 0 0 7px var(--accent)}                 /* the recommended pick */
.tile--empty{background:transparent;box-shadow:none;border:1.5px dashed var(--rule)}
.screen .tile--empty{border-color:var(--screen-line)}
/* Hero faces (feedback #72). Hero art (/api/label/icon/npc_dota_hero_<key>) is 256x144; in a
   square or round box object-fit:cover would keep the middle, and a quarter of heroes have the face
   well off it. --fx = the face's horizontal centre (0..1 of the art width) per hero; the position puts
   it in the middle of a square box: X = (fx*r - .5)/(r - 1), r = 256/144, clamped to the art. Heroes
   not listed are centred (.5). _vert portraits are a different source and are left alone. ONE table:
   the Combo Finder's pair data reads these lines too (backend/chemrage_api/hero_faces.py), so keep
   the selector shape exact and values in (0,1); test_hero_faces.py checks both. */
img[src*="/npc_dota_hero_"]:not([src$="_vert"]){object-position:clamp(0%,calc((var(--fx,.5)*1.7778 - .5)/.7778*100%),100%) 50%}
img[src$="/npc_dota_hero_abaddon"]{--fx:.47}
img[src$="/npc_dota_hero_abyssal_underlord"]{--fx:.44}
img[src$="/npc_dota_hero_alchemist"]{--fx:.30}
img[src$="/npc_dota_hero_antimage"]{--fx:.56}
img[src$="/npc_dota_hero_arc_warden"]{--fx:.55}
img[src$="/npc_dota_hero_axe"]{--fx:.60}
img[src$="/npc_dota_hero_bane"]{--fx:.58}
img[src$="/npc_dota_hero_batrider"]{--fx:.63}
img[src$="/npc_dota_hero_beastmaster"]{--fx:.52}
img[src$="/npc_dota_hero_bloodseeker"]{--fx:.57}
img[src$="/npc_dota_hero_bounty_hunter"]{--fx:.42}
img[src$="/npc_dota_hero_brewmaster"]{--fx:.58}
img[src$="/npc_dota_hero_bristleback"]{--fx:.37}
img[src$="/npc_dota_hero_broodmother"]{--fx:.42}
img[src$="/npc_dota_hero_chaos_knight"]{--fx:.45}
img[src$="/npc_dota_hero_chen"]{--fx:.57}
img[src$="/npc_dota_hero_clinkz"]{--fx:.46}
img[src$="/npc_dota_hero_crystal_maiden"]{--fx:.56}
img[src$="/npc_dota_hero_dark_seer"]{--fx:.60}
img[src$="/npc_dota_hero_dark_willow"]{--fx:.40}
img[src$="/npc_dota_hero_dazzle"]{--fx:.62}
img[src$="/npc_dota_hero_death_prophet"]{--fx:.75}
img[src$="/npc_dota_hero_disruptor"]{--fx:.45}
img[src$="/npc_dota_hero_doom_bringer"]{--fx:.43}
img[src$="/npc_dota_hero_dragon_knight"]{--fx:.67}
img[src$="/npc_dota_hero_drow_ranger"]{--fx:.36}
img[src$="/npc_dota_hero_earth_spirit"]{--fx:.48}
img[src$="/npc_dota_hero_earthshaker"]{--fx:.46}
img[src$="/npc_dota_hero_elder_titan"]{--fx:.45}
img[src$="/npc_dota_hero_ember_spirit"]{--fx:.42}
img[src$="/npc_dota_hero_enchantress"]{--fx:.42}
img[src$="/npc_dota_hero_enigma"]{--fx:.60}
img[src$="/npc_dota_hero_faceless_void"]{--fx:.57}
img[src$="/npc_dota_hero_furion"]{--fx:.48}
img[src$="/npc_dota_hero_grimstroke"]{--fx:.67}
img[src$="/npc_dota_hero_hoodwink"]{--fx:.45}
img[src$="/npc_dota_hero_huskar"]{--fx:.35}
img[src$="/npc_dota_hero_invoker"]{--fx:.60}
img[src$="/npc_dota_hero_juggernaut"]{--fx:.39}
img[src$="/npc_dota_hero_keeper_of_the_light"]{--fx:.32}
img[src$="/npc_dota_hero_kez"]{--fx:.60}
img[src$="/npc_dota_hero_kunkka"]{--fx:.44}
img[src$="/npc_dota_hero_legion_commander"]{--fx:.38}
img[src$="/npc_dota_hero_leshrac"]{--fx:.62}
img[src$="/npc_dota_hero_lich"]{--fx:.40}
img[src$="/npc_dota_hero_life_stealer"]{--fx:.60}
img[src$="/npc_dota_hero_lina"]{--fx:.26}
img[src$="/npc_dota_hero_lone_druid"]{--fx:.72}
img[src$="/npc_dota_hero_luna"]{--fx:.45}
img[src$="/npc_dota_hero_lycan"]{--fx:.62}
img[src$="/npc_dota_hero_magnataur"]{--fx:.58}
img[src$="/npc_dota_hero_marci"]{--fx:.32}
img[src$="/npc_dota_hero_mars"]{--fx:.47}
img[src$="/npc_dota_hero_medusa"]{--fx:.45}
img[src$="/npc_dota_hero_meepo"]{--fx:.68}
img[src$="/npc_dota_hero_mirana"]{--fx:.42}
img[src$="/npc_dota_hero_monkey_king"]{--fx:.42}
img[src$="/npc_dota_hero_morphling"]{--fx:.33}
img[src$="/npc_dota_hero_muerta"]{--fx:.55}
img[src$="/npc_dota_hero_naga_siren"]{--fx:.40}
img[src$="/npc_dota_hero_necrolyte"]{--fx:.67}
img[src$="/npc_dota_hero_nevermore"]{--fx:.47}
img[src$="/npc_dota_hero_night_stalker"]{--fx:.62}
img[src$="/npc_dota_hero_nyx_assassin"]{--fx:.45}
img[src$="/npc_dota_hero_obsidian_destroyer"]{--fx:.52}
img[src$="/npc_dota_hero_ogre_magi"]{--fx:.42}
img[src$="/npc_dota_hero_omniknight"]{--fx:.45}
img[src$="/npc_dota_hero_oracle"]{--fx:.48}
img[src$="/npc_dota_hero_pangolier"]{--fx:.67}
img[src$="/npc_dota_hero_phantom_assassin"]{--fx:.58}
img[src$="/npc_dota_hero_phantom_lancer"]{--fx:.42}
img[src$="/npc_dota_hero_puck"]{--fx:.60}
img[src$="/npc_dota_hero_pudge"]{--fx:.30}
img[src$="/npc_dota_hero_pugna"]{--fx:.47}
img[src$="/npc_dota_hero_razor"]{--fx:.68}
img[src$="/npc_dota_hero_riki"]{--fx:.70}
img[src$="/npc_dota_hero_ringmaster"]{--fx:.42}
img[src$="/npc_dota_hero_rubick"]{--fx:.48}
img[src$="/npc_dota_hero_sand_king"]{--fx:.52}
img[src$="/npc_dota_hero_shadow_demon"]{--fx:.42}
img[src$="/npc_dota_hero_shadow_shaman"]{--fx:.30}
img[src$="/npc_dota_hero_shredder"]{--fx:.60}
img[src$="/npc_dota_hero_silencer"]{--fx:.58}
img[src$="/npc_dota_hero_skeleton_king"]{--fx:.45}
img[src$="/npc_dota_hero_skywrath_mage"]{--fx:.40}
img[src$="/npc_dota_hero_slardar"]{--fx:.35}
img[src$="/npc_dota_hero_slark"]{--fx:.45}
img[src$="/npc_dota_hero_snapfire"]{--fx:.55}
img[src$="/npc_dota_hero_sniper"]{--fx:.40}
img[src$="/npc_dota_hero_spectre"]{--fx:.58}
img[src$="/npc_dota_hero_spirit_breaker"]{--fx:.60}
img[src$="/npc_dota_hero_storm_spirit"]{--fx:.40}
img[src$="/npc_dota_hero_sven"]{--fx:.60}
img[src$="/npc_dota_hero_techies"]{--fx:.45}
img[src$="/npc_dota_hero_templar_assassin"]{--fx:.40}
img[src$="/npc_dota_hero_terrorblade"]{--fx:.58}
img[src$="/npc_dota_hero_tidehunter"]{--fx:.35}
img[src$="/npc_dota_hero_tiny"]{--fx:.53}
img[src$="/npc_dota_hero_troll_warlord"]{--fx:.30}
img[src$="/npc_dota_hero_tusk"]{--fx:.40}
img[src$="/npc_dota_hero_undying"]{--fx:.55}
img[src$="/npc_dota_hero_ursa"]{--fx:.32}
img[src$="/npc_dota_hero_vengefulspirit"]{--fx:.55}
img[src$="/npc_dota_hero_venomancer"]{--fx:.60}
img[src$="/npc_dota_hero_viper"]{--fx:.45}
img[src$="/npc_dota_hero_visage"]{--fx:.45}
img[src$="/npc_dota_hero_void_spirit"]{--fx:.45}
img[src$="/npc_dota_hero_warlock"]{--fx:.45}
img[src$="/npc_dota_hero_weaver"]{--fx:.55}
img[src$="/npc_dota_hero_windrunner"]{--fx:.58}
img[src$="/npc_dota_hero_winter_wyvern"]{--fx:.45}
img[src$="/npc_dota_hero_wisp"]{--fx:.40}
img[src$="/npc_dota_hero_zuus"]{--fx:.55}

/* ---------- 15. Number chips (win rates + marginals on a solid dark chip) ---------- */
/* <span class="wr" data-wr="55.8">55.8%</span>   <span class="wr" data-marg="-2.5">−2.5</span> */
.wr{--wr:var(--screen-ink);display:inline-flex;align-items:center;justify-content:center;min-width:3.4em;padding:5px 8px 4px;border-radius:var(--r-xs);background:var(--chip);color:var(--wr);box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--wr) 45%,transparent);font:800 14px/1.1 var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:-.01em;white-space:nowrap}
.wr.is-low,.is-low>.tile__m{background:var(--wr);color:#fff;box-shadow:inset 0 0 0 1px var(--chip),0 0 0 1.5px var(--chip)} /* below 47.33% (set by site.js CR.paint): ramp colour on the face, white digits (>= 4.76:1), so deep reds stay readable */
.wr--sm{font-size:12px;padding:3px 6px 2px;min-width:0}                                                         /* dense boards; never under 11px */
.wr--lg{font-size:18px;padding:6px 10px 5px;border-radius:var(--r-sm)}
.wr--xl{font:800 clamp(48px,5.6vw,72px)/1 var(--font-display);letter-spacing:-.03em;padding:0;min-width:0;justify-content:flex-start;background:none;box-shadow:none;text-shadow:0 0 24px color-mix(in srgb,var(--wr) 35%,transparent)} /* the build score, ONLY on a .screen */
.wr--bare{background:none;box-shadow:none;padding:0;min-width:0}                                                 /* ONLY on a .screen */

/* ---------- 16. Bars, meter, histogram, split ---------- */
/* <div class="bar" data-wr="56.2" style="--pct:78"><i></i></div>  dark track + ramp fill */
.bar{--wr:var(--oled);--pct:50;position:relative;height:10px;border-radius:2px;background:var(--chip);box-shadow:inset 0 0 0 1px rgba(255,255,255,.06);overflow:hidden}
.bar>i{display:block;height:100%;width:calc(var(--pct)*1%);background:var(--wr);border-radius:inherit}
.bar--take>i{background:var(--screen-ink)}                                                                      /* neutral: not a win rate */
/* <div class="meter" style="--pos:100"><i class="meter__needle"></i></div> ; --pos = (wr-30)/40*100 */
.meter{--pos:50;position:relative;height:10px;border-radius:2px;background:var(--ramp);margin:12px 0 8px}
.meter__needle{position:absolute;top:-6px;left:calc(var(--pos)*1%);width:4px;height:22px;margin-left:-2px;border-radius:1px;background:var(--accent);box-shadow:0 0 0 2px var(--screen),0 0 12px rgba(255,106,38,.8)}
.meter__scale{display:flex;justify-content:space-between;font:600 var(--fs-label)/1 var(--font-mono);color:var(--screen-dim)}
/* <div class="hist"><i data-wr="48.25" style="--h:84"></i>…</div>  inside a .screen */
.hist{display:flex;align-items:flex-end;gap:2px;height:150px}
.hist>i{flex:1;height:calc(var(--h)*1%);min-height:1px;background:var(--wr,var(--oled));border-radius:1px 1px 0 0}
.axis{position:relative;height:20px;margin-top:8px;border-top:1px solid var(--screen-line);font:600 var(--fs-label)/1 var(--font-mono);color:var(--screen-dim)}
.axis>span{position:absolute;top:7px;transform:translateX(-50%);left:var(--x)}
.axis>span:first-child{transform:none}.axis>span:last-child{transform:translateX(-100%)}
/* <div class="split" style="--r:53.5"><span class="split__r">Radiant 53.5%</span><span class="split__d">46.5% Dire</span><div class="split__bar"><i></i></div></div> */
.split{--r:50;display:grid;grid-template-columns:1fr auto;gap:8px 12px;font:700 14px/1 var(--font-mono);font-variant-numeric:tabular-nums}
.split__r{color:var(--radiant)}.split__d{color:var(--dire);text-align:right}
.split__bar{grid-column:1/-1;position:relative;height:12px;border-radius:2px;background:var(--dire);overflow:hidden}
.split__bar>i{position:absolute;inset:0 auto 0 0;width:calc(var(--r)*1%);background:var(--radiant);border-right:2px solid var(--bg)}

/* ---------- 17. List rows (row rules, no floating cards) ---------- */
/* <ol class="lrows"><li class="lrow"><div class="tile tile--sm" data-marg="6.1"><img></div><div><b>Kraken Shell</b><small>Tidehunter · Ability</small></div><span class="wr" data-marg="6.1">+6.1</span></li></ol> */
.lrows{border-top:1px solid var(--rule)}
.lrow{display:grid;grid-template-columns:auto minmax(0,1fr) auto;align-items:center;gap:var(--s3) var(--s4);padding:12px 2px;border-bottom:1px solid var(--rule-row)}
.lrow b{display:block;font:600 var(--fs-sm)/1.25 var(--font-body);color:var(--ink)}
.lrow small{display:block;font-size:var(--fs-xs);line-height:1.35;color:var(--muted)}
.lrow .itile__type{display:block;margin-top:3px}
.lrow__rank{font:700 13px/1 var(--font-mono);color:var(--muted);min-width:1.4em}                              /* only for real sequences */
.lrow--rank{grid-template-columns:auto auto minmax(0,1fr) auto}
.screen .lrows{border-top-color:var(--screen-line)}
.screen .lrow{border-bottom-color:var(--screen-line)}
.screen .lrow b{color:var(--screen-ink)}
.screen .lrow small,.screen .lrow__rank{color:var(--screen-dim)}
/* <dl class="spec"><div><dt>Ability Draft</dt><dd>2 tokens</dd></div></dl> */
.spec{border-top:1.5px solid var(--rule-ink)}
.spec>div{display:flex;justify-content:space-between;gap:var(--s4);padding:11px 0;border-bottom:1px solid var(--rule-row);font-size:var(--fs-sm)}
.spec dt{color:var(--text-2)}.spec dd{margin:0;text-align:right;color:var(--ink);font:700 14px/1.5 var(--font-mono)}
/* <ol class="steps"><li><b>Sign in with Steam</b><span>…</span></li></ol>  numbered: a real sequence */
.steps{counter-reset:st;border-top:1px solid var(--rule)}
.steps>li{counter-increment:st;display:grid;grid-template-columns:44px 1fr;gap:4px var(--s4);padding:var(--s4) 0;border-bottom:1px solid var(--rule-row)}
.steps>li::before{content:counter(st,decimal-leading-zero);grid-row:span 2;font:700 14px/1.6 var(--font-mono);color:var(--accent-ink)}
.steps b{font-size:var(--fs-body)}.steps span{color:var(--text-2);font-size:var(--fs-sm)}
/* <div class="faq"><div><h3>Q</h3><p>A</p></div></div> */
.faq h3{font:600 var(--fs-body)/1.35 var(--font-body);color:var(--ink);margin-bottom:6px}
.faq p{color:var(--text-2)}

/* ---------- 18. Keycaps ---------- */
/* <span class="keys"><kbd class="kbd">Ctrl</kbd><kbd class="kbd">Shift</kbd><kbd class="kbd kbd--accent">S</kbd></span> */
.kbd{display:inline-flex;align-items:center;justify-content:center;min-width:36px;height:36px;padding:0 10px;border-radius:7px;background:var(--key-face);border:1px solid var(--key-edge);border-bottom-width:4px;box-shadow:0 1px 0 var(--dev-hi) inset;color:var(--key-ink);font:700 14px/1 var(--font-mono)}
.kbd--accent{background:var(--accent);color:var(--on-accent);border-color:rgba(0,0,0,.3)}
.keys{display:inline-flex;align-items:center;gap:6px;flex-wrap:wrap}
.keys>.kbd+.kbd::before{content:"+";margin:0 10px 0 -18px;color:var(--muted);font-weight:500}
.keys>.kbd+.kbd{margin-left:18px}

/* ---------- 19. Tabs, token gauge, player stripe ---------- */
.tabs{display:inline-flex;gap:2px;padding:3px;border-radius:var(--r-pill);background:var(--bg-2);border:1px solid var(--rule-row);max-width:100%;overflow-x:auto;scrollbar-width:none} /* segmented control, sentence case */
.tabs>*{display:inline-flex;align-items:center;gap:7px;height:34px;padding:0 15px;border-radius:var(--r-pill);border:0;background:none;font:500 14px/1 var(--font-body);color:var(--text-2);text-decoration:none;cursor:pointer;white-space:nowrap}
.tabs>.is-active{background:var(--panel);color:var(--ink);font-weight:600;box-shadow:0 0 0 1px var(--rule)}
.tabs>.is-active::before{content:"";width:6px;height:6px;border-radius:1px;background:var(--accent)}
/* the same "on" state from ARIA, so a page's JS can keep toggling the attribute it already sets */
.tabs>[aria-selected="true"],.tabs>[aria-pressed="true"],.tabs>[aria-checked="true"]{background:var(--panel);color:var(--ink);font-weight:600;box-shadow:0 0 0 1px var(--rule)}
.tabs>[aria-selected="true"]::before,.tabs>[aria-pressed="true"]::before,.tabs>[aria-checked="true"]::before{content:"";width:6px;height:6px;border-radius:1px;background:var(--accent)}
.tabs>:hover{color:var(--ink)}
.tabs>:disabled,.tabs>[aria-disabled="true"]{opacity:.5;cursor:default}
.tabs--sm>*{height:30px;padding:0 12px;font-size:14px}                                                         /* dense toolbars */
.tabs--block{display:flex;width:100%}.tabs--block>*{flex:1 1 0;justify-content:center}                        /* fills its row, equal segments */
.tabs__n{font:600 var(--fs-label)/1 var(--font-mono);color:var(--muted)}                                       /* a count inside a segment: <b class="tabs__n">12</b> */
/* <span class="tabs tabs--block tabs--stack" role="radiogroup"><button aria-pressed="true"><i class="tabs__ic"></i>All</button>…</span>
   STACKED: a glyph above each short word, for four to six choices in a narrow column (the Combo Finder's
   Pairs). The glyph marks the open segment in orange, so the LED square is dropped; the page draws its glyphs. */
.tabs--stack{border-radius:var(--r-md);overflow:visible}
.tabs--stack>*{flex-direction:column;justify-content:center;gap:5px;height:auto;min-width:0;padding:8px 2px 7px;border-radius:9px}
.tabs.tabs--stack>*::before{content:none}
.tabs__ic{flex:none;display:inline-flex;align-items:center;justify-content:center;width:16px;height:16px;font:800 10px/1 var(--font-body);font-style:normal;color:var(--muted)}
.tabs--stack>.is-active .tabs__ic,.tabs--stack>[aria-selected="true"] .tabs__ic,.tabs--stack>[aria-pressed="true"] .tabs__ic,.tabs--stack>[aria-checked="true"] .tabs__ic{color:var(--accent-ink)}
.gauge{display:grid;grid-template-columns:repeat(var(--n,10),1fr);gap:4px}                                    /* token gauge: <div class="gauge"><i class="on"></i>…</div> */
.gauge>i{height:14px;border-radius:2px;background:var(--bg-2);box-shadow:inset 0 0 0 1px var(--rule-row)}
.gauge>i.on{background:var(--accent)}
.stripe{--pc:var(--rule);border-left:4px solid var(--pc)}                                                     /* player colour edge: style="--pc:var(--p3)" */
.is-you{box-shadow:0 0 0 2px var(--accent),var(--accent-glow)}                                                /* the viewer's own card */

/* ---------- 20. Status chips and inline notices ---------- */
/* <span class="chip live">Live</span>  .live|.win .warn .loss .code ; the old chemrage.css names, so a page's JS keeps setting them */
.chip{display:inline-flex;align-items:center;gap:7px;padding:5px 11px;border:1px solid var(--rule);border-radius:var(--r-pill);font:500 var(--fs-xs)/1.2 var(--font-body);color:var(--text-2);white-space:nowrap} /* status pill, sentence case */
.chip.live,.chip.win{color:var(--ok-ink);border-color:currentColor}                                            /* calibrated, connected, won */
.chip.live::before{content:"";width:7px;height:7px;border-radius:50%;background:currentColor;flex:none}        /* live gets a dot */
.chip.warn{color:var(--accent-ink);border-color:currentColor}                                                  /* needs attention */
.chip.loss{color:var(--bad-ink);border-color:currentColor}                                                     /* lost, failed */
.chip.code{font:700 13px/1.2 var(--font-mono);letter-spacing:.06em;color:var(--ink);border-color:var(--field-edge)} /* a code to read out: party code, match id */
/* <div class="notice notice--warn"><b>Two signals disagree.</b> The pool says … </div> */
.notice{display:flex;align-items:flex-start;gap:12px;padding:12px 16px;border:1px solid var(--rule);border-left:3px solid var(--accent);border-radius:var(--r-sm);background:var(--panel);color:var(--text-2);font-size:var(--fs-sm);line-height:1.45} /* inline message in the flow, never floating */
.notice b{color:var(--ink)}
.notice--ok{border-left-color:var(--ok-ink)}.notice--err{border-left-color:var(--bad-ink)}.notice--info{border-left-color:var(--field-edge)}
.notice[hidden]{display:none}

/* ---------- 21. Toolbar (a row of controls; replaces chemrage.css's .bar, which here is a data bar) ---------- */
.toolbar{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s2) var(--s3);min-width:0}                  /* <div class="toolbar">…<span class="toolbar__sp"></span>…</div> */
.toolbar__sp{flex:1 1 0}                                                                                          /* pushes what follows to the right */
.toolbar .small{margin:0}

/* ---------- 22. Data tables (dense, sortable look, numeric columns) ---------- */
/* <div class="dtable-wrap"><table class="dtable"><thead><tr><th class="rk">#</th><th data-s="name">Ability <span class="dir"></span></th><th class="num" data-s="wr">Win rate <span class="dir">▼</span></th></tr></thead>
     <tbody><tr><td class="rk">1</td><td>…</td><td class="num"><span class="wr wr--sm" data-wr="55.8">55.8%</span></td></tr></tbody></table></div> */
.dtable-wrap{min-width:0;overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--rule);border-radius:var(--r-md);background:var(--panel)} /* the table scrolls sideways in here, the page never does */
.dtable-wrap--tall{max-height:min(72vh,760px);overflow:auto}                                                    /* long tables: the header sticks inside the box */
.dtable{width:100%;border-collapse:collapse;font-size:var(--fs-sm);line-height:1.35;color:var(--text);font-variant-numeric:tabular-nums} /* rows on rules, no zebra */
.dtable th{position:sticky;top:0;z-index:1;background:var(--panel);padding:11px 12px 9px;border-bottom:1.5px solid var(--rule-ink);text-align:left;vertical-align:bottom;white-space:nowrap;font:600 var(--fs-label)/1.25 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted)} /* data labels: mono caps */
.dtable td{padding:9px 12px;border-bottom:1px solid var(--rule-row);vertical-align:middle}
.dtable tbody tr:last-child td{border-bottom:0}
.dtable tbody tr:hover td{background:var(--panel-2)}
.dtable .num{text-align:right;font-family:var(--font-mono);font-variant-numeric:tabular-nums;white-space:nowrap} /* numeric column: right-aligned mono, header too */
.dtable td.num{font-weight:600;color:var(--ink)}
.dtable .rk{width:1%;text-align:right;font:600 13px/1 var(--font-mono);color:var(--muted)}                      /* rank: only for a real order */
.dtable td small,.dtable .sub{display:block;font-size:var(--fs-xs);color:var(--muted)}                          /* second line in a cell */
.dtable a{color:var(--ink);text-decoration-color:var(--rule);text-underline-offset:3px}
.dtable a:hover{text-decoration-color:var(--accent)}
/* sortable headers: th[data-s] (the stats site), table.sortable th, th[aria-sort] or th.is-sortable; the sorted one reads ink with an orange arrow */
.dtable th[data-s],.dtable.sortable th,.dtable th[aria-sort],.dtable th.is-sortable{cursor:pointer;-webkit-user-select:none;user-select:none}
.dtable th[data-s]:hover,.dtable.sortable th:hover,.dtable th[aria-sort]:hover,.dtable th.is-sortable:hover{color:var(--ink)}
.dtable th .dir{display:inline-block;min-width:1em;margin-left:2px;color:var(--accent-ink);font-size:10px;vertical-align:1px}
.dtable th:has(>.dir:not(:empty)),.dtable th[aria-sort="ascending"],.dtable th[aria-sort="descending"]{color:var(--ink)}
.dtable--dense{font-size:var(--fs-xs)}.dtable--dense th{padding:8px 10px 7px}.dtable--dense td{padding:6px 10px}  /* many rows */
.dtable tr.is-you td{background:color-mix(in srgb,var(--accent) 9%,var(--panel))}                               /* the viewer's own row */
.dtable--bare{background:none}.dtable--bare th{background:var(--bg)}                                              /* a table straight on the page, no box */

/* ---------- 23. Tabs (underline; switches whole views) — the segmented control is .tabs, section 19 ---------- */
/* <div class="tabbar" role="tablist"><button role="tab" aria-selected="true">Draft</button><button role="tab">Items <b class="tabs__n">3</b></button></div> */
.tabbar{display:flex;gap:var(--s5);border-bottom:1px solid var(--rule);max-width:100%;overflow-x:auto;scrollbar-width:none} /* sentence case, orange underline on the open view */
.tabbar>*{display:inline-flex;align-items:center;gap:8px;height:44px;padding:0 2px;margin-bottom:-1px;border:0;border-bottom:2px solid transparent;border-radius:0;background:none;font:500 15px/1 var(--font-body);color:var(--text-2);text-decoration:none;cursor:pointer;white-space:nowrap}
.tabbar>:hover{color:var(--ink)}
.tabbar>.is-active,.tabbar>[aria-selected="true"],.tabbar>.on{color:var(--ink);font-weight:600;border-bottom-color:var(--accent)}
.tabbar>:focus-visible{border-radius:var(--r-xs)}

/* ---------- 24. Form fields ---------- */
/* <label class="fld"><span class="fld__label">Your slot</span><select class="input">…</select><span class="fld__hint">Who you are on the board.</span></label> */
.fld{display:grid;gap:6px;min-width:0;align-content:start}                                                      /* label, control, hint, stacked */
.fld__label{font:600 var(--fs-xs)/1.3 var(--font-body);color:var(--ink)}                                        /* sentence case, not mono */
.fld__hint{font-size:var(--fs-xs);line-height:1.4;color:var(--muted)}
.fld.is-error .fld__hint{color:var(--bad-ink)}
.fld.is-error .input{border-color:var(--bad-ink)}
.fld--inline{display:inline-flex;align-items:center;gap:10px}                                                   /* label beside the control in a toolbar */
.fld--inline .fld__label{font-weight:500;color:var(--text-2)}
/* <input class="input">  <input class="input input--search" type="search">  <select class="input">  <textarea class="input"> */
.input{width:100%;min-width:0;height:42px;padding:0 12px;border:1px solid var(--field-edge);border-radius:var(--r-sm);background:var(--field-bg);color:var(--ink);font:400 var(--fs-sm)/1.2 var(--font-body);-webkit-appearance:none;appearance:none;transition:border-color .15s,box-shadow .15s} /* text, number, search, select, textarea */
.input::placeholder{color:var(--muted);opacity:1}
.input:hover{border-color:var(--text-2)}
.input:focus,.input:focus-visible{outline:none;border-color:var(--accent);box-shadow:var(--focus);border-radius:var(--r-sm)}
.input:disabled{opacity:.55;cursor:not-allowed}
.input--sm{height:34px;padding:0 10px;font-size:14px}                                                           /* toolbars, boards */
.input--auto{width:auto}                                                                                         /* sized by content, in a row */
.input--mono{font-family:var(--font-mono);font-variant-numeric:tabular-nums;letter-spacing:.02em}              /* codes, ids, links to copy */
.input--search{padding-left:36px;background:var(--i-search) no-repeat 12px 50%/15px 15px,var(--field-bg)}       /* magnifier, themed */
.input--search::-webkit-search-decoration{-webkit-appearance:none}
textarea.input{height:auto;min-height:104px;padding:10px 12px;line-height:1.45;resize:vertical}
select.input{padding-right:36px;cursor:pointer;background:var(--i-chev) no-repeat right 12px center/12px 8px,var(--field-bg)} /* themed chevron */
select.input--sm{padding-right:30px;background-position:right 10px center}
select.input option{background:var(--panel);color:var(--ink)}
/* <label class="chk"><input type="checkbox"> Follow live</label> ; with a hint: <label class="chk"><input type="checkbox"><span>Outline by ± <small>…</small></span></label>  (radio too) */
.chk{display:inline-flex;align-items:flex-start;gap:10px;font-size:var(--fs-sm);line-height:1.4;color:var(--text);cursor:pointer} /* checkbox / radio with its words */
.chk>input{-webkit-appearance:none;appearance:none;flex:none;display:grid;place-content:center;width:18px;height:18px;margin:1px 0 0;border:1.5px solid var(--field-edge);border-radius:4px;background:var(--field-bg);cursor:pointer;transition:background .12s,border-color .12s}
.chk>input::before{content:"";width:10px;height:10px;background:var(--on-accent);clip-path:polygon(14% 44%,0 62%,40% 100%,100% 20%,84% 4%,38% 66%);transform:scale(0);transition:transform .12s var(--ease)}
.chk>input[type="radio"]{border-radius:50%}.chk>input[type="radio"]::before{width:8px;height:8px;border-radius:50%;clip-path:none}
.chk>input:checked{background:var(--accent);border-color:var(--accent)}
.chk>input:checked::before{transform:scale(1)}
.chk>input:hover{border-color:var(--text-2)}
.chk>input:focus-visible{box-shadow:var(--focus)}
.chk>input:disabled{opacity:.5;cursor:not-allowed}
.chk small{display:block;font-size:var(--fs-xs);color:var(--muted)}
.chk--sm{font-size:14px;gap:8px}.chk--sm>input{width:16px;height:16px;margin-top:1px}
/* <input type="file" class="filein" accept="image/*">  the native control: its button drawn as .btn--secondary --sm */
.filein{max-width:100%;font:400 var(--fs-xs)/1.3 var(--font-body);color:var(--text-2)}                         /* file input; keeps the native picker */
.filein::file-selector-button{height:34px;margin-right:12px;padding:0 15px;border:1.5px solid var(--btn-edge);border-radius:var(--r-pill);background:transparent;color:var(--ink);font:600 14px/1 var(--font-body);cursor:pointer}
.filein::file-selector-button:hover{background:var(--panel-2)}
.filein:focus-visible{box-shadow:none}.filein:focus-visible::file-selector-button{box-shadow:var(--focus)}
/* <input type="range" class="slider">  orange thumb on a sunken track */
.slider{-webkit-appearance:none;appearance:none;height:22px;min-width:0;background:none;cursor:pointer;accent-color:var(--accent)} /* range input */
.slider::-webkit-slider-runnable-track{height:6px;border-radius:3px;background:var(--bg-2);box-shadow:inset 0 0 0 1px var(--rule-row)}
.slider::-moz-range-track{height:6px;border-radius:3px;background:var(--bg-2);box-shadow:inset 0 0 0 1px var(--rule-row)}
.slider::-webkit-slider-thumb{-webkit-appearance:none;width:18px;height:18px;margin-top:-6px;border-radius:50%;background:var(--accent);border:2px solid var(--panel);box-shadow:0 0 0 1px var(--field-edge)}
.slider::-moz-range-thumb{width:14px;height:14px;border-radius:50%;background:var(--accent);border:2px solid var(--panel);box-shadow:0 0 0 1px var(--field-edge)}
.slider:focus-visible{box-shadow:none}.slider:focus-visible::-webkit-slider-thumb{box-shadow:var(--focus)}

/* ---------- 25. Dialogs and menus (the only raised things besides the device) ---------- */
/* <dialog class="dlg"><div class="dlg__head"><h2 class="dlg__title">How it works</h2><button class="dlg__x" aria-label="Close">×</button></div>
     <div class="dlg__body"><p>…</p></div><div class="dlg__foot"><button class="btn btn--primary btn--sm">Got it</button></div></dialog>
   or, without <dialog>: <div class="dlg-scrim"><div class="dlg" role="dialog" aria-modal="true">…</div></div> */
.dlg{width:min(520px,calc(100vw - 32px));max-height:calc(100dvh - 32px);overflow:auto;margin:auto;padding:0;background:var(--panel);color:var(--text);border:1px solid var(--rule);border-radius:var(--r-lg);box-shadow:var(--pop-shadow)} /* modal panel */
dialog.dlg::backdrop{background:var(--scrim)}
dialog.dlg:not([open]){display:none}
.dlg--wide{width:min(760px,calc(100vw - 32px))}
.dlg-scrim{position:fixed;inset:0;z-index:80;display:flex;align-items:flex-start;justify-content:center;padding:max(24px,8vh) 16px 24px;overflow:auto;background:var(--scrim)} /* the backdrop for a div dialog */
.dlg-scrim[hidden]{display:none}
.dlg-scrim>.dlg{margin:0 auto}
.dlg__head{display:flex;align-items:flex-start;gap:var(--s3);padding:20px 22px 0}
.dlg__title{font:700 var(--fs-h3)/1.2 var(--font-display);letter-spacing:-.01em;word-spacing:.06em;color:var(--ink)} /* sentence case */
.dlg__x{margin:-4px -6px 0 auto;flex:none;display:grid;place-items:center;width:36px;height:36px;padding:0;border:1px solid var(--rule);border-radius:50%;background:none;color:var(--text-2);font:400 22px/1 var(--font-body);cursor:pointer} /* close */
.dlg__x:hover{color:var(--ink);background:var(--panel-2)}
.dlg__body{display:grid;gap:var(--s3);padding:12px 22px 22px;font-size:var(--fs-sm);line-height:1.5;color:var(--text-2)}
.dlg__foot{display:flex;flex-wrap:wrap;justify-content:flex-end;align-items:center;gap:10px;padding:14px 22px;border-top:1px solid var(--rule-row);background:var(--panel-2)}
/* <div class="popmenu" role="menu"><div class="popmenu__label">X axis</div><button role="menuitemradio" aria-checked="true">Win rate<small>…</small></button><div class="popmenu__sep"></div>…</div> */
.popmenu{position:fixed;z-index:70;min-width:220px;max-width:calc(100vw - 16px);padding:4px;background:var(--panel);color:var(--text);border:1px solid var(--rule);border-radius:var(--r-md);box-shadow:var(--pop-shadow)} /* menu / popover: JS places it */
.popmenu[hidden]{display:none}
.popmenu>button,.popmenu>a{position:relative;display:block;width:100%;padding:9px 12px;border:0;border-radius:var(--r-sm);background:none;color:var(--text);font:500 var(--fs-sm)/1.3 var(--font-body);text-align:left;text-decoration:none;cursor:pointer}
.popmenu>button:hover,.popmenu>a:hover,.popmenu>button:focus-visible,.popmenu>a:focus-visible{background:var(--surface-3);color:var(--ink);box-shadow:none}
.popmenu>[aria-checked]{padding-left:32px}
.popmenu>[aria-checked]::before{content:"";position:absolute;left:12px;top:14px;width:11px;height:6px;border-left:2px solid transparent;border-bottom:2px solid transparent;transform:rotate(-45deg)} /* a drawn check (no glyph fallback) */
.popmenu>[aria-checked="true"]{color:var(--ink);font-weight:600}
.popmenu>[aria-checked="true"]::before{border-color:var(--accent-ink)}
.popmenu small{display:block;margin-top:2px;font:400 var(--fs-xs)/1.35 var(--font-body);color:var(--muted)}
.popmenu__label{padding:8px 10px 4px;font:600 var(--fs-label)/1.2 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted)} /* a group's data label */
.popmenu__sep{height:1px;margin:4px 6px;background:var(--rule-row)}

/* ---------- 26. Toasts ---------- */
/* <div class="snack" role="status">Link copied.</div>  same look as the header's window.crToast; prefer crToast for one-liners */
.snack{position:fixed;left:50%;bottom:24px;z-index:75;transform:translateX(-50%);display:flex;align-items:center;gap:12px;width:max-content;max-width:min(520px,calc(100vw - 32px));padding:11px 18px;background:var(--panel);color:var(--ink);border:1px solid var(--rule);border-left:3px solid var(--accent);border-radius:8px;box-shadow:var(--pop-shadow);font:500 14px/1.4 var(--font-body);animation:cr-rise .22s var(--ease)} /* transient message */
.snack[hidden]{display:none}
.snack--top{top:18px;bottom:auto}                                                                                /* unused: at 18px it sits over the sticky header (feedback #67); the header's toast is bottom centre too */
.snack--ok{border-left-color:var(--ok-ink)}.snack--err{border-left-color:var(--bad-ink)}
.snack .btn--quiet{height:auto;margin-left:auto;font-size:14px}
@keyframes cr-rise{from{opacity:0;transform:translate(-50%,6px)}to{opacity:1;transform:translate(-50%,0)}}

/* ---------- 27. Empty and loading states ---------- */
/* <div class="blank"><b class="blank__title">No draft yet</b><p>Share your Dota window and the board fills in.</p><button class="btn btn--primary btn--sm">Share screen</button></div> */
.blank{display:grid;justify-items:center;gap:10px;padding:var(--s7) var(--s5);text-align:center;border:1.5px dashed var(--rule);border-radius:var(--r-md);color:var(--text-2);font-size:var(--fs-sm);line-height:1.45} /* nothing to show: say what fills it */
.blank__title{font:600 var(--fs-body)/1.3 var(--font-body);color:var(--ink)}
.blank p{max-width:46ch}
.blank--bare{border:0;padding:var(--s6) var(--s4)}
/* <span class="waitline"><i class="spinner"></i>Reading the board…</span> */
.waitline{display:inline-flex;align-items:center;gap:10px;font-size:var(--fs-sm);color:var(--muted)}            /* a loading line in words */
.spinner{display:inline-block;flex:none;width:16px;height:16px;border-radius:50%;border:2px solid var(--rule-row);border-top-color:var(--accent);animation:cr-spin .8s linear infinite;vertical-align:-3px} /* never over a board: keep the old numbers and say "Updating" in .screen__status */
.spinner--lg{width:28px;height:28px;border-width:3px}
/* <span class="skel" style="width:60%"></span>  <span class="skel skel--block" style="height:120px"></span> */
.skel{display:block;height:.9em;margin:.3em 0;border-radius:3px;background:linear-gradient(90deg,var(--bg-2) 0 35%,var(--panel-2) 50%,var(--bg-2) 65% 100%) 0 0/300% 100%;animation:cr-shimmer 1.4s linear infinite} /* placeholder text line before first data */
.skel--block{height:auto;min-height:48px;margin:0;border-radius:var(--r-sm)}
/* <div class="loadbar" role="progressbar" aria-label="Loading"></div>  indeterminate; style="--pct:40" makes it determinate */
.loadbar{position:relative;height:3px;overflow:hidden;border-radius:2px;background:var(--bg-2)}                  /* thin progress line at the top of a module */
.loadbar::after{content:"";position:absolute;inset:0 auto 0 0;width:32%;border-radius:inherit;background:var(--accent);animation:cr-load 1.25s var(--ease) infinite}
.loadbar[style*="--pct"]::after{width:calc(var(--pct)*1%);animation:none;transition:width .3s var(--ease)}
@keyframes cr-spin{to{transform:rotate(360deg)}}
@keyframes cr-shimmer{to{background-position:-150% 0}}
@keyframes cr-load{from{transform:translateX(-100%)}to{transform:translateX(320%)}}
/* inside a screen the states use the screen's tokens */
.screen .blank{border-color:var(--screen-line);color:var(--screen-dim)}
.screen .blank__title{color:var(--screen-ink)}
.screen .waitline{color:var(--screen-dim)}
.screen .spinner{border-color:var(--screen-line);border-top-color:var(--oled)}
.screen .skel{background-image:linear-gradient(90deg,var(--screen-2) 0 35%,#1d2320 50%,var(--screen-2) 65% 100%)}
.screen .loadbar{background:var(--screen-2)}

/* ---------- 28. Keycap sizes (keycaps are section 18) ---------- */
.kbd--sm{min-width:28px;height:26px;padding:0 7px;border-bottom-width:3px;border-radius:5px;font-size:12px;vertical-align:1px} /* a key inside a sentence */

/* ---------- 29. Board screen: the game-dark box for a draft board, and its chrome ---------- */
/* Anything that mirrors the game or the overlay sits in one, in both themes. Its data language
   (ramp outlines, heat bars, marginal chips, wrColor / deltaColor, Radiant green / Dire red) is
   the board's own; only the chrome below is the system's. .screen--board pins the dark tokens
   (section 3), so a .btn, .tabs, .input, .chip or .dtable inside it reads dark on a light page.
   <section class="screen screen--board">
     <header class="screen__bar"><h2 class="screen__title">Draft board</h2><span class="screen__meta">Ability Draft · 10 players</span>
       <div class="screen__tools"><span class="screen__status is-live"><i class="led led--oled"></i>Live</span><button class="btn btn--secondary btn--sm">Reset</button></div></header>
     <div class="screen__body">…the board (scrolls sideways inside here on a phone)…</div>
     <footer class="screen__foot"><div class="screen__key"><span class="screen__key-k">Key</span><span class="screen__key-i">… sample + words</span></div></footer>
   </section>
   THE ASSISTANT'S COMBOS TAB (#combotab, combos.js) is part of the tool's dark board screen, like the
   draft board beside it: a .screen--board in both themes, its search, sort, list and builder in the pinned
   dark tokens; its signed-out, no-combos and no-match messages are .blank in the screen's tokens (section 27).
   GAME-SCALE EXCEPTION to the 12px floor for labels: a label drawn at game scale INSIDE a zoom-fit board
   (board.js's tile tags and chips, recs.js's strip labels) scales with the board (CRBoard.fitZoom) and may
   be under 12px there, as the game's own are; chrome around a board (bars, keys, buttons) never is. */
.screen--board{display:flex;flex-direction:column;min-width:0;padding:0;overflow:hidden;background:var(--board-ground,var(--screen));color:var(--screen-ink)} /* chrome rows + a body that scrolls on its own */
.screen--slab{--board-ground:radial-gradient(120% 90% at 62% 22%,#15302d 0%,#0d1b1a 55%,#0a1312 100%)}       /* the game's teal pool slab (the homepage board) */
.screen--board.screen--flat{border-radius:var(--r-md)}
.screen__bar{display:flex;flex-wrap:wrap;align-items:center;gap:6px 14px;min-height:50px;padding:9px 14px;border-bottom:1px solid var(--screen-line);background:rgba(255,255,255,.015)} /* title row */
.screen__title{font:600 15px/1.25 var(--font-body);color:var(--screen-ink)}                                    /* sentence case Inter, never Cinzel */
.screen__meta{font-size:var(--fs-xs);line-height:1.35;color:var(--screen-dim)}                                  /* one quiet line beside the title */
.screen__tools{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-left:auto}
.screen__body{position:relative;flex:1 1 auto;min-width:0;padding:14px;overflow:auto;-webkit-overflow-scrolling:touch} /* the board; scrolls inside its own box */
.screen__body--flush{padding:0}
.screen__foot{display:flex;flex-wrap:wrap;align-items:center;gap:6px 16px;padding:9px 14px;border-top:1px solid var(--screen-line);font-size:var(--fs-xs);line-height:1.45;color:var(--screen-dim)} /* legend, source line */
.screen__foot b{color:var(--screen-ink);font-weight:600}
.screen__status{display:inline-flex;align-items:center;gap:8px;font:600 var(--fs-label)/1 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--screen-dim);white-space:nowrap} /* LIVE / WAITING / UPDATING: a data label */
.screen__status.is-live{color:var(--oled)}
.screen__status.is-warn{color:#ffb38a}                                                                           /* 9.9:1 on the screen */
.screen__status .led{width:7px;height:7px}
.screen__status:not(.is-live) .led{background:var(--screen-dim);box-shadow:none}
.screen__status.is-warn .led{background:var(--accent);box-shadow:0 0 8px rgba(255,106,38,.6)}
/* <div class="screen__key"><span class="screen__key-k">Key</span><span class="screen__key-i"><span class="mchip">+2.1</span>what this pick adds to your build</span>…</div> */
.screen__key{display:flex;flex-wrap:wrap;align-items:stretch;max-width:100%;font-size:var(--fs-xs);line-height:1.3;color:var(--screen-ink);background:rgba(5,8,7,.38);border:1px solid rgba(255,255,255,.1);border-radius:3px} /* the legend, in a hairline frame */
.screen__key-k{display:flex;align-items:center;padding:6px 10px;border-right:1px solid rgba(255,255,255,.1);font:600 var(--fs-label)/1 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--screen-dim)}
.screen__key-i{display:inline-flex;align-items:center;gap:9px;padding:6px 12px}
.screen__key-i+.screen__key-i{border-left:1px solid rgba(255,255,255,.07)}
.screen__key-i[hidden]{display:none}
.screen--board .label{color:var(--screen-dim)}
@media (max-width:640px){
  .screen__bar,.screen__foot{padding-left:12px;padding-right:12px}
  .screen__body{padding:12px}
  .screen__key{flex-direction:column}
  .screen__key-k{border-right:0;border-bottom:1px solid rgba(255,255,255,.1)}
  .screen__key-i+.screen__key-i{border-left:0}
}

/* ---------- 30. Dark tooltips and cards on any page ---------- */
/* Dark in both themes (pinned tokens, section 3), like the board under them. JS places them;
   a body-level overlay on a data-cr-zoom page divides viewport px by crZoom.get() (header.js).
   <div class="dtip" role="tooltip" hidden><b>Aftershock</b> · Earthshaker<div class="dtip__foot">…</div></div>
   <div class="dtip dtip--card" hidden>  + CRPieceTip.card(…) inside: the piece's full card
   <aside class="dcard">…</aside>  a dark card in the flow of a light page (a pinned pair beside the chart) */
.dtip{position:fixed;z-index:60;pointer-events:none;width:max-content;max-width:min(320px,calc(100vw - 16px));padding:8px 11px;background:rgba(21,26,23,.98);color:var(--text);border:1px solid var(--field-edge);border-radius:var(--r-sm);box-shadow:0 10px 30px rgba(0,0,0,.55),0 0 0 1px #000;font:400 var(--fs-xs)/1.4 var(--font-body);white-space:normal} /* name + hero, a number or two */
.dtip[hidden]{display:none}
.dtip b{color:var(--ink);font-weight:600}
.dtip .m,.dtip small{color:var(--muted)}
.dtip:not(.dtip--card) .v{font:800 13px/1 var(--font-mono);font-variant-numeric:tabular-nums;color:var(--c,var(--ink))}             /* a ramp-coloured value: style="--c:…"; not in a card, whose piece card (piecetip.js .crpt .v) keeps its own face */
.dtip__k{display:block;margin-bottom:3px;font:600 var(--fs-label)/1.2 var(--font-mono);letter-spacing:var(--track-label);text-transform:uppercase;color:var(--muted)}
.dtip__foot{margin-top:9px;padding-top:8px;border-top:1px solid var(--rule)}
.dtip--card{box-sizing:border-box;width:300px;max-width:calc(100vw - 16px);max-height:calc(100dvh - 16px);overflow:hidden;padding:12px 14px 13px;box-shadow:0 14px 36px rgba(0,0,0,.7),0 0 0 1px #000} /* holds a piece card */
.dtip--card>.crpt-w{width:auto;max-width:none}
.dtip.is-pinned{pointer-events:auto;border-color:var(--accent)}                                                 /* tapped open on touch: it takes clicks */
.dcard{background:var(--panel);color:var(--text);border:1px solid var(--rule);border-radius:var(--r-md);padding:var(--s4);box-shadow:0 0 0 1px #000} /* dark card in the flow */
.dcard .h3{color:var(--ink)}
/* the shared JS overlays (pinned dark in section 3, their own CSS in their scripts): keep them on the system's face */
html[data-cr-theme] .crpt-tip{background:rgba(21,26,23,.98);border-color:var(--field-edge);box-shadow:0 14px 36px rgba(0,0,0,.7),0 0 0 1px #000} /* piecetip.js bind()'s hover card (its CSS loads later, so this outranks it) */

/* Feedback #71: the cross-page view transition's opt-in, here in the render-blocking
   stylesheet so it is in force before the new page's first render (header.js's injected
   copy lands too late for that on the stats pages); header.js names .cr-head */
@view-transition{navigation:auto}
::view-transition-old(root){animation:none;opacity:0}
::view-transition-new(root){animation:none}
@media (prefers-reduced-motion:reduce){@view-transition{navigation:none}}
@media (prefers-reduced-motion:reduce){*{transition:none!important;animation:none!important}}
