/*
JHN Computing — design system stylesheet ("JHN Arcade", variant A "Crest").
v1, 2026-10-16. Docs: docs/design-system.md. Live style guide: /teacher/design/.

Include from any page with a relative path, e.g. from a folder one level down:
    <link rel="stylesheet" href="../shared/jhn.css">
    <script src="../shared/jhn.js"></script>
and opt in to the base styles with <body class="jhn">.

Rules this file encodes (sources in docs/design-system.md):
- Colour comes only from the --jhn-* tokens below. Light is the default;
  dark follows the device unless the viewer picked a theme (data-theme on
  <html>, set by jhn.js). Every token pair a page draws passes WCAG 2.2 AA
  in both themes; tools/browser/regress.mjs re-checks this on every run.
- Right / wrong / info use Okabe-Ito hues, each split into a fill (borders,
  icons: 3:1+) and an ink (text: 4.5:1+), and are never shown by colour
  alone: always an icon (✓ ✗ i), a solid or dashed edge, and words.
- Atkinson Hyperlegible for all text, its Mono for code and registers,
  Pixelify Sans only for scores, timers and the odd fun label.
- Every control is at least 44px tall and has a visible focus ring.
- Animation is short, only on feedback, and off under prefers-reduced-motion.
*/

/* ---------- fonts (self-hosted, SIL OFL 1.1, see fonts/LICENSE-*.txt) ---------- */

@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("fonts/atkinson-hyperlegible-next-latin-wght-normal.woff2") format("woff2");
  font-weight: 200 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible Next";
  src: url("fonts/atkinson-hyperlegible-next-latin-wght-italic.woff2") format("woff2");
  font-weight: 200 800; font-style: italic; font-display: swap;
}
@font-face {
  font-family: "Atkinson Hyperlegible Mono";
  src: url("fonts/atkinson-hyperlegible-mono-latin-wght-normal.woff2") format("woff2");
  font-weight: 200 800; font-style: normal; font-display: swap;
}
@font-face {
  font-family: "Pixelify Sans";
  src: url("fonts/pixelify-sans-latin-wght-normal.woff2") format("woff2");
  font-weight: 400 700; font-style: normal; font-display: swap;
}

/* ---------- tokens: light (default) ---------- */

:root, .jhn-theme-light {
  --jhn-ground: #eef2f8;        /* page background: a pale tint, not pure white (BDA) */
  --jhn-surface: #ffffff;       /* cards, panels, inputs */
  --jhn-surface-2: #e1e8f2;     /* registers, table heads, pressed toggles */
  --jhn-ink: #0b2341;           /* text: school navy */
  --jhn-muted: #44536b;         /* secondary text */
  --jhn-line: #6b7c97;          /* borders that identify a control (3:1) */
  --jhn-header: #0b2341;        /* site header: navy in both themes */
  --jhn-header-ink: #ffffff;
  --jhn-header-muted: #cdd8ea;
  --jhn-gold: #f2c230;          /* crest gold, as a fill */
  --jhn-gold-deep: #a77d00;     /* gold edges on light surfaces (3:1) */
  --jhn-gold-ink: #7a5800;      /* gold text on light surfaces (4.5:1) */
  --jhn-on-gold: #0b2341;       /* text on a gold fill */
  --jhn-heart: #b3121f;         /* crest red: brand details only, never "wrong" */
  --jhn-btn: #0b2341;           /* primary button */
  --jhn-btn-ink: #ffffff;
  --jhn-focus: #0057b8;         /* focus ring */
  --jhn-shadow: #0b2341;

  --jhn-correct: #009e73;       /* Okabe-Ito bluish green */
  --jhn-correct-ink: #006b4e;
  --jhn-correct-bg: #e9f7f1;
  --jhn-incorrect: #d55e00;     /* Okabe-Ito vermillion */
  --jhn-incorrect-ink: #a43f00;
  --jhn-incorrect-bg: #fbe5d4;
  --jhn-info: #0072b2;          /* Okabe-Ito blue */
  --jhn-info-ink: #005689;
  --jhn-info-bg: #dcecf8;

  /* categories: tell things apart (whose data, which item), never right or
     wrong. Same fills in both themes, always with --jhn-on-cat text and a
     visible label, so colour is never the only cue. Okabe-Ito based. */
  --jhn-cat-1: #e69f00;         /* orange */
  --jhn-cat-2: #56b4e9;         /* sky blue */
  --jhn-cat-3: #f0e442;         /* yellow */
  --jhn-cat-4: #cc79a7;         /* reddish purple */
  --jhn-cat-5: #c3b1e1;         /* lavender */
  --jhn-cat-6: #8fd3c7;         /* mint */
  --jhn-on-cat: #0b2341;

  --jhn-font-body: "Atkinson Hyperlegible Next", "Atkinson Hyperlegible", system-ui, sans-serif;
  --jhn-font-mono: "Atkinson Hyperlegible Mono", ui-monospace, "Cascadia Mono", Menlo, monospace;
  --jhn-font-display: "Pixelify Sans", "Atkinson Hyperlegible Next", system-ui, sans-serif;

  /* type scale: 18px body, ratio 1.25 */
  --jhn-step--1: 0.95rem;
  --jhn-step-0: 1.125rem;
  --jhn-step-1: 1.4rem;
  --jhn-step-2: 1.75rem;
  --jhn-step-3: 2.2rem;
  --jhn-step-4: 2.75rem;

  /* 4px spacing grid */
  --jhn-space-1: 4px;
  --jhn-space-2: 8px;
  --jhn-space-3: 12px;
  --jhn-space-4: 16px;
  --jhn-space-5: 24px;
  --jhn-space-6: 32px;
  --jhn-space-7: 48px;

  --jhn-radius: 10px;
  --jhn-radius-sm: 6px;
  --jhn-target: 44px;           /* minimum height of anything you can press */
  --jhn-max: 1180px;            /* page content width */
}

