/* Brew Retro — "the cartridge shelf".
   Neutral putty/charcoal plastic, one accent that follows the handheld's shell colour,
   games as cartridges with their cover as label art. System fonts only.

   1. Tokens and themes       5. Library (index.html)
   2. Base and typography     6. Game page (game.html)
   3. Page frame              7. About (about.html)
   4. Shared components       8. Upload (upload.html)
                              9. Utilities
                             10. Reduced motion
   404.html carries its own cut-down copy of the tokens: keep the two in step. */


/* ========== 1. Tokens and themes ========== */

:root {
  color-scheme: light dark;

  --body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --display: "Avenir Next Condensed", "DIN Condensed", "Bahnschrift Condensed", "Bahnschrift", "Roboto Condensed", "Arial Narrow", "Helvetica Neue", Arial, sans-serif;
  --mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;

  --bg: #ebe9e3;
  --surface: #f8f7f3;
  --sunk: #dfdcd5;
  --ink: #17171c;
  --muted: #56565f;
  --line: #cdcac2;
  --line-strong: #a9a59b;

  /* cartridge plastic and label paper */
  --cart: #d3d0c8;
  --cart-ridge: #b8b4aa;
  --cart-edge: #a29e93;
  --pin: #aca799;
  --label: #fbfaf6;
  --label-ink: #17171c;
  --label-muted: #55555e;
  --lcd: #1d211f;
  --lcd-ink: #c9e3c3;
  --screen: #0d0d10; /* behind cover art, in both schemes */

  --warn-bg: #fbeed2;
  --warn-line: #c99a3a;
  --warn-ink: #5a3c00;

  --radius: 12px;
  --gutter: 16px;
  --max: 1180px;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #121215;
    --surface: #1c1c21;
    --sunk: #0c0c0e;
    --ink: #ededf0;
    --muted: #a3a3ad;
    --line: #303038;
    --line-strong: #4a4a55;
    --cart: #2c2c33;
    --cart-ridge: #3d3d47;
    --cart-edge: #050506;
    --pin: #4b4b56;
    --label: #dcd9d0;
    --label-ink: #17171c;
    --label-muted: #4a4a52;
    --lcd: #0b0d0c;
    --lcd-ink: #b7d8b0;
    --warn-bg: #2d2412;
    --warn-line: #8a6a22;
    --warn-ink: #f4dca3;
  }
}

/* The accent follows the shell colour (data-shell on <html>, ids from assets/js/contract.js).
   --accent fills keep --on-accent text at >= 4.5:1; --accent-ink is >= 4.6:1 on --bg and
   --surface in its scheme; --accent-soft is a pale (light) or deep (dark) tint for pressed states. */
