/* ============================================================
   llm-demo — deep purple, system fonts, no external assets
   Sibling of nodejavascript.com: same palette, same family feel.
   ============================================================ */

:root {
  /* 🔴 THIS SITE'S OWN BACKGROUND, AND IT HAS TO STAY ITS OWN (standard part 5b).
     It was `#08050d` — the exact value the APEX used — so the reference
     implementation and its parent were the same page to anyone glancing at a tab.
     The register measured it, and the compliance check flagged it. A violet-black
     of this site's own hue, so the tab, the page and the header bar agree. */
  --bg: #0a0c18;
  --bg-soft: #0b0e1c;
  --surface: #111524;
  --surface-2: #161c2e;
  --line: rgba(255, 255, 255, 0.09);
  --border-strong: rgba(255, 255, 255, 0.16);

  --text: #f2ede2;
  --muted: #b0a894;

  --accent: #d4af37;
  --accent-deep: #b6912a;
  --accent-soft: rgba(212, 175, 55, 0.14);

  --yellow: #fbbf24;
  --yellow-bright: #fcd34d;
  --yellow-ink: #1f1300;

  --radius: 14px;
  --radius-lg: 22px;
  --container: 940px;

  --font-sans: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace;
}

* {
  box-sizing: border-box;
}

/* `hidden` has to beat any display rule, or a control hidden in the markup comes
   back the moment a class gives it a display — the attribute only sets
   `display: none` at the lowest possible weight. The cookie bar and its two views
   swap places by setting `hidden`, and two of them are laid out with flex, so
   without this the ask stays on screen underneath the panel and the swap silently
   does nothing. */
[hidden] {
  display: none !important;
}

html,
body {
  margin: 0;
  padding: 0;
}

html {
  background: var(--bg);
  scroll-behavior: smooth;
}

body {
  min-height: 100vh;
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 16px;
  line-height: 1.6;
  background:
    radial-gradient(1100px 600px at 12% -8%, rgba(212, 175, 55, 0.16), transparent 60%),
    radial-gradient(900px 500px at 92% 4%, rgba(251, 191, 36, 0.07), transparent 62%),
    linear-gradient(180deg, var(--bg) 0%, #0a0713 55%, var(--bg) 100%);
  background-attachment: fixed;
}

/* 🔴 THE ABSTRACT — the extra touch the apex had and the rest of the family did not.
   Measured in a real browser on 19 Sep 2026: this site painted two gradients and no geometry,
   and so did eight others, while nodejavascript.com painted a masked grid. George, verbatim:
   *"the rest of the sites have lovely theme colors and gradients, but maybe missing the extra
   touch of a background abstract."*

   This site's geometry is a FINE DIAGONAL HATCH, in the site's own violet — one direction, thin,
   close together, which is a shape no other site in the family draws. It is its own fixed layer
   rather than another entry in body's gradient stack for one reason: a pattern has to FADE, and
   nothing fades a background image except a mask. A mask on `body` would fade the page's own
   background with it; masked here, the hatch dissolves before the fold, so there is no edge to
   see — which is the half of part 5d that matters. */
.dvs-pattern {
  position: fixed;
  inset: 0;
  z-index: -1;
  pointer-events: none;
  background-image:
    radial-gradient(circle at 50% 50%, rgba(212, 175, 55, 0.17) 0 1.4px, rgba(0, 0, 0, 0) 1.5px),
    radial-gradient(circle at 50% 50%, rgba(230, 57, 70, 0.11) 0 1px, rgba(0, 0, 0, 0) 1.1px);
  background-size: 34px 34px, 17px 17px;
  background-repeat: repeat;
  -webkit-mask-image: radial-gradient(122% 82% at 50% 0%, #000 18%, rgba(0, 0, 0, 0) 84%);
  mask-image: radial-gradient(122% 82% at 50% 0%, #000 18%, rgba(0, 0, 0, 0) 84%);
}

/* ---- this site's own components: the ticket, the ball, the scoreboard ---- */

.lines {
  list-style: none;
  margin: 22px 0 10px;
  padding: 0;
  display: grid;
  gap: 10px;
}

.lines li {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--border, rgba(255, 255, 255, 0.12));
  border-radius: var(--radius);
  background: rgba(255, 255, 255, 0.03);
}

.lines .ln {
  flex: 0 0 auto;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--muted);
  min-width: 52px;
}

.ball {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  font-size: 1rem;
  color: #1a1403;
  background: linear-gradient(180deg, #f0d477, var(--accent));
  box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.18);
}

.actions { margin: 16px 0 0; }

/* The reason list under a line. It is the part George asked for by name — "tell it
   why its picking these numbers" — so it is set as prose with a marker, not as a
   table or a run-on paragraph. */
.why {
  list-style: none;
  margin: 18px 0 0;
  padding: 0;
  display: grid;
  gap: 12px;
}

.why li {
  position: relative;
  padding-left: 20px;
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--text, #e9e6dc);
}

.why li::before {
  content: "";
  position: absolute;
  left: 2px;
  top: 0.62em;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent);
}