/* ---------- tokens: dark (device setting, unless the viewer chose light) ---------- */

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --jhn-ground: #0b2341;
    --jhn-surface: #13335c;
    --jhn-surface-2: #1b3f6e;
    --jhn-ink: #f3f6fb;
    --jhn-muted: #b8c6db;
    --jhn-line: #7f9cc6;
    --jhn-header: #071a32;
    --jhn-header-ink: #ffffff;
    --jhn-header-muted: #b8c6db;
    --jhn-gold: #f2c230;
    --jhn-gold-deep: #f2c230;
    --jhn-gold-ink: #f2c230;
    --jhn-on-gold: #0b2341;
    --jhn-heart: #ff7b7b;
    --jhn-btn: #f2c230;
    --jhn-btn-ink: #0b2341;
    --jhn-focus: #ffd34d;
    --jhn-shadow: #000b1a;
    --jhn-correct: #2fbf8f;
    --jhn-correct-ink: #6ee3bb;
    --jhn-correct-bg: #0f3d3a;
    --jhn-incorrect: #f0822e;
    --jhn-incorrect-ink: #ffab70;
    --jhn-incorrect-bg: #47291c;
    --jhn-info: #4aa8e8;
    --jhn-info-ink: #93ccf3;
    --jhn-info-bg: #163a5e;
    color-scheme: dark;
  }
}

/* ---------- tokens: dark (chosen with the theme toggle, or a .jhn-theme-dark panel) ---------- */

:root[data-theme="dark"], .jhn-theme-dark {
  --jhn-ground: #0b2341;
  --jhn-surface: #13335c;
  --jhn-surface-2: #1b3f6e;
  --jhn-ink: #f3f6fb;
  --jhn-muted: #b8c6db;
  --jhn-line: #7f9cc6;
  --jhn-header: #071a32;
  --jhn-header-ink: #ffffff;
  --jhn-header-muted: #b8c6db;
  --jhn-gold: #f2c230;
  --jhn-gold-deep: #f2c230;
  --jhn-gold-ink: #f2c230;
  --jhn-on-gold: #0b2341;
  --jhn-heart: #ff7b7b;
  --jhn-btn: #f2c230;
  --jhn-btn-ink: #0b2341;
  --jhn-focus: #ffd34d;
  --jhn-shadow: #000b1a;
  --jhn-correct: #2fbf8f;
  --jhn-correct-ink: #6ee3bb;
  --jhn-correct-bg: #0f3d3a;
  --jhn-incorrect: #f0822e;
  --jhn-incorrect-ink: #ffab70;
  --jhn-incorrect-bg: #47291c;
  --jhn-info: #4aa8e8;
  --jhn-info-ink: #93ccf3;
  --jhn-info-bg: #163a5e;
  color-scheme: dark;
}
:root[data-theme="light"] { color-scheme: light; }
.jhn-theme-light, .jhn-theme-dark { background: var(--jhn-ground); color: var(--jhn-ink); }

/* ---------- base (only on pages with <body class="jhn">; :where keeps it easy to override) ---------- */