:root, :root[data-shell="wave"] { --accent: #2172d5; --accent-edge: #164c8e; --on-accent: #ffffff; --accent-ink: #1b66bd; --accent-soft: #d6e2ee; }
:root[data-shell="inferno"] { --accent: #d73a20; --accent-edge: #902715; --on-accent: #ffffff; --accent-ink: #bf341a; --accent-soft: #f3d9d1; }
:root[data-shell="leaf"] { --accent: #368248; --accent-edge: #1e4828; --on-accent: #ffffff; --accent-ink: #307240; --accent-soft: #d9e4d8; }
:root[data-shell="bubblegum"] { --accent: #e30f6c; --accent-edge: #960a48; --on-accent: #ffffff; --accent-ink: #ca0f62; --accent-soft: #f5d2dd; }
:root[data-shell="volt"] { --accent: #f2c230; --accent-edge: #a37c08; --on-accent: #141418; --accent-ink: #7f600d; --accent-soft: #f7efd4; }
:root[data-shell="midnight"] { --accent: #2b2b33; --accent-edge: #060607; --on-accent: #ffffff; --accent-ink: #2b2b33; --accent-soft: #d7d6d4; }
@media (prefers-color-scheme: dark) {
  :root, :root[data-shell="wave"] { --accent: #2172d5; --accent-edge: #13437d; --on-accent: #ffffff; --accent-ink: #3b88e3; --accent-soft: #1d2f49; }
  :root[data-shell="inferno"] { --accent: #d73a20; --accent-edge: #7e2213; --on-accent: #ffffff; --accent-ink: #e5593f; --accent-soft: #452321; }
  :root[data-shell="leaf"] { --accent: #368248; --accent-edge: #183a20; --on-accent: #ffffff; --accent-ink: #3fa65a; --accent-soft: #22322a; }
  :root[data-shell="bubblegum"] { --accent: #e30f6c; --accent-edge: #83093e; --on-accent: #ffffff; --accent-ink: #f06ba8; --accent-soft: #481932; }
  :root[data-shell="volt"] { --accent: #f2c230; --accent-edge: #b1880b; --on-accent: #141418; --accent-ink: #f2c230; --accent-soft: #4b4124; }
  :root[data-shell="midnight"] { --accent: #5f5f81; --accent-edge: #343446; --on-accent: #ffffff; --accent-ink: #8383a3; --accent-soft: #2b2b36; }
}

@media (min-width: 720px) { :root { --gutter: 32px; } }


/* ========== 2. Base and typography ========== */

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; }

body {
  margin: 0;
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  background: var(--bg);
  color: var(--ink);
  font: 16px/1.55 var(--body);
  overflow-wrap: break-word;
}
/* The footer starts below the fold while content streams in: no layout shift. */
main { flex: 1; min-height: 100vh; min-height: 100svh; }

img { max-width: 100%; }
a { color: var(--accent-ink); text-underline-offset: 0.18em; text-decoration-thickness: 1px; }
a:hover { text-decoration-thickness: 2px; }

:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 2px; border-radius: 4px; }

h1, h2 { line-height: 1.1; margin: 0 0 0.5em; }
/* The display voice: condensed heavy caps. */
h1, .state h2, .prose h2, .step-title, .slot-text, .ticket-title, .cart-title {
  font-family: var(--display);
  font-stretch: condensed;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.005em;
  line-height: 0.95;
}
h1 { font-size: clamp(2.4rem, 1.6rem + 3.4vw, 4.4rem); }
h2 { font-size: 1.35rem; }
p { margin: 0 0 1em; }

/* The label voice: small monospace caps for metadata and section labels. */
.label, .site-nav a, .crumbs, .results-bar, .sort label, .panel > h2, .side-h {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}

.lede { font-size: 1.15rem; color: var(--muted); }

code, kbd { font-family: var(--mono); font-size: 0.88em; }
kbd {
  display: inline-block;
  min-width: 1.9em;
  padding: 0.1em 0.45em;
  border: 1px solid var(--line-strong);
  border-bottom-width: 3px;
  border-radius: 5px;
  background: var(--surface);
  color: var(--ink);
  text-align: center;
  font-size: 0.8em;
  line-height: 1.4;
}


/* ========== 3. Page frame: header, footer, shell picker ========== */

.wrap { width: 100%; max-width: var(--max); margin: 0 auto; padding: 0 var(--gutter); }

.skip-link {
  position: absolute;
  left: 8px; top: -100px;
  z-index: 10;
  padding: 10px 16px;
  background: var(--ink);
  color: var(--bg);
  border-radius: 8px;
  font-weight: 650;
}
.skip-link:focus { top: 8px; }

.site-header { border-bottom: 2px solid var(--ink); }
.site-header .wrap {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  min-height: 64px;
}
.brand { display: inline-flex; align-items: center; color: var(--ink); padding: 6px 0; }
.wordmark { display: block; width: auto; height: 24px; }
.wm-ink { fill: currentColor; }
.wm-plate { fill: var(--accent); }
.wm-hub { fill: var(--on-accent); }

.site-nav ul { display: flex; gap: 2px; list-style: none; margin: 0; padding: 0; }
.site-nav a {
  position: relative;
  display: block;
  padding: 12px 10px;
  color: var(--muted);
  text-decoration: none;
}
.site-nav a:hover { color: var(--ink); }
.site-nav a[aria-current="page"] { color: var(--ink); }
/* the current page gets a little power LED */
.site-nav a[aria-current="page"]::before {
  content: "";
  position: absolute;
  left: 50%; bottom: 4px;
  width: 6px; height: 6px;
  margin-left: -3px;
  border-radius: 50%;
  background: var(--accent);
  box-shadow: 0 0 0 2px var(--bg), 0 0 6px var(--accent);
}
@media (max-width: 420px) {
  .wordmark { height: 16px; }
  .site-nav a { padding: 12px 6px; letter-spacing: 0.06em; }
}

.site-footer { margin-top: 72px; border-top: 2px solid var(--ink); color: var(--muted); font-size: 0.875rem; }
.site-footer .wrap {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: flex-start;
  gap: 20px 40px;
  padding-top: 24px;
  padding-bottom: 40px;
}
.site-footer p { margin: 0 0 0.5em; max-width: 60ch; }
.site-footer a { color: var(--ink); }

/* Shell colour picker: six swatches like the six handheld colours (--swatch is set by shell.js). */
.shell-picker { border: 0; margin: 0; padding: 0; min-width: 0; }
.shell-picker legend { padding: 0; margin-bottom: 8px; color: var(--muted); }
.shell-picker .swatches { display: flex; gap: 8px; }
.swatch { position: relative; display: block; }
.swatch input { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.swatch span {
  display: block;
  width: 28px; height: 28px;
  border-radius: 8px 8px 12px 8px;
  background: var(--swatch);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 18%), 0 3px 0 var(--line-strong);
  transition: transform 80ms ease, box-shadow 80ms ease;
}
.swatch input:checked + span { transform: translateY(2px); box-shadow: inset 0 0 0 1px rgb(0 0 0 / 18%), 0 1px 0 var(--line-strong), 0 0 0 3px var(--bg), 0 0 0 5px var(--ink); }
.swatch input:focus-visible + span { outline: 3px solid var(--accent-ink); outline-offset: 5px; }


/* ========== 4. Shared components ========== */

/* ----- Buttons: hardware keys that press down ----- */

.btn {
  --btn-bg: var(--surface);
  --btn-fg: var(--ink);
  --btn-edge: var(--line-strong);
  --btn-depth: 3px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-height: 44px;
  padding: 10px 18px;
  border: 1px solid var(--btn-edge);
  border-radius: 10px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font: inherit;
  font-weight: 650;
  line-height: 1.2;
  text-decoration: none;
  text-align: center;
  cursor: pointer;
  box-shadow: 0 var(--btn-depth) 0 var(--btn-edge);
  margin-bottom: var(--btn-depth);
  transition: transform 70ms ease, box-shadow 70ms ease, background-color 120ms ease;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  touch-action: manipulation;
}
.btn:hover { background: var(--sunk); }
.btn:active { transform: translateY(calc(var(--btn-depth) - 1px)); box-shadow: 0 1px 0 var(--btn-edge); }
.btn svg { width: 18px; height: 18px; flex: none; }
.btn-primary { --btn-bg: var(--accent); --btn-fg: var(--on-accent); --btn-edge: var(--accent-edge); --btn-depth: 4px; }
.btn-primary:hover { background: var(--accent); filter: brightness(1.07); }
.btn-big { min-height: 56px; padding: 14px 22px; font-size: 1.05rem; width: 100%; }
.btn-small { min-height: 34px; padding: 5px 12px; font-size: 0.85rem; border-radius: 8px; --btn-depth: 2px; }
.btn-row { display: flex; flex-wrap: wrap; gap: 10px; }
.btn-row .btn { flex: 1 1 auto; }
.actions { display: flex; flex-wrap: wrap; gap: 10px; }
/* sending: the key stays down and stripes run across it */
.btn.is-sending {
  cursor: progress;
  transform: translateY(3px);
  box-shadow: 0 1px 0 var(--btn-edge);
  background-image: repeating-linear-gradient(-45deg, rgb(255 255 255 / 16%) 0 10px, transparent 10px 20px);
  background-size: 28.28px 28.28px;
}

/* ----- Form fields (upload form, report form): label, hint, input, counter, error ----- */

.field { margin: 0 0 24px; padding: 0; border: 0; min-width: 0; }
.field > label, .field > legend { display: block; padding: 0; font-weight: 700; margin-bottom: 2px; }
.field .hint { margin: 0 0 8px; color: var(--muted); font-size: 0.9rem; }
.optional { color: var(--muted); font-weight: 450; }
.field input[type="text"], .field input[type="url"], .field input[type="email"], .field textarea {
  display: block;
  width: 100%;
  min-height: 46px;
  padding: 10px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--surface);
  box-shadow: inset 0 2px 0 rgb(0 0 0 / 5%);
  color: var(--ink);
  font: inherit;
}
.field input:hover, .field textarea:hover { border-color: var(--ink); }
.field textarea { resize: vertical; line-height: 1.5; }
.field input::placeholder { color: var(--muted); opacity: 1; }
.field input:focus-visible, .field textarea:focus-visible { outline-offset: 0; border-radius: 8px; border-color: var(--ink); }
.field [aria-invalid="true"] { border-color: var(--warn-line); box-shadow: 0 0 0 1px var(--warn-line); }
.counter { margin: 4px 0 0; text-align: right; color: var(--muted); font-family: var(--mono); font-size: 0.75rem; }
.counter:empty { display: none; }
.counter.is-near { color: var(--accent-ink); font-weight: 700; }
.field-error { margin: 4px 0 0; color: var(--warn-ink); font-size: 0.9rem; font-weight: 600; }
.field-error:empty { display: none; }
.field.has-error .field-error { padding: 6px 10px; border-radius: 6px; background: var(--warn-bg); }

/* The error box above a form's send button. */
.submit-error {
  margin: 0 0 16px;
  padding: 12px 14px;
  border: 1px solid var(--warn-line);
  border-radius: 8px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-weight: 550;
}
.submit-error p { margin: 0; }
.submit-error p + p { margin-top: 6px; }
.submit-error a { color: inherit; }
.submit-error:focus { outline: none; }
.submit-error:focus-visible { outline: 3px solid var(--accent-ink); }

/* The honeypot: off-screen for people, still in the form for bots. */
.hp { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }

/* ----- Chips: tag toggles (library filter, upload form) ----- */

.chips { display: flex; gap: 8px; list-style: none; margin: 0; padding: 0; }
/* One scrolling row in the library, so its height never changes. */
.chips-scroll {
  flex-wrap: nowrap;
  min-height: 46px;
  overflow-x: auto;
  padding: 2px 4px 6px;
  margin: 0 -4px;
  scrollbar-width: thin;
}
.chips-wrap { flex-wrap: wrap; }
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 36px;
  padding: 6px 13px;
  border: 1px solid var(--line-strong);
  border-radius: 8px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  box-shadow: 0 2px 0 var(--line-strong);
  transition: transform 70ms ease, box-shadow 70ms ease;
}
.chip:hover { background: var(--sunk); }
.chip .count { font-family: var(--mono); color: var(--muted); font-size: 0.78em; }
.chip[aria-pressed="true"] {
  background: var(--accent-soft);
  border-color: var(--accent-ink);
  color: var(--ink);
  transform: translateY(2px);
  box-shadow: 0 0 0 var(--line-strong), inset 0 0 0 1px var(--accent-ink);
}
.chip[aria-pressed="true"] .count { color: var(--ink); }
.chip[aria-disabled="true"] { opacity: 0.45; cursor: not-allowed; }
.chip[aria-disabled="true"]:hover { background: var(--surface); }

/* ----- The cartridge: a game card, cover as label art ----- */

.cart {
  display: block;
  color: var(--label-ink);
  text-decoration: none;
  filter: drop-shadow(0 4px 0 var(--cart-edge));
  transition: transform 110ms ease, filter 110ms ease;
  -webkit-tap-highlight-color: transparent;
}
.cart:focus-visible { outline-offset: 5px; border-radius: 10px; }
.cart-shell {
  display: block;
  padding: 20px 9px 16px;
  border-radius: 6px 0 14px 14px;
  /* the cut corner, top right */
  clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
  /* grip ridges at the top, contact pins at the bottom (--pins lights up on hover) */
  background:
    repeating-linear-gradient(to bottom, var(--cart-ridge) 0 2px, transparent 2px 5px) 50% 4px / 44% 12px no-repeat,
    repeating-linear-gradient(to right, var(--pins, var(--pin)) 0 3px, transparent 3px 6px) 50% calc(100% - 4px) / 60% 5px no-repeat,
    var(--cart);
}
.cart-label {
  display: block;
  padding: 6px 6px 8px;
  border-radius: 4px;
  background: var(--label);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 7%);
}
.cart-art {
  position: relative;
  display: block;
  aspect-ratio: 10 / 9;
  border-radius: 2px;
  background: var(--screen);
  overflow: hidden;
}
.cover {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
  image-rendering: pixelated;
  background: var(--screen);
}
.cart-title {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-height: 2em;
  margin: 8px 0 3px;
  font-size: 1.12rem;
  line-height: 1;
}
.cart-foot { display: flex; align-items: center; gap: 6px; min-height: 1.1rem; }
.cart-by {
  display: block;
  flex: 1;
  min-width: 0;
  margin: 0;
  overflow: hidden;
  white-space: nowrap;
  text-overflow: ellipsis;
  color: var(--label-muted);
  font-family: var(--mono);
  font-size: 0.7rem;
}
.cart-flag {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  flex: none;
  padding: 1px 5px 1px 3px;
  border-radius: 3px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--mono);
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.cart-flag svg { width: 11px; height: 11px; }

/* What's printed under the slot: tags and the counters. Always one line tall. */
.cart-meta {
  display: flex;
  justify-content: space-between;
  gap: 8px;
  min-height: 1.5em;
  margin-top: 10px;
  padding: 0 2px;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.04em;
  line-height: 1.5;
}
.cart-tags { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; text-transform: uppercase; }
.stats { display: inline-flex; gap: 10px; flex: none; color: var(--ink); }
.stat { display: inline-flex; align-items: center; gap: 3px; font-variant-numeric: tabular-nums; }
.stat svg { width: 10px; height: 10px; fill: currentColor; color: var(--muted); }

@media (hover: hover) {
  .cart:hover { --pins: var(--accent); transform: translateY(-5px); filter: drop-shadow(0 9px 0 var(--cart-edge)); }
}
.cart:active { transform: translateY(2px); filter: drop-shadow(0 1px 0 var(--cart-edge)); }

/* Loading: blank cartridges in exactly the real geometry. */
.cart.is-blank { pointer-events: none; }
.is-blank .cart-art { background: var(--cart-ridge); }
.is-blank .cart-title, .is-blank .cart-by { color: transparent; }
.is-blank .cart-title::before, .is-blank .cart-by::before {
  content: "";
  display: block;
  width: 78%;
  height: 0.8em;
  border-radius: 2px;
  background: var(--sunk);
}
.is-blank .cart-by::before { width: 50%; height: 0.7em; margin-top: 0.2em; }
@media (prefers-reduced-motion: no-preference) {
  .is-blank .cart-shell { animation: blink 1.4s steps(2, jump-none) infinite; }
}
@keyframes blink { from { opacity: 1; } to { opacity: 0.6; } }

/* ----- States: a small LCD readout and plain words (empty, no match, errors, success) ----- */

.state { margin: 28px 0; padding: 36px 20px 40px; text-align: center; }
.state .state-lcd {
  display: inline-block;
  margin: 0 auto 18px;
  max-width: none;
  padding: 10px 16px;
  border: 6px solid var(--cart);
  border-radius: 8px 8px 16px 8px;
  background: var(--lcd);
  color: var(--lcd-ink);
  font-family: var(--mono);
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.state h1, .state h2 { font-size: 1.9rem; line-height: 1; margin-bottom: 0.4em; }
.state p { color: var(--muted); max-width: 46ch; margin: 0 auto 1.2em; }
.state .actions { justify-content: center; }

/* ----- Section labels, warnings, the controls table, numbered steps ----- */

.side-h { margin: 0 0 12px; color: var(--muted); }

.warning {
  display: flex;
  gap: 10px;
  margin: 12px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--warn-line);
  border-radius: 8px;
  background: var(--warn-bg);
  color: var(--warn-ink);
  font-size: 0.9rem;
}
.warning svg { flex: none; width: 18px; height: 18px; margin-top: 2px; }

.keys { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.keys th, .keys td { text-align: left; padding: 8px 0; border-bottom: 1px solid var(--line); vertical-align: middle; }
.keys th { font-weight: 550; color: var(--muted); }
.keys thead th { font-family: var(--mono); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.1em; }

.steps { padding-left: 0; list-style: none; counter-reset: step; }
.steps > li { position: relative; counter-increment: step; padding: 2px 0 18px 50px; }
.steps > li::before {
  display: grid;
  place-items: center;
  width: 34px; height: 34px;
  border-radius: 8px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--mono);
  font-weight: 700;
  font-size: 0.95rem;
  box-shadow: 0 3px 0 var(--accent-edge);
}
.steps > li::before { content: counter(step); position: absolute; left: 0; top: 0; }


/* ========== 5. Library (index.html) ========== */

.intro { padding: 40px 0 4px; }
.intro h1 { max-width: 15ch; margin-bottom: 0.3em; }
.intro p { color: var(--muted); font-size: 1.1rem; max-width: 46ch; margin: 0; }
@media (min-width: 900px) {
  .intro { display: grid; grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr); gap: 40px; align-items: end; }
  .intro h1 { margin: 0; max-width: none; }
  .intro p { padding-bottom: 0.4em; }
}

.controls { display: grid; grid-template-columns: minmax(0, 1fr); gap: 14px; padding: 28px 0 6px; }
.search-row { display: flex; flex-wrap: wrap; gap: 10px; align-items: stretch; }
.search { position: relative; flex: 1 1 260px; }
.search svg {
  position: absolute;
  left: 14px; top: 50%;
  width: 18px; height: 18px;
  transform: translateY(-50%);
  color: var(--muted);
  pointer-events: none;
}
.search input, .sort select {
  width: 100%;
  min-height: 46px;
  padding: 10px 14px 10px 42px;
  border: 2px solid var(--ink);
  border-radius: 10px;
  background: var(--surface);
  color: var(--ink);
  font: inherit;
}
.search input::placeholder { color: var(--muted); opacity: 1; }
.search input:focus-visible, .sort select:focus-visible { outline-offset: 1px; }

.sort { display: flex; align-items: center; gap: 10px; flex: 0 1 auto; }
.sort label { color: var(--muted); white-space: nowrap; }
.sort select {
  width: auto;
  padding: 10px 40px 10px 14px;
  appearance: none;
  -webkit-appearance: none;
  font-weight: 600;
  cursor: pointer;
  /* the drop-down arrow */
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 20px) 50%, calc(100% - 14px) 50%;
  background-size: 6px 6px;
  background-repeat: no-repeat;
}

.results-bar {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
  min-height: 44px;
  color: var(--muted);
}
.results-bar p { margin: 0; }
.results-bar .bar-actions { display: flex; gap: 8px; }

.grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(148px, 1fr));
  gap: 26px 14px;
  list-style: none;
  margin: 10px 0 0;
  padding: 0;
}
@media (min-width: 560px) {
  .grid { grid-template-columns: repeat(auto-fill, minmax(184px, 1fr)); gap: 36px 24px; }
}
/* Long lists skip work for off-screen cartridges. The padding keeps the hover lift,
   the edge and the focus ring inside the containment box. */
.grid > li {
  content-visibility: auto;
  contain-intrinsic-size: auto 380px;
  padding: 10px;
  margin: -10px;
}


/* ========== 6. Game page (game.html) ========== */

.crumbs { margin: 0; padding: 20px 0 0; }
.crumbs a { color: var(--muted); text-decoration: none; }
.crumbs a:hover { color: var(--ink); text-decoration: underline; }

/* Two columns on wide screens: the 5:8 handheld, sized to fit a laptop screen, then the rest. */
.game {
  --device-h: min(82vh, 760px);
  --device-w: calc(var(--device-h) * 5 / 8);
  display: grid;
  gap: 32px;
  padding-top: 18px;
}
@media (min-width: 900px) {
  .game { grid-template-columns: minmax(300px, var(--device-w)) minmax(0, 1fr); gap: 48px; align-items: start; }
  .device-col { position: sticky; top: 16px; }
}
.device {
  width: min(100%, var(--device-w));
  margin: 0 auto;
  aspect-ratio: 5 / 8;
  border-radius: 18px;
}
.device iframe { display: block; width: 100%; height: 100%; border: 0; border-radius: inherit; }
.device-note { margin: 12px auto 0; text-align: center; color: var(--muted); font-size: 0.8rem; max-width: 40ch; }
@media (pointer: coarse) { .device-note { display: none; } }

.side-col { min-width: 0; }
/* Skeleton text bars in the side column until the catalog arrives. */
.bar { display: block; height: 1em; margin: 0 0 12px; border-radius: 3px; background: var(--sunk); }
.bar-h1 { height: 3.2rem; width: 70%; }
.bar-short { width: 40%; }

.game-head h1 { margin-bottom: 0.2em; }
.byline { margin: 0 0 14px; color: var(--muted); font-family: var(--mono); font-size: 0.85rem; }
.byline a { color: var(--ink); font-weight: 600; }
.desc { font-size: 1.08rem; max-width: 60ch; }

.tag-list { display: flex; flex-wrap: wrap; gap: 6px; list-style: none; margin: 0 0 22px; padding: 0; }
.tag {
  display: inline-block;
  padding: 3px 8px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  text-decoration: none;
}
a.tag:hover { background: var(--sunk); }

.badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  margin: 0 0 14px;
  padding: 3px 9px 3px 6px;
  border-radius: 6px;
  background: var(--accent);
  color: var(--on-accent);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.badge svg { width: 14px; height: 14px; }

/* Plays and the Like button: always the same height, numbers or not. */
.game-stats { display: flex; flex-wrap: wrap; align-items: center; gap: 10px 18px; min-height: 44px; margin: 0 0 16px; }
.plays { display: inline-flex; align-items: center; gap: 6px; font-family: var(--mono); font-size: 0.85rem; color: var(--muted); }
.plays strong { color: var(--ink); font-weight: 700; }
.plays svg { width: 12px; height: 12px; fill: currentColor; }
.like { gap: 8px; min-height: 40px; padding: 8px 14px; }
.like svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; }
.like .like-count { font-family: var(--mono); font-size: 0.85rem; font-weight: 700; }
.like[aria-pressed="true"] {
  --btn-bg: var(--accent-soft);
  --btn-edge: var(--accent-ink);
  transform: translateY(2px);
  box-shadow: 0 1px 0 var(--accent-ink);
}
.like[aria-pressed="true"] svg { fill: var(--accent-ink); stroke: var(--accent-ink); }
.like[aria-pressed="true"]:active { transform: translateY(3px); box-shadow: 0 0 0 var(--accent-ink); }

.action-stack { display: grid; gap: 14px; }
.size-note { margin: -4px 0 0; text-align: center; color: var(--muted); font-family: var(--mono); font-size: 0.75rem; }

.box {
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  background: var(--surface);
  padding: 16px;
}
.install-box ul { margin: 14px 0 0; padding-left: 1.2em; color: var(--muted); font-size: 0.9rem; }
.install-box li { margin-bottom: 4px; }
.install-box .more { margin: 12px 0 0; font-size: 0.875rem; }

.secondary-actions { display: grid; gap: 10px; margin-top: 4px; }
.secondary-actions .side-h { margin: 8px 0 0; }

.status { min-height: 1.5em; margin: 0; font-size: 0.9rem; font-weight: 600; color: var(--accent-ink); }

/* The copied prompt or link, readable and selectable. */
.reveal { border: 1px solid var(--line-strong); border-radius: var(--radius); background: var(--surface); overflow: hidden; }
.reveal-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  padding: 10px 12px 8px 16px;
  border-bottom: 1px solid var(--line);
}
.reveal-head h2 { margin: 0; font-size: 0.95rem; }
.reveal textarea {
  display: block;
  width: 100%;
  min-height: 8em;
  margin: 0;
  padding: 14px 16px;
  border: 0;
  resize: vertical;
  background: transparent;
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.8rem;
  line-height: 1.55;
  white-space: pre-wrap;
}
.reveal textarea:focus-visible { outline-offset: -3px; }

.panel { margin-top: 40px; padding-top: 16px; border-top: 2px solid var(--ink); }
.panel > h2 { margin-bottom: 16px; }
.facts { display: grid; grid-template-columns: max-content minmax(0, 1fr); gap: 10px 20px; margin: 0; }
.facts dt { color: var(--muted); font-family: var(--mono); font-size: 0.78rem; letter-spacing: 0.04em; padding-top: 0.2em; }
.facts dd { margin: 0; }
.hash { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.hash code { word-break: break-all; font-size: 0.78rem; padding: 4px 6px; border-radius: 6px; background: var(--sunk); }
@media (max-width: 480px) {
  .facts { grid-template-columns: 1fr; gap: 2px; }
  .facts dd { margin-bottom: 10px; }
}
.small-note { margin-top: 12px; color: var(--muted); font-size: 0.9rem; }

/* ----- Report: a short form in a modal dialog (report.js), or a panel under the button ----- */

.report-line { margin: 16px 0 0; }
.report-open { color: var(--muted); }
.report-open:hover { color: var(--ink); }

.report {
  width: min(560px, calc(100% - 2 * var(--gutter)));
  max-height: calc(100% - 32px);
  margin: auto;
  padding: 0;
  border: 2px solid var(--ink);
  border-radius: var(--radius);
  background: var(--surface);
  color: var(--ink);
  box-shadow: 0 6px 0 var(--line-strong), 0 24px 60px rgb(0 0 0 / 30%);
  overflow: auto;
  overscroll-behavior: contain;
}
.report::backdrop { background: rgb(12 12 14 / 62%); }
.report[open] { animation: report-in 160ms ease-out; }
@keyframes report-in { from { opacity: 0; transform: translateY(12px); } }
/* No <dialog>: the same form, as a panel in the page under the button. */
.report-inline { width: auto; max-height: none; margin: 16px 0 0; box-shadow: 0 4px 0 var(--line-strong); }

.report-inner { padding: 18px 20px 20px; }
@media (max-width: 420px) { .report-inner { padding: 14px 14px 16px; } }

.report-head { display: flex; justify-content: space-between; align-items: flex-start; gap: 12px; }
.report-kicker { margin: 4px 0 6px; color: var(--muted); overflow-wrap: anywhere; }
.report-title {
  margin: 0;
  font-family: var(--display);
  font-stretch: condensed;
  font-weight: 800;
  font-size: 2rem;
  line-height: 0.95;
  text-transform: uppercase;
}
.report-title:focus { outline: none; }
.report-title:focus-visible { outline: 3px solid var(--accent-ink); }
.report-close {
  display: grid;
  place-items: center;
  flex: none;
  width: 44px; height: 44px;
  margin: -6px -8px 0 0;
  border: 0;
  border-radius: 10px;
  background: none;
  color: var(--muted);
  cursor: pointer;
}
.report-close:hover { background: var(--sunk); color: var(--ink); }
.report-close svg { width: 22px; height: 22px; }
.report-intro { margin: 8px 0 16px; color: var(--muted); font-size: 0.9rem; }

/* The four reasons: large keys with an LED that lights on the chosen one. */
.report-reasons { margin-bottom: 18px; }
.report-reason-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 10px; }
.report-reason {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 12px;
  align-items: start;
  min-height: 56px;
  padding: 12px 14px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--surface);
  box-shadow: 0 3px 0 var(--line-strong);
  margin-bottom: 3px;
  cursor: pointer;
  transition: transform 70ms ease, box-shadow 70ms ease, background-color 120ms ease;
  -webkit-tap-highlight-color: transparent;
}
.report-reason:hover { background: var(--sunk); }
.report-reason input {
  appearance: none;
  width: 14px; height: 14px;
  margin: 4px 0 0;
  border-radius: 50%;
  background: var(--sunk);
  box-shadow: inset 0 0 0 1px var(--line-strong);
  cursor: pointer;
}
.report-reason input:checked { background: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-edge), 0 0 8px var(--accent); }
.report-reason input:focus-visible { outline: 3px solid var(--accent-ink); outline-offset: 3px; border-radius: 50%; }
.report-reason:has(input:checked) {
  background: var(--accent-soft);
  border-color: var(--accent-ink);
  transform: translateY(2px);
  box-shadow: 0 1px 0 var(--accent-ink);
}
.report-reason-text { display: grid; gap: 2px; }
.report-reason-text strong { font-weight: 700; line-height: 1.3; }
.report-reason-text span { color: var(--muted); font-size: 0.85rem; line-height: 1.4; }
.report-reasons.has-error .report-reason:not(:has(input:checked)) { border-color: var(--warn-line); }