.why b { color: var(--accent); }

.actions button {
  font: inherit;
  font-size: 0.92rem;
  padding: 10px 16px;
  border-radius: 999px;
  border: 1px solid var(--accent);
  background: var(--accent-soft);
  color: var(--text);
  cursor: pointer;
}

.actions button:hover { background: rgba(212, 175, 55, 0.22); }
.actions button.done { border-color: #7fd18a; color: #cdebd2; }

.tablewrap {
  overflow-x: auto;
  margin: 14px 0 18px;
  border: 1px solid var(--border, rgba(255, 255, 255, 0.12));
  border-radius: var(--radius);
}

.tablewrap table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.92rem;
}

.tablewrap caption {
  caption-side: top;
  text-align: left;
  padding: 12px 14px 6px;
  color: var(--muted);
  font-size: 0.86rem;
}

.tablewrap th,
.tablewrap td {
  padding: 8px 14px;
  text-align: left;
  border-bottom: 1px solid rgba(255, 255, 255, 0.07);
  white-space: nowrap;
}

.tablewrap thead th {
  font-size: 0.78rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--muted);
  font-weight: 600;
}

.tablewrap tbody th { font-weight: 500; }
.tablewrap tbody tr:last-child th,
.tablewrap tbody tr:last-child td { border-bottom: 0; }
.tablewrap td { font-variant-numeric: tabular-nums; }
.tablewrap .good { color: #7fd18a; }
.tablewrap .bad { color: #f08a7a; }

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  * {
    transition: none !important;
    animation: none !important;
  }
}

/* ---------- shell ---------- */

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
}
.skip:focus {
  left: 8px;
  top: 8px;
  z-index: 20;
  padding: 8px 12px;
  border-radius: 8px;
  background: var(--accent);
  color: #101425;
  font-weight: 700;
}

.top {
  position: sticky;
  top: 0;
  z-index: 10;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 18px;
  align-items: center;
  justify-content: space-between;
  padding: 12px 20px;
  background: rgba(8, 5, 13, 0.82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--text);
  text-decoration: none;
}
.brand .mark {
  color: var(--accent);
  display: inline-flex;
}
.brand b {
  display: block;
  font-size: 15px;
  letter-spacing: 0.2px;
}
.brand small {
  display: block;
  color: var(--muted);
  font-size: 11.5px;
  letter-spacing: 0.4px;
  text-transform: uppercase;
}

.top nav {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
  font-size: 14px;
}
.top nav a {
  color: var(--muted);
  text-decoration: none;
}
.top nav a:hover,
.top nav a:focus-visible {
  color: var(--text);
}

main {
  max-width: var(--container);
  margin: 0 auto;
  padding: 32px 20px 60px;
}

/* ---------- hero ---------- */

.hero {
  padding: 26px 0 34px;
}

h1 {
  font-size: clamp(30px, 6vw, 46px);
  line-height: 1.1;
  margin: 0 0 14px;
  letter-spacing: -0.5px;
}

.lede {
  font-size: clamp(16px, 2.4vw, 19px);
  color: #ded6c0;
  margin: 0 0 22px;
  max-width: 62ch;
}