:where(body.jhn) {
  margin: 0;
  background: var(--jhn-ground);
  color: var(--jhn-ink);
  font-family: var(--jhn-font-body);
  font-size: var(--jhn-step-0);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
:where(.jhn) *, :where(.jhn) *::before, :where(.jhn) *::after { box-sizing: border-box; }
:where(.jhn) :is(h1, h2, h3) { font-family: var(--jhn-font-body); font-weight: 700; line-height: 1.15; margin: 0; text-wrap: balance; }
:where(.jhn) h1 { font-size: var(--jhn-step-3); }
:where(.jhn) h2 { font-size: var(--jhn-step-2); }
:where(.jhn) h3 { font-size: var(--jhn-step-1); }
:where(.jhn) p { margin: 0; max-width: 68ch; }
:where(.jhn) a { color: var(--jhn-ink); text-underline-offset: 3px; }
:where(.jhn) a:hover { color: var(--jhn-focus); }
:where(.jhn) code, :where(.jhn) kbd, :where(.jhn) samp { font-family: var(--jhn-font-mono); }
:where(.jhn) img { max-width: 100%; }

/* `hidden` must always win: components like .jhn-btn set their own display,
   which would otherwise override the browser's [hidden] rule and show it. */
[hidden] { display: none !important; }

/* every page that links this file gets a visible focus ring, opted in or not */
:focus-visible { outline: 3px solid var(--jhn-focus); outline-offset: 3px; }

.jhn-sr { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; }
.jhn-wrap { max-width: var(--jhn-max); margin-inline: auto; padding-inline: var(--jhn-space-4); }
.jhn-main { display: grid; gap: var(--jhn-space-5); padding-block: var(--jhn-space-5) var(--jhn-space-7); }
.jhn-stack { display: grid; gap: var(--jhn-space-3); }
/* a single-column page: <main class="jhn-wrap jhn-main jhn-narrow">. Narrows
   and centres the page's content, so a wide screen isn't half empty. */
.jhn-narrow { --jhn-max: 932px; }
/* The header lines up with a narrow page's content too (older browsers
   without :has() keep the wider header, which still works). */
body:has(main.jhn-narrow) :is(.jhn-header, .jhn-site-footer) .jhn-wrap { --jhn-max: 932px; }
.jhn-row { display: flex; flex-wrap: wrap; gap: var(--jhn-space-3); align-items: center; }
.jhn-muted { color: var(--jhn-muted); }
.jhn-mono { font-family: var(--jhn-font-mono); }
.jhn-display { font-family: var(--jhn-font-display); }

/* ---------- site header (built by JHN.header() in jhn.js) ---------- */

.jhn-header { background: var(--jhn-header); color: var(--jhn-header-ink); text-align: left; }
.jhn-header-in { display: flex; flex-wrap: wrap; align-items: center; gap: var(--jhn-space-3) var(--jhn-space-4); padding-block: var(--jhn-space-3); }
.jhn-logo { width: 52px; height: 52px; flex: none; background: #ffffff; border-radius: var(--jhn-radius-sm); display: grid; place-items: center; }
.jhn-logo img { width: 42px; height: 42px; object-fit: contain; }
.jhn-brand { display: flex; flex-direction: column; min-width: 0; flex: 1 1 220px; }
.jhn-wordmark { margin: 0; font-family: var(--jhn-font-body); font-weight: 700; font-size: var(--jhn-step-2); line-height: 1.1; color: var(--jhn-header-ink); }
.jhn-brand-sub { color: var(--jhn-header-muted); font-size: var(--jhn-step--1); }
.jhn-header-actions { display: flex; flex-wrap: wrap; gap: var(--jhn-space-2); }
.jhn-back { color: var(--jhn-header-ink); font-weight: 700; text-decoration: none; display: inline-flex; align-items: center; min-height: var(--jhn-target); padding-inline: var(--jhn-space-2); border-radius: var(--jhn-radius-sm); }
.jhn-back:hover { color: var(--jhn-header-ink); text-decoration: underline; }
.jhn-header .jhn-btn--quiet { color: var(--jhn-header-ink); border-color: var(--jhn-header-muted); }
.jhn-header .jhn-btn--quiet[aria-pressed="true"] { background: rgba(255, 255, 255, 0.16); }
/* toggles show their state as a tick as well as a fill */
.jhn-btn[aria-pressed]::before { content: ""; display: inline-block; width: 1em; text-align: center; }
.jhn-btn[aria-pressed="true"]::before { content: "✓"; }
.jhn-header :focus-visible { outline-color: #ffd34d; }

/* ---------- site footer: <footer class="jhn-site-footer"> on the home pages ----------
   A band like the header. When the page is shorter than the screen, it sits
   at the bottom of the screen rather than under the last thing on the page. */
body.jhn:has(> .jhn-site-footer) { display: flex; flex-direction: column; min-height: 100svh; }
body.jhn:has(> .jhn-site-footer) > main { flex: 1 0 auto; width: 100%; align-content: start; } /* the spare height goes below, not into its rows */
.jhn-site-footer { background: var(--jhn-header); color: var(--jhn-header-muted); margin-top: var(--jhn-space-6); }
.jhn-site-footer-in { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--jhn-space-2) var(--jhn-space-4); padding-block: var(--jhn-space-4); font-size: var(--jhn-step--1); }
.jhn-site-footer p { margin: 0; }
.jhn-site-footer a { color: var(--jhn-header-ink); font-weight: 700; }
.jhn-site-footer :focus-visible { outline-color: #ffd34d; }

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

.jhn-btn {
  font: 700 var(--jhn-step-0)/1.2 var(--jhn-font-body);
  min-height: var(--jhn-target); padding: 0 var(--jhn-space-5);
  border: 2px solid transparent; border-radius: var(--jhn-radius-sm);
  background: var(--jhn-btn); color: var(--jhn-btn-ink);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--jhn-space-2);
  cursor: pointer; text-decoration: none;
  transition: filter 0.12s ease, transform 0.08s ease;
}
.jhn-btn:hover { filter: brightness(1.12); color: var(--jhn-btn-ink); }
.jhn-btn:active { transform: translateY(1px); }
.jhn-btn--secondary { background: transparent; color: var(--jhn-ink); border-color: var(--jhn-ink); }
.jhn-btn--secondary:hover { color: var(--jhn-ink); background: var(--jhn-surface-2); filter: none; }
.jhn-btn--quiet { background: transparent; color: var(--jhn-ink); border-color: var(--jhn-line); font-weight: 400; padding: 0 var(--jhn-space-3); }
.jhn-btn--quiet:hover { color: var(--jhn-ink); filter: none; background: var(--jhn-surface-2); }
.jhn-btn--quiet[aria-pressed="true"] { background: var(--jhn-surface-2); }
.jhn-btn--big { min-height: 56px; font-size: var(--jhn-step-1); padding: 0 var(--jhn-space-6); }
.jhn-btn:disabled, .jhn-btn[aria-disabled="true"] { opacity: 0.5; cursor: not-allowed; filter: none; transform: none; }

/* ---------- sections and activity cards (home pages; built by JHN.renderActivities) ---------- */

.jhn-section { display: grid; gap: var(--jhn-space-4); padding-block: var(--jhn-space-4); }
.jhn-section-head { display: flex; align-items: baseline; flex-wrap: wrap; gap: var(--jhn-space-2) var(--jhn-space-3); }
.jhn-section-title { font-size: var(--jhn-step-2); }
.jhn-section-note { color: var(--jhn-muted); font-size: var(--jhn-step--1); }
.jhn-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: var(--jhn-space-5); }

.jhn-card {
  background: var(--jhn-surface); color: var(--jhn-ink);
  border: 1px solid var(--jhn-line); border-radius: var(--jhn-radius);
  display: flex; flex-direction: column; min-width: 0; text-decoration: none;
  transition: transform 0.12s ease, box-shadow 0.12s ease, border-color 0.12s ease;
}
a.jhn-card:hover { color: var(--jhn-ink); transform: translateY(-2px); box-shadow: 0 6px 0 -2px var(--jhn-gold); border-color: var(--jhn-ink); }
.jhn-card-top { display: flex; align-items: center; justify-content: space-between; gap: var(--jhn-space-3); padding: var(--jhn-space-4) var(--jhn-space-4) 0; }
.jhn-card-body { display: grid; gap: var(--jhn-space-2); align-content: start; flex: 1; padding: var(--jhn-space-3) var(--jhn-space-4) var(--jhn-space-4); }
.jhn-card-title { font-size: var(--jhn-step-1); font-weight: 700; line-height: 1.2; }
.jhn-card-blurb { color: var(--jhn-muted); font-size: var(--jhn-step--1); }

/* ---------- student home: folding curriculum, search and filters ---------- */

.jhn-filters { display: flex; flex-wrap: wrap; align-items: center; gap: var(--jhn-space-2); padding-block: var(--jhn-space-4); }
.jhn-filter-q { flex: 1 1 16rem; min-width: 0; }
.jhn-menu { position: relative; }
.jhn-menu-btn { list-style: none; gap: var(--jhn-space-1); white-space: nowrap; min-height: var(--jhn-target); }
.jhn-menu-btn::-webkit-details-marker { display: none; }
.jhn-menu.is-active > .jhn-menu-btn { border-color: var(--jhn-ink); font-weight: 700; }
.jhn-menu-list { position: absolute; top: calc(100% + 4px); left: 0; z-index: 20; min-width: 12rem; max-width: calc(100vw - 2 * var(--jhn-space-4)); max-height: 60vh; overflow: auto; display: grid; padding: var(--jhn-space-1); background: var(--jhn-surface); border: 1px solid var(--jhn-ink); border-radius: var(--jhn-radius); box-shadow: 0 6px 0 -2px var(--jhn-line); }
.jhn-menu-list--right { left: auto; right: 0; }
.jhn-menu-item { display: flex; align-items: center; gap: var(--jhn-space-2); min-height: var(--jhn-target); padding: 0 var(--jhn-space-2); border-radius: var(--jhn-radius-sm); cursor: pointer; white-space: nowrap; }
.jhn-menu-item:hover { background: var(--jhn-surface-2); }
.jhn-menu-item input { width: 18px; height: 18px; accent-color: var(--jhn-ink); margin: 0; }
@media (max-width: 480px) {
  .jhn-filter-q { flex-basis: 100%; }
  .jhn-filters { gap: var(--jhn-space-2) var(--jhn-space-1); }
  .jhn-menu-btn, #jhn-clear { padding: 0 var(--jhn-space-2); font-size: var(--jhn-step--1); }
  .jhn-clear-word { display: none; }
}

.jhn-fold { border: 1px solid var(--jhn-line); border-radius: var(--jhn-radius); background: var(--jhn-surface); margin-block: var(--jhn-space-3); }
.jhn-fold .jhn-fold { background: var(--jhn-ground); margin-inline: var(--jhn-space-3); }
.jhn-fold > summary {
  display: flex; align-items: baseline; flex-wrap: wrap;
  gap: var(--jhn-space-2) var(--jhn-space-3);
  padding: var(--jhn-space-3) var(--jhn-space-4);
  cursor: pointer; min-height: var(--jhn-target); list-style: none;
}
.jhn-fold > summary::-webkit-details-marker { display: none; }
/* Newer Chromium hides closed <details> content with content-visibility,
   which still leaves the children with a layout box; make it a real
   display:none so closed cards can't be measured or reached. */
.jhn-fold:not([open]) > :not(summary) { display: none; }
.jhn-fold > summary::before { content: "▸"; color: var(--jhn-gold-ink); flex: none; }
.jhn-fold[open] > summary::before { content: "▾"; }
.jhn-fold--ks > summary .jhn-fold-title { font-size: var(--jhn-step-2); font-weight: 700; }
.jhn-fold--year > summary .jhn-fold-title { font-size: var(--jhn-step-1); font-weight: 700; }
.jhn-fold--unit > summary .jhn-fold-title { font-size: var(--jhn-step-0); font-weight: 700; }
.jhn-fold-note { color: var(--jhn-muted); font-size: var(--jhn-step--1); }
.jhn-fold-count {
  margin-left: auto; font-family: var(--jhn-font-mono); font-size: 0.82rem; line-height: 1.2;
  padding: 3px 8px; border: 1px solid var(--jhn-line); border-radius: var(--jhn-radius-sm);
  background: var(--jhn-surface-2); color: var(--jhn-ink);
}
.jhn-fold-link {
  font: inherit; font-size: var(--jhn-step--1); min-height: 32px; padding: 0 var(--jhn-space-2);
  background: transparent; color: var(--jhn-ink); border: 1px solid var(--jhn-line);
  border-radius: var(--jhn-radius-sm); cursor: pointer;
}
.jhn-fold--unit > .jhn-grid { padding: 0 var(--jhn-space-4) var(--jhn-space-4); }
.jhn-chip--tag { background: transparent; }
.jhn-filter-empty { color: var(--jhn-muted); padding-block: var(--jhn-space-3); }
.jhn-fold[hidden], .jhn-card[hidden] { display: none; }
@media (max-width: 480px) {
  .jhn-fold .jhn-fold { margin-inline: var(--jhn-space-2); }
}

.jhn-panel { background: var(--jhn-surface); border: 1px solid var(--jhn-line); border-radius: var(--jhn-radius); padding: var(--jhn-space-5); display: grid; gap: var(--jhn-space-4); min-width: 0; }

/* pixel icons (JHN.icon); currentColor, crisp at any size */
.jhn-pix { width: 28px; height: 28px; display: block; flex: none; shape-rendering: crispEdges; }

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

.jhn-chips { display: flex; flex-wrap: wrap; gap: var(--jhn-space-1) var(--jhn-space-2); margin-top: var(--jhn-space-2); }
.jhn-chip { font-family: var(--jhn-font-mono); font-size: 0.82rem; line-height: 1.2; padding: 3px 8px; white-space: nowrap;
  border: 1px solid var(--jhn-line); border-radius: var(--jhn-radius-sm); background: var(--jhn-surface-2); color: var(--jhn-ink); }
.jhn-chip--level { font-weight: 700; background: transparent; border-color: var(--jhn-ink); }
.jhn-chip--stretch { border-style: dashed; }

/* CPU stage chips: FETCH / DECODE / EXECUTE. The current one is filled, arrowed and aria-current. */
.jhn-stages { display: flex; flex-wrap: wrap; gap: var(--jhn-space-2); list-style: none; margin: 0; padding: 0; }
.jhn-stage { font-weight: 700; font-size: var(--jhn-step--1); letter-spacing: 0.06em; text-transform: uppercase;
  padding: 6px 12px; border: 2px solid var(--jhn-line); border-radius: var(--jhn-radius-sm); color: var(--jhn-muted); }
.jhn-stage[aria-current="step"], .jhn-stage.is-current { background: var(--jhn-gold); border-color: var(--jhn-gold); color: var(--jhn-on-gold); }
.jhn-stage[aria-current="step"]::before, .jhn-stage.is-current::before { content: "▶ "; }

/* ---------- game pieces: HUD, instruction, registers, answers ---------- */

.jhn-hud { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--jhn-space-3) var(--jhn-space-6); }
.jhn-hud-item { display: grid; }
.jhn-hud-label { font-size: var(--jhn-step--1); color: var(--jhn-muted); }
.jhn-hud-value { font-family: var(--jhn-font-display); font-weight: 600; font-size: var(--jhn-step-3); line-height: 1.1; font-variant-numeric: tabular-nums; }