.report-form .field { margin-bottom: 18px; }
.report-nav { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 10px; margin-top: 4px; }
.report-nav .btn { flex: 0 1 auto; min-width: 120px; }
@media (max-width: 420px) { .report-nav .btn { flex: 1 1 auto; } }

/* Sent: an LCD readout and the report number, then Close. */
.report-done { padding: 6px 0 0; }
.report-lcd {
  display: inline-block;
  margin: 0 0 14px;
  padding: 8px 14px;
  border: 5px solid var(--cart);
  border-radius: 8px 8px 14px 8px;
  background: var(--lcd);
  color: var(--lcd-ink);
  font-family: var(--mono);
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
}
.report-done .report-title { margin-bottom: 10px; }
.report-done > p { color: var(--muted); }
.report-id { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
.report-id .label { color: var(--muted); }
.report-id code { padding: 4px 8px; border-radius: 6px; background: var(--sunk); color: var(--ink); font-size: 0.9rem; word-break: break-all; }


/* ========== 7. About (about.html) ========== */

.prose { max-width: 68ch; padding-top: 44px; }
.prose h1 { margin-bottom: 0.35em; }
.prose h2 { margin-top: 2.2em; font-size: 1.6rem; line-height: 1; }
.prose ul { padding-left: 1.2em; }
.prose li { margin-bottom: 0.4em; }
.prose .keys { max-width: 420px; }


/* ========== 8. Upload (upload.html) ========== */

/* "Make a cartridge": one cart on the bench (.dock) and four steps that each do something to it.
   The steps sit under a row of LEDs; on wide screens the cart rides alongside them. */

.upload-head { padding-top: 40px; }
.upload-head h1 { margin-bottom: 0.3em; }
.upload-intro .lede { max-width: 50ch; margin-bottom: 4px; }
@media (max-width: 559px) { .upload-intro .lede { font-size: 1rem; } }
@media (min-width: 900px) {
  .upload-head { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); gap: 40px; align-items: end; }
  .upload-head h1 { margin: 0; }
}