.facts {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 10px;
}
.facts li {
  position: relative;
  padding-left: 22px;
  color: var(--muted);
  font-size: 14.5px;
}
.facts li::before {
  content: "";
  position: absolute;
  left: 4px;
  top: 10px;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--yellow);
}
.facts b {
  color: var(--text);
}

/* ---------- cards ---------- */

.card {
  background: linear-gradient(180deg, var(--surface) 0%, var(--surface-2) 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  padding: 22px;
  margin: 0 0 22px;
  box-shadow: 0 12px 34px -20px rgba(0, 0, 0, 0.7);
}

.card h2 {
  display: flex;
  align-items: center;
  gap: 12px;
  font-size: clamp(19px, 3.4vw, 24px);
  margin: 0 0 8px;
  letter-spacing: -0.2px;
}

.card h3 {
  font-size: 15px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  margin: 0 0 8px;
}

.step {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px;
  height: 30px;
  flex: 0 0 30px;
  border-radius: 50%;
  background: var(--accent-soft);
  border: 1px solid rgba(212, 175, 55, 0.4);
  color: var(--accent);
  font-size: 15px;
  font-weight: 700;
}

.sub {
  color: var(--muted);
  font-size: 14.5px;
  margin: 0 0 18px;
  max-width: 70ch;
}

.small {
  font-size: 13.5px;
  margin: 10px 0 0;
}
.muted {
  color: var(--muted);
}

.mono {
  font-family: var(--font-mono);
  font-size: 12.5px;
  color: #d9d0b6;
  word-break: break-word;
}

/* ---------- chips ---------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 16px;
}

.chip {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 3px;
  padding: 10px 14px;
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid var(--line);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  cursor: pointer;
  text-align: left;
}
.chip strong {
  font-weight: 700;
}
.chip span {
  color: var(--muted);
  font-size: 12px;
}
.chip:hover {
  border-color: var(--border-strong);
}
.chip.is-on {
  background: var(--accent-soft);
  border-color: rgba(212, 175, 55, 0.55);
  color: #fdf8ea;
}
.chip.is-on span {
  color: #ded1a2;
}
.presets .chip {
  min-width: 190px;
}

/* ---------- fields ---------- */

.field {
  display: block;
  margin: 0 0 14px;
}
.label {
  display: block;
  font-size: 12.5px;
  text-transform: uppercase;
  letter-spacing: 0.5px;
  color: var(--muted);
  margin-bottom: 6px;
}
.label b {
  color: var(--text);
  font-family: var(--font-mono);
  text-transform: none;
  letter-spacing: 0;
}

textarea,
input[type="text"] {
  width: 100%;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.32);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 13px;
  line-height: 1.55;
  resize: vertical;
}
textarea:focus,
input[type="text"]:focus {
  outline: 2px solid rgba(212, 175, 55, 0.6);
  outline-offset: 1px;
  border-color: transparent;
}

input[type="range"] {
  width: 100%;
  accent-color: var(--accent);
}

.sliders {
  display: grid;
  gap: 8px 18px;
}
@media (min-width: 640px) {
  .sliders {
    grid-template-columns: repeat(3, minmax(0, 1fr));
  }
}

/* ---------- buttons ---------- */

.row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin: 16px 0;
}

button.primary,
button.ghost {
  font: inherit;
  font-weight: 700;
  border-radius: 12px;
  padding: 12px 18px;
  cursor: pointer;
  border: 1px solid transparent;
}
button.primary {
  background: var(--yellow);
  color: var(--yellow-ink);
}
button.primary:hover:not(:disabled) {
  background: var(--yellow-bright);
}
button.ghost {
  background: transparent;
  border-color: var(--border-strong);
  color: var(--text);
  font-weight: 600;
}
button.ghost:hover:not(:disabled) {
  border-color: var(--accent);
  color: #fdf8ea;
}
button:disabled {
  opacity: 0.42;
  cursor: not-allowed;
}
button:focus-visible,
a:focus-visible {
  outline: 2px solid var(--yellow);
  outline-offset: 2px;
}

/* ---------- progress ---------- */

.progress {
  height: 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.07);
  overflow: hidden;
  border: 1px solid var(--line);
}
.progress-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--accent-deep), var(--accent), var(--yellow));
  transition: width 160ms linear;
}