.jhn-instr { font-family: var(--jhn-font-mono); font-weight: 700; font-size: var(--jhn-step-4); line-height: 1.1; letter-spacing: 0.02em; }
/* Registers sit centred in a row, each a box with its label above its value.
   The accumulator is a bigger register of the same shape, centred on its own
   line above them (the user's preference from the old site, 2026-10-19). */
.jhn-regs { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--jhn-space-3); }
.jhn-reg { display: grid; justify-items: center; text-align: center; gap: 2px; width: 120px; min-width: 0; padding: var(--jhn-space-2) var(--jhn-space-3); border: 2px solid var(--jhn-line); border-radius: var(--jhn-radius-sm); background: var(--jhn-surface-2); }
.jhn-reg-label { font-size: var(--jhn-step--1); color: var(--jhn-muted); }
.jhn-reg-value { font-family: var(--jhn-font-mono); font-weight: 700; font-size: var(--jhn-step-2); font-variant-numeric: tabular-nums; }
/* optional short label for phones ("R1"), with the full name kept for screen readers */
.jhn-reg-short { display: none; }
/* width + auto side margins: centred, and on a line of its own inside .jhn-regs */
.jhn-reg--acc { width: 220px; margin-inline: calc(50% - 110px); padding: var(--jhn-space-3) var(--jhn-space-4); border-width: 3px; border-color: var(--jhn-gold-deep); background: var(--jhn-surface); }
.jhn-reg--acc .jhn-reg-label { color: var(--jhn-ink); font-weight: 700; }
.jhn-reg--acc .jhn-reg-value { font-size: var(--jhn-step-4); line-height: 1.1; }