/* Disclosures (the fine print, "More details"): a summary with a small +/- key. */
.fine-print summary, .more-details summary {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  cursor: pointer;
  list-style: none;
}
.fine-print summary::-webkit-details-marker, .more-details summary::-webkit-details-marker { display: none; }
.fine-print summary::before, .more-details summary::before {
  content: "+";
  display: grid;
  place-items: center;
  flex: none;
  width: 24px; height: 24px;
  border: 1px solid var(--line-strong);
  border-radius: 6px;
  background: var(--surface);
  box-shadow: 0 2px 0 var(--line-strong);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 0.9rem;
  font-weight: 700;
  line-height: 1;
}
:is(.fine-print, .more-details)[open] summary::before { content: "–"; transform: translateY(2px); box-shadow: 0 0 0 var(--line-strong); }
.fine-print summary {
  width: max-content;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.fine-print summary:hover { color: var(--ink); }
.fine-print ul { margin: 2px 0 0; padding-left: 1.2em; color: var(--muted); font-size: 0.9rem; max-width: 60ch; }
.fine-print li { margin-bottom: 4px; }

/* ----- The LEDs: one per step, lit when done, glowing on the current one ----- */

.leds { margin-top: 28px; border-top: 2px solid var(--ink); border-bottom: 1px solid var(--line); }
.leds ol { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); margin: 0; padding: 0; list-style: none; }
.led-step {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  min-height: 52px;
  padding: 10px 4px;
  border: 0;
  background: none;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
}
.led-step:hover { color: var(--ink); }
.led-step:focus-visible { outline-offset: -3px; }
.led {
  flex: none;
  width: 10px; height: 10px;
  border-radius: 50%;
  background: var(--sunk);
  box-shadow: inset 0 1px 2px rgb(0 0 0 / 35%), 0 0 0 1px var(--line-strong);
}
.led-num { color: var(--muted); font-weight: 500; }
.led-step.is-done .led { background: var(--accent); box-shadow: inset 0 -1px 0 rgb(0 0 0 / 25%), 0 0 0 1px var(--accent-edge); }
.led-step[aria-current="step"] { color: var(--ink); }
.led-step[aria-current="step"] .led { background: var(--accent); box-shadow: 0 0 0 1px var(--accent-edge), 0 0 0 4px var(--accent-soft), 0 0 10px var(--accent); }
/* the current step's key is pressed in: an accent bar along the bottom */
.led-step[aria-current="step"]::after {
  content: "";
  position: absolute;
  left: 18%; right: 18%; bottom: -1px;
  height: 3px;
  border-radius: 3px 3px 0 0;
  background: var(--accent);
}
.led-step[aria-disabled="true"] { cursor: default; opacity: 0.5; }
.led-step[aria-disabled="true"]:hover { color: var(--muted); }
@media (max-width: 559px) {
  .led-step { flex-direction: column; gap: 6px; letter-spacing: 0.06em; }
  .led-num { display: none; }
}