.status {
  min-height: 21px;
  margin: 12px 0 6px;
  font-size: 14px;
  color: var(--muted);
}
.status.is-ok {
  color: #b9f6c8;
}
.status.is-warn {
  color: var(--yellow-bright);
}

/* ---------- training numbers ---------- */

.train-grid {
  display: grid;
  gap: 14px;
  margin-top: 12px;
}
@media (min-width: 700px) {
  .train-grid {
    grid-template-columns: minmax(0, 1fr) 220px;
  }
}

#lossChart {
  width: 100%;
  height: 120px;
  display: block;
  border-radius: 10px;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.28);
}

.numbers {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(88px, 1fr));
  gap: 8px;
  margin: 0;
  align-content: start;
}
.numbers > div {
  background: rgba(0, 0, 0, 0.25);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 10px;
}
.numbers dt {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.4px;
  color: var(--muted);
}
.numbers dd {
  margin: 2px 0 0;
  font-family: var(--font-mono);
  font-size: 14px;
  color: var(--text);
}

/* ---------- model stats ---------- */

.stats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 8px;
}
.stats > div {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  align-items: baseline;
  background: rgba(0, 0, 0, 0.24);
  border: 1px solid var(--line);
  border-radius: 10px;
  padding: 8px 11px;
  font-size: 13px;
}
.stats span {
  color: var(--muted);
}
.stats b {
  font-family: var(--font-mono);
  font-weight: 600;
  color: var(--text);
}

/* ---------- test panel ---------- */

.test {
  border-color: rgba(212, 175, 55, 0.28);
}
.test.is-ready {
  box-shadow: 0 0 0 1px rgba(212, 175, 55, 0.3), 0 16px 44px -22px rgba(212, 175, 55, 0.6);
}

/* ---------- the verdict: "did it work?" ---------- */

.verdict {
  margin: 12px 0 0;
  padding: 11px 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
  font-size: 14px;
  line-height: 1.5;
  display: none;
}
.verdict:not(:empty) {
  display: block;
}
.verdict.is-good {
  border-color: rgba(120, 220, 150, 0.4);
  background: rgba(120, 220, 150, 0.09);
  color: #c5f7d2;
}
.verdict.is-bad {
  border-color: rgba(244, 184, 96, 0.42);
  background: rgba(244, 184, 96, 0.09);
  color: #f7d9a8;
}

.lookfor {
  margin: 12px 0 0;
  border: 1px solid var(--line);
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.22);
}
.lookfor summary {
  padding: 10px 14px;
  cursor: pointer;
  font-size: 13.5px;
  color: var(--accent);
}
.lookfor[open] summary {
  border-bottom: 1px solid var(--line);
}
.lookfor p {
  margin: 0;
  padding: 10px 14px 0;
  font-size: 13.5px;
  line-height: 1.55;
  color: var(--muted);
}
.lookfor p:last-child {
  padding-bottom: 12px;
}
.lookfor b {
  color: var(--text);
}

.samples {
  display: grid;
  gap: 10px;
  margin-top: 12px;
}

.sample {
  margin: 0;
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--line);
  background: rgba(0, 0, 0, 0.34);
  font-family: var(--font-mono);
  font-size: 13.5px;
  line-height: 1.5;
  white-space: pre-wrap;
  word-break: break-word;
  color: #f0ebdc;
}

/* ---------- how it works / honesty ---------- */

.how {
  margin: 0;
  padding-left: 22px;
  display: grid;
  gap: 10px;
  color: var(--muted);
  font-size: 14.5px;
}
.how b {
  color: var(--text);
}