.jhn-answers { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: var(--jhn-space-3); }
.jhn-answer { font: 700 var(--jhn-step-3)/1 var(--jhn-font-mono); min-height: 72px; border-radius: var(--jhn-radius);
  border: 2px solid var(--jhn-ink); background: var(--jhn-surface); color: var(--jhn-ink); cursor: pointer;
  display: flex; align-items: center; justify-content: center; gap: var(--jhn-space-2); }
.jhn-answer:hover { background: var(--jhn-surface-2); }
.jhn-answer:disabled { cursor: default; }
.jhn-answer.is-right { background: var(--jhn-correct-bg); border-color: var(--jhn-correct); color: var(--jhn-correct-ink); }
.jhn-answer.is-right::after { content: "✓"; font-family: var(--jhn-font-body); }
.jhn-answer.is-wrong { background: var(--jhn-incorrect-bg); border-color: var(--jhn-incorrect); color: var(--jhn-incorrect-ink); border-style: dashed; }
.jhn-answer.is-wrong::after { content: "✗"; font-family: var(--jhn-font-body); }
.jhn-answer.is-dim { opacity: 0.55; }

/* ---------- feedback (JHN.feedback / JHN.toast): icon + words + colour ---------- */

.jhn-fb { display: flex; align-items: center; gap: var(--jhn-space-3); padding: var(--jhn-space-3) var(--jhn-space-4);
  border: 2px solid; border-radius: var(--jhn-radius); font-weight: 700; animation: jhn-in 0.18s ease-out; }