/* ----- The bench: the dock (the cart) and the stage (the current step) ----- */

.bench-grid { display: grid; gap: 20px; padding-top: 18px; }
.stage { min-width: 0; }

/* Phones and tablets: a compact strip above the step. Wide screens: a column that stays in view. */
.dock { display: grid; grid-template-columns: 112px minmax(0, 1fr); column-gap: 18px; align-items: center; }
/* Until a ROM is in there is nothing to preview, and the slot (with its own little cart) needs
   the room on a small screen. The cart arrives with the ROM. */
@media (max-width: 899px) {
  .dock:has(.cart-preview[data-state="empty"]) { display: none; }
}
/* Playing on a phone needs the whole handheld and Print in one screen; the proof under Print
   shows the label art meanwhile. */
@media (max-width: 639px) {
  .bench[data-step="2"] .dock { display: none; }
}
.dock .cart { grid-row: 1 / span 2; }
.dock-title { align-self: end; margin: 0; color: var(--muted); }
.dock-note { align-self: start; margin: 4px 0 0; color: var(--muted); font-size: 0.85rem; }
@media (min-width: 900px) {
  .bench-grid { grid-template-columns: minmax(0, 1fr) 248px; gap: 56px; align-items: start; padding-top: 32px; }
  .dock { display: block; order: 2; position: sticky; top: 24px; }
  .dock-title { margin-bottom: 16px; }
  .dock-note { margin-top: 14px; text-align: center; }
}