.two-col {
  display: grid;
  gap: 18px;
}
@media (min-width: 700px) {
  .two-col {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.two-col ul {
  margin: 0;
  padding-left: 20px;
  color: var(--muted);
  font-size: 14.5px;
  display: grid;
  gap: 8px;
}

a {
  color: var(--accent);
}
a:hover {
  color: #e8cf7a;
}

/* ---------- footer ---------- */

/* 🔴 `.site-footer` until 27 September 2026, while the markup writes
   `<footer class="foot">` — so the border, the padding and the centring never
   appeared either. Same fault as the three rules below, same evening. */
.foot {
  border-top: 1px solid var(--line);
  padding: 26px 20px 40px;
  text-align: center;
  color: var(--muted);
  font-size: 13.5px;
}
/* ---------- the footer ----------

   🔴 THE NAMES HERE MUST MATCH THE MARKUP, AND THEY DID NOT. This stylesheet
   carried `.footer-brand` / `.footer-links` / `.footer-copy` while the page
   writes `.foot-brand` / `.foot-links` / `.foot-line` — so not one of these
   rules ever applied. The brand line lost its colour and its gap, and the links
   list kept the browser's own bullets and stacked into three lines instead of
   one row. George found it by looking at the page on 27 September 2026, and no
   existing test could have: the markup was valid, and every check read markup
   rather than geometry. Two browser checks now read the rendered boxes.
*/
.foot-brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--muted);
}
.foot-brand .mark {
  color: var(--accent);
  display: inline-flex;
}
.foot-brand a {
  color: var(--text);
  text-decoration: none;
}
.foot-brand a:hover {
  color: var(--accent);
}
/* 🔴 `.foot-links` WAS HERE AND IS DELETED WITH THE MARKUP IT STYLED (27 September 2026).
   Leaving the rules behind would be the same class of fault in reverse: a stylesheet that
   names markup nobody writes. The footer is the brand line, the copyright with the cookie
   door, and nothing else. */

/* 🔴 A SENTENCE IN A TABLE NEEDS TO WRAP. `.tablewrap` sets `white-space:
   nowrap` on every cell, which is right for a table of numbers and wrong for the
   per-game measurement table, whose last column is a phrase — the first build
   cut it off mid-sentence behind a horizontal scrollbar. The class says which
   table is which rather than relaxing the rule for all of them. */
.tablewrap table.wrap th,
.tablewrap table.wrap td {
  white-space: normal;
}

/* ---------- the games menu, and the one page per game ----------

   The shelf: `/games/` lists every history held and every game page carries the
   same list, so any game is one click from any other. There is no nav in the
   brand bar — part 3 keeps that to the mark and the site's own name — so the
   navigation lives in the page, where it can be as long as the shelf is. */
.menu ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 8px;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
}
.menu li a {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: baseline;
  gap: 4px 14px;
  padding: 10px 13px;
  border: 1px solid var(--line);
  border-radius: 10px;
  text-decoration: none;
  color: var(--text);
}
.menu li a:hover {
  border-color: var(--accent);
}
.menu li a span {
  color: var(--muted);
  font-size: 12.5px;
}
.menu li a[aria-current="page"] {
  border-color: var(--accent);
  color: var(--accent);
}

/* 🔴 THE TINY YELLOW STAR ON EVERY GITHUB LINK — part 4b of the nodejavascript site standard.
   The star takes the page's own yellow (`--yellow`) and the label does NOT: a yellow star beside a
   yellow label is the misreading the rule names. `display: inline-block` is load-bearing, because
   a global `svg { display: block }` would drop the star onto a line of its own. */
.gh-star {
  display: inline-block;
  width: 0.85em;
  height: 0.85em;
  margin-right: 5px;
  flex: none;
  fill: var(--yellow);
  vertical-align: -0.05em;
}

.foot-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 6px 14px;
  margin: 12px 0 0;
  font-size: 12.5px;
  color: rgba(168, 156, 196, 0.75);
}

/* ---------- the cookie bar ----------

   The same consent model as inputresponse.com, in this page's colours. Three
   things here are deliberate and should stay that way.

   It sits in one row - the question, then the two answers - because a banner that
   stacks into paragraphs is a banner people resent. The two answers carry the
   page's own `ghost` class, so they are the same size, the same weight and the
   same distance from the reader: no accept-first order, no smaller decline, and
   no colour that quietly says which one is welcome. And the detail lives one link
   away rather than in the bar itself. */

/* A fixed banner sits on top of whatever is behind it and takes the click, so the
   page leaves exactly the banner's own height free while it is up - measured and
   written back by consent.js, and reset to zero the moment the question is
   answered. Before this the footer could not be clicked at all until a visitor
   answered a question about cookies, which is not a question anyone should have to
   answer to reach a link. */