.jhn-fb-icon { flex: none; width: 36px; height: 36px; display: grid; place-items: center; font-size: 22px; line-height: 1;
  border-radius: var(--jhn-radius-sm); color: var(--jhn-surface); }
.jhn-fb-text { display: grid; gap: 2px; }
.jhn-fb-detail { font-weight: 400; }
.jhn-fb--correct { background: var(--jhn-correct-bg); border-color: var(--jhn-correct); color: var(--jhn-correct-ink); }
.jhn-fb--correct .jhn-fb-icon { background: var(--jhn-correct); }
.jhn-fb--incorrect { background: var(--jhn-incorrect-bg); border-color: var(--jhn-incorrect); color: var(--jhn-incorrect-ink); border-style: dashed; }
.jhn-fb--incorrect .jhn-fb-icon { background: var(--jhn-incorrect); }
.jhn-fb--info { background: var(--jhn-info-bg); border-color: var(--jhn-info); color: var(--jhn-info-ink); }
.jhn-fb--info .jhn-fb-icon { background: var(--jhn-info); }
.jhn-fb--complete { background: var(--jhn-surface); border-color: var(--jhn-gold-deep); color: var(--jhn-ink); }
.jhn-fb--complete .jhn-fb-icon { background: var(--jhn-gold); color: var(--jhn-on-gold); }

.jhn-toasts { position: fixed; z-index: 1000; left: 50%; bottom: var(--jhn-space-5); transform: translateX(-50%);
  display: grid; gap: var(--jhn-space-2); width: min(560px, calc(100% - 2 * var(--jhn-space-4))); pointer-events: none; }
.jhn-toasts .jhn-fb { pointer-events: none; box-shadow: 0 6px 0 -2px var(--jhn-shadow); }

/* "How to play" that folds away (<details class="jhn-howto">), so the game
   starts on the first screen. The summary keeps a one-line gist in view. */
.jhn-howto { background: var(--jhn-info-bg); color: var(--jhn-info-ink); border: 2px solid var(--jhn-info); border-radius: var(--jhn-radius); }
.jhn-howto > summary { display: flex; align-items: center; gap: var(--jhn-space-3); min-height: var(--jhn-target); padding: var(--jhn-space-2) var(--jhn-space-4); cursor: pointer; list-style: none; }
.jhn-howto > summary::-webkit-details-marker { display: none; }
.jhn-howto > summary::before { content: "i"; flex: none; width: 28px; height: 28px; display: grid; place-items: center; border-radius: var(--jhn-radius-sm);
  background: var(--jhn-info); color: var(--jhn-surface); font-weight: 700; }
.jhn-howto > summary::after { content: "Show more ▾"; margin-left: auto; flex: none; font-size: var(--jhn-step--1); font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.jhn-howto[open] > summary::after { content: "Show less ▴"; }
.jhn-howto-gist { min-width: 0; }
.jhn-howto-body { padding: 0 var(--jhn-space-4) var(--jhn-space-4) calc(var(--jhn-space-4) + 28px + var(--jhn-space-3)); display: grid; gap: var(--jhn-space-2); }

/* ---------- drag and drop ---------- */

.jhn-pool { display: flex; flex-wrap: wrap; gap: var(--jhn-space-2); }
.jhn-zones { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--jhn-space-4); }
.jhn-zone { border: 3px dashed var(--jhn-line); border-radius: var(--jhn-radius); padding: var(--jhn-space-3); min-height: 200px;
  display: flex; flex-direction: column; gap: var(--jhn-space-2); background: var(--jhn-surface); }