/* The preview cartridge: the library's .cart, sized by its own width so a 104px cart and a 248px
   one keep the library's proportions. It is not a link, so it does not lift on hover. */
.cart-preview { position: relative; container-type: inline-size; }
@media (hover: hover) {
  .dock .cart:hover { --pins: var(--pin); transform: none; filter: drop-shadow(0 4px 0 var(--cart-edge)); }
}
.dock .cart:active { transform: none; filter: drop-shadow(0 4px 0 var(--cart-edge)); }
.cart-preview .cart-title { font-size: clamp(0.8rem, 9cqi, 1.5rem); }
.cart-preview .cart-by { font-size: clamp(0.55rem, 5.6cqi, 0.8rem); }
.cart-preview .cart-meta { font-size: clamp(0.55rem, 5.2cqi, 0.75rem); }
.cart-preview .cart-flag { font-size: clamp(0.4rem, 4.6cqi, 0.65rem); }
.cart-preview .cart-flag svg { width: 1.6em; height: 1.6em; }
.cart-title.is-placeholder { color: var(--label-muted); opacity: 0.55; }
.cart-screen {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 4px;
  color: var(--lcd-ink);
  font-family: var(--mono);
  font-size: clamp(0.5rem, 6.5cqi, 0.85rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-align: center;
  text-transform: uppercase;
}
.cart-screen:empty { display: none; }
.cart-preview[data-state="empty"] .cart-label { opacity: 0.8; }
.cart-preview[data-state="empty"] .cart-art { background: var(--lcd); }

/* "In review", pressed onto the label once the submission is accepted. Decorative. */
.stamp {
  position: absolute;
  left: 50%; top: 36%;
  margin: 0;
  padding: 0.2em 0.5em;
  border: 3px solid var(--accent-edge);
  border-radius: 6px;
  background: color-mix(in srgb, var(--label) 82%, transparent);
  color: var(--accent-edge);
  font-family: var(--mono);
  font-size: clamp(0.6rem, 9cqi, 1.3rem);
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translate(-50%, -50%) rotate(-12deg);
}

/* ----- Steps ----- */

.step-title { margin: 0 0 8px; font-size: clamp(1.7rem, 1.4rem + 1vw, 2.2rem); }
/* Headings take focus from script (tabindex="-1"): ring for keyboard users only. */
.step-title:focus { outline: none; }
.step-title:focus-visible { outline: 3px solid var(--accent-ink); }
.step-lede { max-width: 56ch; margin-bottom: 20px; color: var(--muted); }
.step-nav {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px;
  margin-top: 24px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.step-nav .btn-primary { margin-left: auto; }

/* Step 1, Insert. The drop zone is a cartridge slot with a little cart above it that sinks in
   when a file is dragged anywhere over the window. */
.slot {
  position: relative;
  display: grid;
  justify-items: center;
  gap: 14px;
  padding: 96px 20px 26px;
  border: 2px solid var(--line-strong);
  border-radius: 16px;
  background: var(--sunk);
  box-shadow: inset 0 4px 0 rgb(0 0 0 / 6%);
  text-align: center;
  cursor: pointer;
  transition: border-color 120ms ease, background-color 120ms ease;
}
.slot::before { /* the cart */
  content: "";
  position: absolute;
  left: 50%; top: 16px;
  width: 64px; height: 52px;
  margin-left: -32px;
  border-radius: 3px 0 6px 6px;
  clip-path: polygon(0 0, calc(100% - 10px) 0, 100% 10px, 100% 100%, 0 100%);
  background:
    linear-gradient(var(--screen), var(--screen)) 50% 13px / 56% 20px no-repeat,
    linear-gradient(var(--label), var(--label)) 50% 10px / 76% 34px no-repeat,
    repeating-linear-gradient(to bottom, var(--cart-ridge) 0 1px, transparent 1px 3px) 50% 2px / 40% 6px no-repeat,
    var(--cart);
  transition: transform 160ms ease;
}
.slot-mouth { /* the slot, drawn over the cart's lower edge */
  position: absolute;
  left: 50%; top: 58px;
  width: 104px; height: 16px;
  transform: translateX(-50%);
  border-radius: 5px 5px 3px 3px;
  background:
    repeating-linear-gradient(to right, var(--pin) 0 3px, transparent 3px 7px) 50% calc(100% - 3px) / 70% 3px no-repeat,
    var(--lcd);
  box-shadow: inset 0 5px 0 rgb(0 0 0 / 45%), 0 1px 0 var(--surface);
  transition: box-shadow 120ms ease;
}
.slot-text { margin: 0; font-size: clamp(1.35rem, 1.1rem + 1vw, 1.75rem); line-height: 1; }
.slot-text code { font-family: inherit; font-size: inherit; text-transform: none; }
.slot-over { display: none; }
.slot-hint { max-width: 44ch; margin: 0; color: var(--muted); font-size: 0.875rem; }
/* Touch screens have nothing to drag from: the button says it all. */
@media (hover: none) and (pointer: coarse) { .slot-text { display: none; } }
.slot:hover { border-color: var(--ink); }
.slot.is-over { border-color: var(--accent-ink); background-color: var(--accent-soft); }
.slot.is-over::before { transform: translateY(10px); }
.slot.is-over .slot-mouth { box-shadow: inset 0 5px 0 rgb(0 0 0 / 45%), 0 0 0 3px var(--accent), 0 0 18px var(--accent); }
.slot.is-over .slot-idle { display: none; }
.slot.is-over .slot-over { display: inline; }
.slot.is-bad { border-color: var(--warn-line); }

.result { margin-top: 14px; padding: 12px 14px; border: 1px solid var(--line-strong); border-radius: 10px; background: var(--surface); }
.result p { margin: 0; }
.result .result-title { font-weight: 700; margin-bottom: 4px; }
.result ul { margin: 6px 0 0; padding-left: 1.2em; }
.result li { margin-bottom: 4px; }
.result .result-note { margin-top: 8px; color: var(--muted); font-size: 0.9rem; }
.result-ok { border-color: var(--accent-ink); box-shadow: inset 4px 0 0 var(--accent); }
.result-ok .result-title::before { content: "OK  "; font-family: var(--mono); font-size: 0.8em; color: var(--accent-ink); white-space: pre; }
.result-bad { border-color: var(--warn-line); background: var(--warn-bg); color: var(--warn-ink); }
.result-bad .result-note { color: inherit; }
.draft-note { margin: 12px 0 0; color: var(--muted); font-size: 0.9rem; }

/* Step 2, Play. The handheld (5:8, the player's device layout) and, beside it, Print. */
.capture { display: grid; gap: 16px; }
/* Small enough that the LEDs, the handheld and Print share one phone screen. */
.capture-device { position: relative; width: min(100%, 360px, max(240px, (100svh - 290px) * 5 / 8)); aspect-ratio: 5 / 8; margin: 0 auto; border-radius: 18px; }
.capture-device iframe { display: block; width: 100%; height: 100%; border: 0; border-radius: inherit; }
.capture-device::after { /* the shutter flash */
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: #fff;
  opacity: 0;
  pointer-events: none;
}
@media (min-width: 640px) {
  .capture { grid-template-columns: minmax(250px, 340px) minmax(0, 1fr); gap: 28px; align-items: start; }
  .capture-device { margin: 0; }
}
.capture-side { min-width: 0; }
.rom-chip {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 14px 0 0;
  color: var(--muted);
  font-family: var(--mono);
  font-size: 0.75rem;
}
.rom-chip::before { content: ""; flex: none; width: 8px; height: 8px; border-radius: 50%; background: var(--accent); box-shadow: 0 0 6px var(--accent); }
.print-button[aria-disabled="true"] { cursor: progress; }
.proof {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: 14px;
  padding: 10px 12px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--surface);
}
/* the print, like a photo on label paper */
.proof img { flex: none; width: 84px; height: auto; aspect-ratio: 10 / 9; padding: 4px 4px 10px; border-radius: 3px; background: var(--label); box-sizing: content-box; }
.proof p { margin: 0; font-size: 0.9rem; }
.player-help { margin: 14px 0 0; color: var(--muted); font-size: 0.85rem; }
@media (pointer: coarse) { .player-help { display: none; } }

.field-status { min-height: 1.5em; margin: 10px 0 0; font-size: 0.9rem; font-weight: 600; color: var(--muted); }
.field-status.is-bad { color: var(--warn-ink); }
/* Beside Print, the proof shows success; the status line is only seen when something is wrong
   (screen readers still hear every message from it). */
.capture .field-status:not(.is-bad) {
  position: absolute;
  width: 1px; height: 1px;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

/* Step 3, Label. Tags and the optional details (the fields themselves are in section 4). */
.field .chips { margin-top: 4px; }
.field .chip { min-height: 44px; }
#tags-fieldset[aria-invalid="true"] .chip:not([aria-pressed="true"]) { border-color: var(--warn-line); }

/* Three pixel pips beside "Pick up to three": one lights per tag. */
.tags-hint { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 10px; }
.pips { display: inline-flex; gap: 4px; }
.pips i { width: 10px; height: 10px; border-radius: 2px; background: var(--sunk); box-shadow: inset 0 0 0 1px var(--line-strong); }
.pips i.is-on { background: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-edge); }

.field-check { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 12px; align-items: start; }
.field-check input { width: 22px; height: 22px; margin: 1px 0 0; accent-color: var(--accent); }
.field-check > label { font-weight: 550; margin: 0; }
.field-check .field-error { grid-column: 2; }

.more-details { margin: 0 0 8px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); }
.more-details summary { min-height: 56px; font-weight: 700; }
.more-body { padding: 10px 0 2px; }