body {
  padding-bottom: var(--consent-height, 0px);
}

.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 22px;
  padding: 13px 20px;
  background: rgba(27, 16, 44, 0.96);
  border-top: 1px solid var(--line);
  backdrop-filter: blur(8px);
  /* It is the last thing on the screen, so it must never be taller than the
     screen. On a short viewport - a phone in landscape is about 320px tall - the
     stacked layout could otherwise grow past the top edge, and the part above it
     is fixed to the window: it cannot be scrolled to and cannot be clicked.
     Capped and made scrollable, every part of the question stays reachable. `dvh`
     is the height the browser actually gives the page once its own toolbars are
     accounted for; `vh` stays first for anything that does not know it. */
  max-height: calc(100vh - 12px);
  max-height: calc(100dvh - 12px);
  overflow-y: auto;
}
.consentTitle {
  flex: 0 0 auto;
  margin: 0;
  font-size: 14px;
  color: var(--text);
  white-space: nowrap;
}
.consentText {
  flex: 1 1 300px;
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
}
.consentActions {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  flex: 1 1 auto;
  gap: 10px;
}
.consentActions button {
  min-width: 0;
  padding: 10px 14px;
}
/* An anchor does not inherit body colour, so a link dropped into new markup gets
   the browser's default blue - which is out of place on this panel. Anything that
   wants to look like this site has to say so. */
.consentText a {
  color: var(--text);
}

/* The question and the longer answer share ONE fixed bar and swap places inside
   it, rather than a second dialog opening over the first. That is not tidiness:
   this bar is the element whose height is measured and reserved at the bottom of
   the page, and the observer already follows it - so the taller view is measured
   like the shorter one instead of guessed at. */
.consentAsk {
  flex: 1 1 320px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 22px;
}
.consentPrefs {
  flex: 1 1 100%;
}
/* The title's row, so the way out sits at the top right of the panel and not among
   the answers at the bottom. A panel with no dismiss is a consent wall: somebody
   who opened it to LOOK had to answer it again to get out. */
.consentHead {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.consentClose {
  flex: 0 0 auto;
  background: none;
  border: 1px solid var(--line);
  border-radius: 10px;
  color: var(--muted);
  font: inherit;
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  padding: 3px 10px;
}
.consentClose:hover,
.consentClose:focus-visible {
  color: var(--text);
  border-color: var(--text);
}
/* The way to the longer answer, and quieter than the two answers on purpose: it is
   not a third answer to the question, and it must not read as one. */
.consentSettings {
  flex: 0 0 auto;
  color: var(--muted);
}
/* A control that looks like a link because it reads like one - the footer door and
   the settings offer. Two of them drawn differently is how a page starts looking
   unfinished. */
.linkish {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  color: inherit;
  cursor: pointer;
  text-decoration: none;
}
.linkish:hover,
.linkish:focus-visible {
  color: var(--accent);
  text-decoration: underline;
}

/* EVERY PURPOSE IS NAMED, and there is exactly one real choice to name: this site
   has no strictly necessary cookie to describe, so it does not invent a row to
   look thorough. */
.consentList {
  list-style: none;
  margin: 8px 0 0;
  padding: 0;
}
.consentRow {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px 16px;
  padding: 10px 0;
  border-top: 1px solid var(--line);
}
.consentRow > div {
  flex: 1 1 260px;
  min-width: 0;
}
.consentRowName {
  margin: 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--text);
}
.consentRowWhy {
  margin: 2px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--muted);
}

/* The switch. Its ring is drawn from `aria-checked`, so what the eye sees and what
   a screen reader announces are the same attribute and cannot drift apart -
   nothing in the script toggles a class. The word beside it carries the state as
   well, because a state shown only in colour is a state some readers cannot see. */
.consentSwitch {
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 6px 12px;
  font: inherit;
  font-size: 12px;
  color: var(--muted);
  cursor: pointer;
}
.consentSwitch .consentDot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--muted);
}
.consentSwitch[aria-checked="true"] {
  border-color: var(--accent);
  color: var(--text);
}
.consentSwitch[aria-checked="true"] .consentDot {
  background: var(--accent);
}