.jhn-zone-title { font-weight: 700; font-size: var(--jhn-step-1); }
.jhn-zone.is-target { border-style: solid; border-color: var(--jhn-focus); background: var(--jhn-info-bg); }
.jhn-tile { font: 700 var(--jhn-step-0)/1.2 var(--jhn-font-body); min-height: var(--jhn-target); padding: var(--jhn-space-2) var(--jhn-space-3);
  border: 2px solid var(--jhn-ink); border-radius: var(--jhn-radius-sm); background: var(--jhn-surface-2); color: var(--jhn-ink);
  display: inline-flex; align-items: center; justify-content: space-between; gap: var(--jhn-space-2); cursor: grab; }
.jhn-tile.is-right { background: var(--jhn-correct-bg); border-color: var(--jhn-correct); color: var(--jhn-correct-ink); }
.jhn-tile.is-right::after { content: "✓"; }
.jhn-tile.is-wrong { background: var(--jhn-incorrect-bg); border-color: var(--jhn-incorrect); color: var(--jhn-incorrect-ink); border-style: dashed; }
.jhn-tile.is-wrong::after { content: "✗"; }
.jhn-tile.is-held, .jhn-tile[aria-pressed="true"] { transform: rotate(-2deg); box-shadow: 6px 6px 0 0 var(--jhn-gold); outline: 3px solid var(--jhn-focus); outline-offset: 3px; }

/* ---------- forms, tables, dialogs, progress ---------- */

.jhn-field { display: grid; gap: var(--jhn-space-1); }
.jhn-field > label { font-weight: 700; font-size: var(--jhn-step--1); }
.jhn-input, .jhn-select { font: inherit; font-size: var(--jhn-step-0); min-height: var(--jhn-target); padding: 0 var(--jhn-space-3);
  border: 2px solid var(--jhn-line); border-radius: var(--jhn-radius-sm); background: var(--jhn-surface); color: var(--jhn-ink); }
.jhn-input:hover, .jhn-select:hover { border-color: var(--jhn-ink); }

/* Tables (reworked 2026-10-19 after the old-vs-new comparison: the pale head
   blended into the page and the 15px text broke the 18px body rule). Body-size
   text on a white surface, a crest-gold head like the old site's, zebra rows. */
.jhn-table { width: 100%; border-collapse: collapse; font-size: var(--jhn-step-0); background: var(--jhn-surface); border: 1px solid var(--jhn-line); }
.jhn-table th, .jhn-table td { text-align: left; vertical-align: top; padding: var(--jhn-space-2) var(--jhn-space-3); border-bottom: 1px solid var(--jhn-line); }
.jhn-table th { font-weight: 700; }
.jhn-table th:not([scope="row"]) { background: var(--jhn-gold); color: var(--jhn-on-gold); }
.jhn-table tr:nth-child(even) > :is(td, th[scope="row"]) { background: var(--jhn-ground); }
.jhn-table code { font-weight: 700; white-space: nowrap; }
.jhn-scroll { overflow-x: auto; }

.jhn-dialog { border: 2px solid var(--jhn-ink); border-radius: var(--jhn-radius); background: var(--jhn-surface); color: var(--jhn-ink);
  padding: var(--jhn-space-5); max-width: min(560px, calc(100% - 2 * var(--jhn-space-4))); }
.jhn-dialog::backdrop { background: rgba(11, 35, 65, 0.6); }

.jhn-progress { height: 14px; border: 2px solid var(--jhn-line); border-radius: var(--jhn-radius-sm); background: var(--jhn-surface-2); overflow: hidden; }
.jhn-progress > span { display: block; height: 100%; background: var(--jhn-gold); transition: width 0.3s ease; }
/* A progress bar with its words above it: JHN.progressBar(row, done, total, "sorted") fills both. */
.jhn-progress-row { display: grid; gap: var(--jhn-space-1); }
.jhn-progress-row > p { margin: 0; font-weight: 700; }

/* ---------- Start again footer: JHN.startAgain() draws it at the bottom of <main> ---------- */
.jhn-saved { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--jhn-space-2) var(--jhn-space-4);
  margin-top: var(--jhn-space-6); padding-top: var(--jhn-space-3); border-top: 1px solid var(--jhn-line); color: var(--jhn-muted); }
.jhn-saved > p { margin: 0; }

/* ---------- options: pick one (radio) or several (checkbox), drawn as buttons ----------
   <fieldset class="jhn-options"><legend>…</legend>
     <label class="jhn-option"><input type="radio" name="q1" value="dfs"> Depth-first</label> …
   Real inputs, so arrow keys, Space and screen readers work for free; the
   input stays visible, so a circle says "one" and a square says "several". */
.jhn-options { display: flex; flex-wrap: wrap; gap: var(--jhn-space-2); border: 0; padding: 0; margin: 0; min-width: 0; }
.jhn-options > legend { padding: 0; margin-bottom: var(--jhn-space-2); font-weight: 700; }
.jhn-options--stack { flex-direction: column; align-items: stretch; }
.jhn-option { display: inline-flex; align-items: center; gap: var(--jhn-space-2); min-height: var(--jhn-target);
  padding: 8px 14px; background: var(--jhn-surface-2); color: var(--jhn-ink); border: 2px solid var(--jhn-line);
  border-radius: var(--jhn-radius-sm); cursor: pointer; font-weight: 700; }