/* Step 4, Send. The review list, the fine print, the send button and what it still needs. */
.review { margin: 0 0 28px; border-top: 2px solid var(--ink); }
.review-row { display: grid; grid-template-columns: 112px minmax(0, 1fr); gap: 2px 16px; padding: 8px 0; border-bottom: 1px solid var(--line); }
.review dt { padding-top: 12px; color: var(--muted); font-family: var(--mono); font-size: 0.72rem; font-weight: 600; letter-spacing: 0.1em; text-transform: uppercase; }
.review dd { display: flex; justify-content: space-between; align-items: center; gap: 12px; min-width: 0; margin: 0; }
.review-value { min-width: 0; white-space: pre-line; overflow-wrap: anywhere; }
.review-cover { display: block; width: 80px; height: auto; aspect-ratio: 10 / 9; border-radius: 2px; }
/* "Change": a quiet text key, so six of them do not shout; still a 44px target. */
.review-edit {
  flex: none;
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: var(--accent-ink);
  font: inherit;
  font-size: 0.875rem;
  font-weight: 650;
  text-decoration: underline;
  text-underline-offset: 0.18em;
  cursor: pointer;
}
.review-edit:hover { text-decoration-thickness: 2px; }
@media (max-width: 480px) {
  .review-row { grid-template-columns: minmax(0, 1fr); }
  .review dt { padding-top: 4px; }
}