.jhn-option:hover { border-color: var(--jhn-ink); }
.jhn-option input { width: 20px; height: 20px; margin: 0; flex: none; accent-color: var(--jhn-ink); }
.jhn-option input:focus-visible { outline: none; }
.jhn-option:has(:focus-visible) { outline: 3px solid var(--jhn-focus); outline-offset: 3px; }
.jhn-option:has(:checked) { border-width: 4px; border-color: var(--jhn-ink); padding: 6px 12px; }
.jhn-option:has(:disabled) { cursor: default; }
/* Marked: icon + edge + colour, as on tiles and answers. */
.jhn-option.is-right { background: var(--jhn-correct-bg); color: var(--jhn-correct-ink); border-color: var(--jhn-correct); }
.jhn-option.is-right::after { content: "✓"; }
.jhn-option.is-wrong { background: var(--jhn-incorrect-bg); color: var(--jhn-incorrect-ink); border-color: var(--jhn-incorrect); border-style: dashed; }
.jhn-option.is-wrong::after { content: "✗"; }

/* ---------- result: the end of a game or round ----------
   <section class="jhn-panel jhn-result"> label, the score big, a line of
   detail, then the buttons. --cover lays it over the game (the game's box
   needs position: relative). Move focus to its first button when it shows. */
.jhn-result { display: grid; justify-items: center; gap: var(--jhn-space-3); text-align: center; }
.jhn-result[hidden] { display: none; }
.jhn-result > * { margin: 0; }
.jhn-result-label { font-weight: 700; color: var(--jhn-muted); }
.jhn-result-value { font-family: var(--jhn-font-display); font-weight: 600; font-size: calc(var(--jhn-step-4) * 1.6);
  line-height: 1; font-variant-numeric: tabular-nums; }
.jhn-result-detail { max-width: 46ch; }
.jhn-result-actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--jhn-space-2); }
.jhn-result--cover { position: absolute; inset: 0; z-index: 5; align-content: center; padding: var(--jhn-space-4);
  background: var(--jhn-surface); border-radius: inherit; }

/* ---------- projected (front-of-room) pages: <body class="jhn jhn-projected"> ---------- */

.jhn-projected { --jhn-step--1: 1.1rem; --jhn-step-0: 1.4rem; --jhn-step-1: 1.75rem; --jhn-step-2: 2.2rem; --jhn-step-3: 2.75rem; --jhn-step-4: 4.5rem; --jhn-max: 1600px; }

/* ---------- motion ---------- */

@keyframes jhn-in { from { transform: translateY(6px); opacity: 0.2; } to { transform: none; opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
}

/* ---------- phone ---------- */

@media (max-width: 640px) {
  /* compact header: back link and toggles on one row, crest and title below,
     so the page starts ~110px down instead of ~200px */
  .jhn-header-in { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "back back actions" "logo brand brand"; gap: var(--jhn-space-1) var(--jhn-space-2); padding-block: var(--jhn-space-2); }
  .jhn-back { grid-area: back; font-size: var(--jhn-step--1); padding-inline: 0; }
  .jhn-header-actions { grid-area: actions; flex-wrap: nowrap; gap: var(--jhn-space-1); }
  .jhn-header .jhn-btn--quiet { font-size: var(--jhn-step--1); padding: 0 var(--jhn-space-2); }
  .jhn-logo { grid-area: logo; width: 40px; height: 40px; }
  .jhn-logo img { width: 32px; height: 32px; }
  .jhn-brand { grid-area: brand; align-self: center; }
  .jhn-wordmark { font-size: var(--jhn-step-1); }
  .jhn-brand-sub { display: none; }
  .jhn-howto > summary::after { content: "More ▾"; }
  .jhn-howto[open] > summary::after { content: "Less ▴"; }
  .jhn-howto-body { padding-left: var(--jhn-space-4); }
  .jhn-instr { font-size: var(--jhn-step-2); }
  /* registers side by side, so a timed question's answers stay on the first screen */
  .jhn-regs { gap: var(--jhn-space-2); }
  .jhn-reg { width: auto; flex: 1 1 0; min-width: 52px; max-width: 120px; padding: var(--jhn-space-1) var(--jhn-space-2); }
  .jhn-reg--acc { flex: none; width: 170px; max-width: none; margin-inline: calc(50% - 85px); padding: var(--jhn-space-2) var(--jhn-space-3); }
  .jhn-reg--acc .jhn-reg-value { font-size: var(--jhn-step-3); }
  .jhn-reg-value { font-size: var(--jhn-step-1); }
  .jhn-reg:has(.jhn-reg-short) .jhn-reg-long { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
  .jhn-reg-short { display: inline; }
  /* short answers (numbers) stay in one row, so a timed question fits one screen */
  .jhn-answers--short { grid-template-columns: repeat(auto-fit, minmax(70px, 1fr)); gap: var(--jhn-space-2); }
  .jhn-answer { font-size: var(--jhn-step-2); min-height: 60px; }
}