.fine { max-width: 60ch; margin: 4px 0 20px; padding-left: 12px; border-left: 3px solid var(--accent); color: var(--muted); font-size: 0.9rem; }

.send-nav { margin-top: 0; }
.send-nav .btn { min-height: 56px; }
.send-nav .submit-button { flex: 1 1 240px; width: auto; max-width: 360px; }
.missing { margin: 10px 0 0; color: var(--muted); font-size: 0.9rem; text-align: right; }
.missing.is-ready { color: var(--accent-ink); font-weight: 700; }
.submit-error:not([hidden]) ~ .missing.is-ready { display: none; }

/* The confirmation: the stamped cart stays in the dock; a claim ticket prints out here. */
.success:focus { outline: none; }
.success > p { max-width: 52ch; color: var(--muted); }
.ticket {
  max-width: 420px;
  margin: 24px 0 28px;
  padding: 16px 20px 20px;
  border-top: 6px solid var(--accent);
  border-radius: 6px;
  background: var(--label);
  color: var(--label-ink);
  box-shadow: inset 0 0 0 1px rgb(0 0 0 / 10%), 0 3px 0 var(--cart-edge);
}
.ticket p { margin: 0; }
.ticket .ticket-head { display: flex; justify-content: space-between; gap: 12px; margin-bottom: 10px; color: var(--label-muted); }
.ticket .ticket-title { margin-bottom: 14px; font-size: 1.7rem; }
.ticket-id { position: relative; padding-top: 14px; border-top: 2px dashed rgb(0 0 0 / 22%); }
/* the stub's two notches, punched where the tear line meets the edges */
.ticket-id::before, .ticket-id::after {
  content: "";
  position: absolute;
  top: -12px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--bg);
}
.ticket-id::before { left: -31px; }
.ticket-id::after { right: -31px; }
.ticket-id .label { color: var(--label-muted); }
.ticket-id code { font-size: 1.2rem; font-weight: 700; letter-spacing: 0.04em; overflow-wrap: anywhere; user-select: all; }
.ticket .ticket-note { margin: 6px 0 14px; color: var(--label-muted); font-size: 0.85rem; }
.upload .btn-small { min-height: 44px; }

/* Moments, each tied to a real event and none of them blocking. All off under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .led-step[aria-current="step"] .led { animation: led-glow 1.6s ease-in-out infinite alternate; }
  .slot:hover::before { transform: translateY(3px); }
  .cart-preview[data-state="empty"] .cart-screen { animation: blink 1.4s steps(2, jump-none) infinite; }
  /* the ROM goes in: the cart drops onto the bench, its pins light, the title types on */
  .cart-preview.is-anim-insert { --pins: var(--accent); animation: cart-insert 460ms cubic-bezier(0.3, 1.5, 0.5, 1); }
  .cart-title.is-anim-type { animation: type-on 520ms steps(14, end); }
  /* Print: a shutter flash on the handheld, and the frame prints onto the label line by line */
  .capture-device.is-flash::after { animation: shutter 260ms ease-out; }
  .cover.is-anim-print { animation: print-in 560ms steps(9, end); }
  /* full tags: the pips shake no */
  .pips.is-full { animation: shake 260ms steps(4, end); }
  .submit-button.is-sending { animation: stripes 700ms linear infinite; }
  /* sent: the stamp comes down, the ticket prints out */
  .stamp.is-anim-stamp { animation: stamp 280ms cubic-bezier(0.2, 1.6, 0.4, 1); }
  .success:not([hidden]) .ticket { animation: print-in 640ms steps(8, end) 200ms backwards; }
}
@keyframes led-glow { from { filter: brightness(0.9); } to { filter: brightness(1.25); } }
@keyframes cart-insert { 0% { transform: translateY(-16px); } 60% { transform: translateY(3px); } 100% { transform: none; } }
@keyframes type-on { from { clip-path: inset(0 100% 0 0); } to { clip-path: inset(0); } }
@keyframes shutter { from { opacity: 0.7; } to { opacity: 0; } }
@keyframes print-in { from { clip-path: inset(0 0 100% 0); } to { clip-path: inset(0); } }
@keyframes shake { 0%, 100% { transform: none; } 25% { transform: translateX(-3px); } 75% { transform: translateX(3px); } }
@keyframes stripes { from { background-position: 0 0; } to { background-position: 28.28px 0; } }
@keyframes stamp { from { opacity: 0; transform: translate(-50%, -50%) rotate(-12deg) scale(1.8); } to { opacity: 1; transform: translate(-50%, -50%) rotate(-12deg) scale(1); } }


/* ========== 9. Utilities ========== */

[hidden] { display: none !important; }

.visually-hidden {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}


/* ========== 10. Reduced motion ========== */

@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;
  }
  .cart:hover, .cart:active { transform: none; }
}
