:root {
  --ice: #f3f7fb;
  --ice-line: #dbe5ee;
  --blue: #1c5fb8;
  --red: #c8102e;
  --text: #0f1b2b;
  --muted: #5a6b7c;
  --card: #ffffff;
  --card-edge: #d7e0ea;
  --accent: #1c5fb8;
  --amber: #e0a100;
  --danger: #c8102e;
  --ok: #1e8a4c;
  --puck: #101418;
  --puck-text: #ffffff;
  --overlay: rgba(243, 247, 251, 0.94);
  /* Team mode's buzzer: one red in every theme, like a real one (not
     redefined for the dark palette) */
  --buzzer: #d0121f; --buzzer-deep: #8e0b18; --buzzer-base: #5a0710; --buzzer-hi: #ff6b73; --buzzer-word: #ffffff;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --ice: #16212c; --ice-line: #233242; --blue: #4d8be0; --red: #e3384f;
    --text: #e8eef5; --muted: #9fb0c1; --card: #1f2c39; --card-edge: #324456;
    --accent: #6ea4f0; --amber: #ffc43d; --danger: #ff5c70; --ok: #4fcf84;
    --puck: #f3f7fb; --puck-text: #101418; --overlay: rgba(22, 33, 44, 0.94);
  }
}
:root[data-theme="dark"] {
  --ice: #16212c; --ice-line: #233242; --blue: #4d8be0; --red: #e3384f;
  --text: #e8eef5; --muted: #9fb0c1; --card: #1f2c39; --card-edge: #324456;
  --accent: #6ea4f0; --amber: #ffc43d; --danger: #ff5c70; --ok: #4fcf84;
  --puck: #f3f7fb; --puck-text: #101418; --overlay: rgba(22, 33, 44, 0.94);
}

* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; color: var(--text); background: var(--ice);
  font: 16px/1.4 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  display: flex; flex-direction: column; min-height: 100dvh;
}
button, input, select, textarea { font: inherit; color: inherit; }
[hidden] { display: none !important; }

/* The rink: blue lines at 35% / 65%, the red line and centre circle at 50%. */
.rink {
  flex: 1; position: relative; padding: 16px 16px 24px;
  background:
    radial-gradient(circle at 50% 50%, transparent 0 70px, var(--red) 70px 73px, transparent 73px),
    radial-gradient(circle at 50% 50%, var(--red) 0 4px, transparent 4px),
    linear-gradient(to bottom, transparent calc(50% - 2px), var(--red) calc(50% - 2px) calc(50% + 2px), transparent calc(50% + 2px)),
    linear-gradient(to bottom, transparent calc(35% - 4px), var(--blue) calc(35% - 4px) calc(35% + 4px), transparent calc(35% + 4px),
      transparent calc(65% - 4px), var(--blue) calc(65% - 4px) calc(65% + 4px), transparent calc(65% + 4px)),
    repeating-linear-gradient(90deg, transparent 0 39px, var(--ice-line) 39px 40px),
    var(--ice);
  background-attachment: scroll;
}
.rink::before { /* frost */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, rgba(255,255,255,.35), transparent 30%, transparent 70%, rgba(255,255,255,.25));
}
@media (prefers-color-scheme: dark) { .rink::before { background: none; } }
.screen { position: relative; max-width: 560px; margin: 0 auto; }
.rink { overflow-x: clip; }

/* Scoreboard */
.scoreboard {
  display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px;
  padding: 10px 16px; background: var(--puck); color: var(--puck-text);
  font-variant-numeric: tabular-nums;
}
.scoreboard .seat { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.scoreboard .seat.right { text-align: right; }
.scoreboard .sname { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; opacity: .55; }
.scoreboard .seat.on .sname { opacity: 1; }
.scoreboard .seat.on .sname::before { content: "● "; color: var(--ok); font-size: 10px; vertical-align: middle; }
.scoreboard .seat.right.on .sname::before { content: ""; }
.scoreboard .seat.right.on .sname::after { content: " ●"; color: var(--ok); font-size: 10px; vertical-align: middle; }
.scoreboard .slives { font-size: 12px; opacity: .8; letter-spacing: 2px; }
.scoreboard .center { text-align: center; }
.scoreboard .brand { display: block; font-weight: 800; letter-spacing: .5px; font-size: 13px; text-transform: uppercase; opacity: .8; }
/* the other side's last turn, after a buzz */
.scoreboard .brand.last { color: var(--danger); opacity: 1; }
.scoreboard .chain { display: block; font-weight: 800; font-size: 22px; line-height: 1; }

/* Home */
.title { font-size: 44px; font-weight: 900; letter-spacing: -1px; margin: 24px 0 6px; text-align: center; }
.title b { font-weight: inherit; color: var(--blue); }
.title span { color: var(--red); }
.tag { text-align: center; color: var(--muted); margin: 0 0 20px; }
.tag b { font-weight: 800; color: var(--accent); border-bottom: 2px solid currentColor; }
.modes { display: grid; grid-template-columns: repeat(2, 1fr); gap: 8px; margin-bottom: 14px; }
.setup .rules ul { margin: 0; padding: 0; list-style: none; color: var(--muted); font-size: 13px; display: grid; gap: 5px; }
.setup .rules li b { color: var(--text); }
/* The rules are folded away until the arrow beside their heading is pressed. */
.setup .rules summary { font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); cursor: pointer; list-style: none; width: fit-content; }
.setup .rules summary::-webkit-details-marker { display: none; }
.setup .rules summary::after { content: " ▸"; }
.setup .rules details[open] summary::after { content: " ▾"; }
.setup .rules details[open] summary { margin-bottom: 4px; }
.mode {
  background: var(--card); border: 2px solid var(--card-edge); border-radius: 14px; padding: 14px 12px;
  text-align: left; cursor: pointer; display: flex; flex-direction: column; gap: 3px;
}
.mode strong { font-size: 18px; }
.mode small { color: var(--muted); }
.mode.on { border-color: var(--accent); box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 25%, transparent), 0 0 16px 4px color-mix(in srgb, var(--accent) 55%, transparent); }
.setup { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 14px; display: grid; gap: 12px; }
.setup label { display: block; font-size: 12px; font-weight: 700; text-transform: uppercase; letter-spacing: .6px; color: var(--muted); margin-bottom: 4px; }
.setup .row > div[data-view] { margin-top: 12px; }
.setup .row.two { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.setup input[type=text], .setup select, .setup textarea {
  width: 100%; padding: 10px 12px; border: 1px solid var(--card-edge); border-radius: 10px; background: var(--ice);
}
.setup textarea { resize: vertical; }
.seg { display: flex; gap: 4px; flex-wrap: wrap; }
.seg button { flex: 1; padding: 8px 6px; border: 1px solid var(--card-edge); border-radius: 10px; background: var(--ice); cursor: pointer; white-space: nowrap; }
.seg button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
/* Six clocks: two even rows of three (60 s alone on a row read as a different button). */
#clock button { flex: 0 0 calc((100% - 8px) / 3); }
.go {
  padding: 14px; border: 0; border-radius: 12px; background: var(--red); color: #fff;
  font-weight: 800; font-size: 18px; cursor: pointer; width: 100%;
}
.go:disabled { opacity: .5; cursor: default; }
/* The install hint (the Android design, D6): a small button in the home foot. */
.go.install { display: block; width: auto; margin: 14px auto 0; padding: 8px 16px; font-size: 14px; }
.foot-note.beta { font-weight: 700; }   /* the Play test's line (the Android design): the one call to action on Android */
.board { text-align: center; color: var(--muted); font-size: 13px; margin: 14px 0 0; }
.board strong { color: var(--text); }
.foot { display: flex; gap: 14px; justify-content: center; flex-wrap: wrap; color: var(--muted); font-size: 13px; margin-top: 16px; }
.link { background: none; border: 0; color: var(--accent); cursor: pointer; padding: 4px 6px; text-decoration: underline; }

/* Game */
.play { min-height: 190px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; padding: 8px 0; }
.name-card {
  background: var(--card); border: 1px solid var(--card-edge); border-radius: 16px; padding: 14px 22px;
  text-align: center; box-shadow: 0 10px 30px rgba(0,0,0,.12); max-width: 100%;
}
.name-card .nm { font-size: 30px; font-weight: 800; letter-spacing: -.5px; line-height: 1.1; }
.name-card .nm .hl { color: var(--red); font-size: 1.35em; font-weight: 900; }
.name-card .bio { color: var(--muted); font-size: 13px; margin-top: 4px; font-variant-numeric: tabular-nums; }
.name-card.enter { animation: pass-in .5s cubic-bezier(.2,.9,.3,1.1) both; }
@keyframes pass-in { from { transform: translateX(-60vw) rotate(-4deg); opacity: 0; } to { transform: none; opacity: 1; } }

.thinking { display: flex; gap: 6px; }
.thinking span { width: 10px; height: 10px; border-radius: 50%; background: var(--muted); animation: blink 1.2s infinite; }
.thinking span:nth-child(2) { animation-delay: .2s; } .thinking span:nth-child(3) { animation-delay: .4s; }
@keyframes blink { 0%, 80%, 100% { opacity: .25; } 40% { opacity: 1; } }

.callout {
  /* Above the puck and the name card on every layout: fixed, centred, own backing. */
  position: fixed; left: 50%; top: 42vh; transform: translate(-50%, -50%); z-index: 6;
  padding: 10px 28px; border-radius: 18px; background: var(--overlay);
  box-shadow: 0 10px 40px rgba(0,0,0,.25); text-align: center; pointer-events: none; white-space: nowrap;
  font-size: 48px; font-weight: 900; letter-spacing: -1px; text-transform: uppercase; color: var(--red);
  animation: shout .9s ease-out both;
}
.callout.ok { color: var(--ok); }
.callout .why { display: block; font-size: 14px; font-weight: 600; text-transform: none; letter-spacing: 0; color: var(--text); }
@keyframes shout {
  0% { transform: translate(-50%, -50%) scale(.4); opacity: 0; }
  25% { transform: translate(-50%, -50%) scale(1.08); opacity: 1; }
  100% { transform: translate(-50%, -50%) scale(1); opacity: 1; }
}
@media (max-width: 420px) { .callout { font-size: 36px; white-space: normal; max-width: 90vw; } }
/* The wall's WOW! under GIGANTIC SAVE! (Team-mode design, section 18): the
   same shout, a size down, popping PACE.wowMs after it (app.js sets the
   delay); it goes when the callout does. */
.callout .wow { display: block; font-size: .75em; animation: wow .9s ease-out both; }
@keyframes wow {
  0% { transform: scale(.4); opacity: 0; }
  25% { transform: scale(1.08); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
/* A commentator's saying under the shout (nhl-game-logs
   docs/design-change-up-sayings.md, style A; its rise, section 10, look 3):
   the shout's face at .8 of its size, in the page's text colour on the
   overlay — the voice from the booth, not the team's colour. A block that
   wraps to a second line when it must, PACE.sayMs after the shout (app.js
   sets the delays). It rises in three beats — small (.65, the size it used
   to be), medium (.82), large — three cuts 150 ms apart, scaled from its
   top edge so the gap under the shout never moves; and the large one hits:
   amber with a glow settling to the text colour, the words knocked a few
   pixels and back (rise-hit, PACE.sayHitMs after the saying, fill forwards
   so nothing of it shows before). It goes when the callout does, which
   stays PACE.sayHoldMs longer for it. */
.callout .say { display: block; margin: 10px auto 0; white-space: normal; max-width: 86vw; font-size: .8em; letter-spacing: -.5px; color: var(--text); font-weight: 800; transform-origin: 50% 0;
  animation: rise-beats .45s linear both, rise-hit .32s ease-out forwards; }
@keyframes rise-beats {
  0%, 32% { transform: scale(.65); opacity: 1; }
  34%, 65% { transform: scale(.82); }
  67%, 100% { transform: scale(1); }
}
@keyframes rise-hit {
  0% { color: var(--amber); text-shadow: 0 0 18px var(--amber); translate: 0 0; }
  20% { translate: -4px 2px; }
  40% { translate: 4px -2px; }
  60% { translate: -2px 1px; }
  80% { translate: 1px 0; }
  100% { color: var(--text); text-shadow: 0 0 0 transparent; translate: 0 0; }
}

.puck-row { display: flex; flex-direction: column; align-items: center; gap: 6px; margin: 6px 0 14px; }
.puck { position: relative; width: 132px; height: 132px; }
.puck svg { position: absolute; inset: 0; width: 100%; height: 100%; transform: rotate(-90deg); }
.puck .ring-bg { fill: var(--puck); stroke: var(--card-edge); stroke-width: 6; }
.puck .ring { fill: none; stroke: var(--ok); stroke-width: 6; stroke-linecap: round;
  stroke-dasharray: 282.7; stroke-dashoffset: 0; transition: stroke .3s; }
.puck.warn .ring { stroke: var(--amber); } .puck.danger .ring { stroke: var(--danger); }
.puck .letter { position: absolute; inset: 0; display: grid; place-items: center; color: var(--puck-text);
  font-size: 56px; font-weight: 900; line-height: 1; padding-bottom: 10px; }
.puck .letter.free { font-size: 20px; letter-spacing: 1px; }
.puck .letter.pop { animation: pop .4s ease-out; }
@keyframes pop { 0% { transform: scale(.5); } 60% { transform: scale(1.2); } 100% { transform: scale(1); } }
/* The puck drop (nhl-game-logs docs/design-change-up-puck-drop.md, D3; web/app.js
   puckDrop): the ring full and the seconds hidden while the wheel spins; the
   landed letter's halo for the glow's 800 ms. */
.puck.drop .ring { stroke-dashoffset: 0 !important; }
.puck.drop .secs { visibility: hidden; }
.puck .letter.drop { animation: drop .8s ease-out; }
/* The landing is the pop AND the halo (D3): the two rules above are one
   weight, so alone the later one would replace the pop (R2). */
.puck .letter.pop.drop { animation: pop .4s ease-out, drop .8s ease-out; }
@keyframes drop {
  0% { text-shadow: 0 0 0 transparent; }
  30% { text-shadow: 0 0 14px var(--ok), 0 0 28px var(--ok); }
  100% { text-shadow: 0 0 0 transparent; }
}
.puck .secs { position: absolute; left: 0; right: 0; bottom: 24px; text-align: center; color: var(--puck-text);
  font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums; opacity: .85; }
/* Team mode's buzzer beside the puck (nhl-game-logs
   docs/design-change-up-buzzer.md, section 7: look 4, the mini, from
   mocks/buzzer/buzzer.css). The pair is centred; with the buzzer hidden
   (Classic) the puck sits where it always has. Locked: dim and disabled;
   armed: breathing; pressed: sunk into its base, dark, BUZZED. */
.puck-pair { display: flex; align-items: center; justify-content: center; gap: 18px; }
.buzzer {
  position: relative; width: 92px; height: 92px; border-radius: 50%; border: 0; padding: 0; margin: 0;
  background: var(--buzzer); color: var(--buzzer-word); cursor: pointer; font: inherit;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  box-shadow: 0 5px 0 var(--buzzer-base);
  -webkit-tap-highlight-color: transparent; user-select: none;
}
.buzzer .bi { position: relative; display: flex; flex-direction: column; align-items: center; }
.buzzer .bw { font-size: 19px; font-weight: 900; letter-spacing: 1px; line-height: 1; }
.buzzer:disabled { cursor: default; }
.buzzer.locked { filter: saturate(.1); opacity: .38; }
.buzzer.armed { animation: buzz-breathe 1.8s ease-in-out infinite; }
@keyframes buzz-breathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.045); } }
.buzzer.pressed { background: var(--buzzer-deep); transform: translateY(4px); box-shadow: 0 1px 0 var(--buzzer-base); }
.buzzer.pressed .bw { font-size: 15px; }
@media (prefers-reduced-motion: reduce) { .buzzer.armed { animation: none; } }
.hint { font-size: 13px; color: var(--muted); min-height: 18px; }

.answer { display: flex; gap: 8px; }
.answer input { flex: 1; padding: 14px; font-size: 18px; border: 2px solid var(--card-edge); border-radius: 12px; background: var(--card); }
.answer input:focus { outline: none; border-color: var(--accent); }
.answer button { padding: 0 20px; border: 0; border-radius: 12px; background: var(--accent); color: #fff; font-weight: 800; cursor: pointer; }
.answer input:disabled, .answer button:disabled { opacity: .5; }
.answer.shake { animation: shake .4s; }
@keyframes shake { 20% { transform: translateX(-8px); } 40% { transform: translateX(8px); } 60% { transform: translateX(-5px); } 80% { transform: translateX(5px); } }

.overlay { position: fixed; inset: 0; background: var(--overlay); display: grid; place-items: center; z-index: 5; }
.overlay .box { text-align: center; padding: 24px; max-width: 360px; width: 100%; display: grid; gap: 8px; }
.pass-to { color: var(--muted); text-transform: uppercase; letter-spacing: 1px; font-size: 13px; }
.pass-name { font-size: 40px; font-weight: 900; }
.pass-letter { color: var(--muted); margin-bottom: 8px; }
.pass-letter b { color: var(--red); font-size: 22px; }

/* Team mode: the two lineup cards (yours left, theirs right). */
.lineups { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; margin-bottom: 4px; }
.lineup { background: var(--card); border: 1px solid var(--card-edge); border-radius: 12px; padding: 6px; min-width: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 7px; }
.lineup .lhead { display: flex; justify-content: space-between; gap: 6px; font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.lineup .lhead span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
.lineup .lhead span:last-child { flex: 0 0 auto; }
.lineup .lrow { display: flex; gap: 7px; justify-content: center; }   /* the chemistry rings need the room (design-change-up-chem-glow.md, D6) */
.chip {
  flex: 1 1 0; min-width: 0; max-width: 34%; border: 1px dashed var(--card-edge); border-radius: 8px; padding: 3px 4px;
  text-align: center; line-height: 1.15; background: var(--ice);
}
.chip .cs { display: block; white-space: nowrap; font-size: 9px; font-weight: 700; letter-spacing: .2px; color: var(--muted); }
.chip .cn { display: block; font-size: 11px; font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
/* The nameplate (app.js fitName): the name's own box, measured, its type
   brought down and then condensed from the left edge until it fits. */
.chip .cn .cnt { display: inline-block; vertical-align: top; transform-origin: 0 50%; }
.chip.filled .cn { text-overflow: clip; height: 13px; line-height: 13px; }
/* A phone: thinner gutters, so the chips (and their names) get the width. */
@media (max-width: 420px) {
  .lineups { gap: 6px; } .lineup { padding: 4px; } .lineup .lrow { gap: 6px; }
  .chip { padding: 3px 2px; }
}
.chip .co { display: block; font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; }
.chip.filled { border-style: solid; border-color: var(--accent); background: var(--card); }
/* A chip in its player's team colours (inline style): the slot and the
   rating take the text colour, a shade lighter. */
.chip.filled.team { border-width: 2px; }
.chip.filled.team .cs, .chip.filled.team .co { color: inherit; opacity: .78; }
.lineups.dim .chip.team { opacity: .55; }
.chip.empty .cn { color: var(--muted); font-weight: 400; }
.chip.callup { border-style: dotted; opacity: .7; }
/* A substitute for an injured man (the series card): a red cross on the
   chip's corner. */
.chip .cx { position: absolute; top: -5px; right: -5px; width: 13px; height: 13px; border-radius: 50%; background: #d8252f; color: #fff;
  font-size: 9px; line-height: 13px; font-weight: 900; text-align: center; box-shadow: 0 0 0 1.5px var(--card); }
.series .inj { font-size: 13px; padding-top: 0; }
.chip.bench { max-width: none; flex: 0 0 auto; padding: 3px 8px; border-style: dotted; }
/* The bench peek (nhl-game-logs docs/design-change-up-bench.md, the pick B). In the
   name phase the Bench chip is a button: the label, the count, the chevron where the
   OVR sits on a player's chip (▾ closed, ▴ open), so the row's height does not change.
   A bench of 0 has no chevron and does nothing. Open: a solid accent edge, like a
   filled chip's. The series and final cards keep the plain div, hence button. here. */
button.chip.bench { font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; -webkit-user-select: none; user-select: none; }
button.chip.bench:disabled { cursor: default; }
button.chip.bench .co { font-size: 11px; line-height: 12px; color: var(--muted); position: relative; }
button.chip.bench:not(:disabled) .co::after { content: "▾"; position: absolute; left: 0; right: 0; top: 0; }
button.chip.bench[aria-expanded="true"] .co::after { content: "▴"; }
button.chip.bench[aria-expanded="true"] { border-style: solid; border-color: var(--accent); color: var(--accent); }
button.chip.bench[aria-expanded="true"] .cs, button.chip.bench[aria-expanded="true"] .co { color: var(--accent); }
/* The bench list: one man a row — his position, his full name (fitted as a nameplate
   is, app.js fitName), his OVR — in his team colours like his chip would be. */
.bench-list { display: grid; gap: 3px; margin: 0; padding: 0; list-style: none; }
.brow { display: flex; align-items: center; gap: 5px; padding: 2px 6px; border: 1px solid var(--card-edge); border-radius: 6px; background: var(--ice); color: var(--text); font-size: 11px; font-weight: 700; line-height: 16px; min-width: 0; text-align: left; }
.brow.team { border-width: 2px; padding: 1px 5px; }
.brow .bp { flex: 0 0 auto; width: 16px; font-size: 8.5px; letter-spacing: .2px; opacity: .78; }
.brow .bn { flex: 1 1 auto; min-width: 0; height: 16px; white-space: nowrap; overflow: hidden; }
.brow .bn .cnt { display: inline-block; vertical-align: top; transform-origin: 0 50%; }
.brow .bo { flex: 0 0 auto; font-size: 10px; opacity: .78; font-variant-numeric: tabular-nums; }
/* past seven men the list scrolls inside its box (a third of a seventh row shows there is more) */
.bench-list.scroll { max-height: calc(6 * 22px + 5 * 3px + 8px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
/* The bubble: hanging from the card's bottom edge over the name card's area, the card's
   width, a caret under the Bench chip; the card above its neighbours while open. Nothing
   under it moves. */
.lineup { position: relative; }
.lineup.peek { z-index: 4; }
.bench-pop { position: absolute; left: 0; right: 0; top: calc(100% + 7px); z-index: 4; padding: 6px; background: var(--card); border: 1px solid var(--accent); border-radius: 10px; box-shadow: 0 10px 26px rgba(15, 27, 43, .22); }
.bench-pop::before { content: ""; position: absolute; top: -6px; right: var(--caret, 27px); width: 10px; height: 10px; background: var(--card); border-left: 1px solid var(--accent); border-top: 1px solid var(--accent); transform: translateX(50%) rotate(45deg); }
/* A player's chip has two faces: the chip (.cf) and, on a tap, his ratings
   (.cb) over it, on the scoreboard's black whatever the team's colours. */
.chip { position: relative; }
.chip.filled[data-pid] { cursor: pointer; -webkit-tap-highlight-color: transparent; }
.chip .cf { display: block; }
.chip.flipped .cf { visibility: hidden; }
.chip .cb {
  display: none; position: absolute; inset: 0; border-radius: 6px; padding: 1px 4px; background: #101418; color: #fff;
  grid-template-columns: 1fr; align-content: space-evenly;
}
.chip.flipped .cb { display: grid; }
.chip .ca { display: flex; justify-content: space-between; align-items: baseline; font-size: 8.75px; line-height: 1; }
/* A skater's back: two columns of three (SHO PLY PHY / DEF DIS OVR), each
   rating under its acronym, big enough to read (user, 2026-10-08: six rows of
   8 px were not). It is its own size, centred on the chip and over its
   neighbours' edges when the chip is narrower — a phone's is 50 px wide. A
   goalie's two cells keep the chip's own box. */
.chip.flipped { z-index: 3; }
.chip .cb:not(.goalie) {
  inset: auto; left: 50%; top: 50%; transform: translate(-50%, -50%); width: max-content; min-width: max(100%, 62px); min-height: 100%;
  grid-template-columns: 1fr 1fr; grid-template-rows: repeat(3, auto); grid-auto-flow: column; gap: 0 6px; padding: 2px 5px;
}
.chip .cb:not(.goalie) .ca { flex-direction: column; align-items: center; justify-content: center; }
.chip .cb:not(.goalie) .ca i { font-size: 7.5px; line-height: 8px; font-style: normal; opacity: .75; }
.chip .cb:not(.goalie) .ca b { font-size: 14px; line-height: 14px; }
.chip .ca i { font-style: normal; font-size: 7px; font-weight: 700; letter-spacing: .3px; color: #9fb0c1; }
.chip .ca b { font-weight: 800; font-variant-numeric: tabular-nums; }
.chip .ca.boost b { color: #ffd23f; }
.chip .cb.goalie .ca { font-size: 12px; } .chip .cb.goalie .ca i { font-size: 8px; }
@keyframes chip-flip { 50% { transform: rotateY(90deg); } }
/* The birth country's flag in the chip's corner (web/flags.js); it glows
   when a countryman is on the card (the halo's rules are with the chemistry's). */
.flag { display: inline-block; vertical-align: -1px; margin-right: 2px; width: 12px; height: 8px; border-radius: 2px; overflow: hidden; box-shadow: 0 0 0 .5px rgba(0, 0, 0, .4); }
.flag svg { display: block; width: 100%; height: 100%; }
.flag.code { width: auto; padding: 0 1.5px; font-size: 6px; font-weight: 800; line-height: 9px; letter-spacing: 0; background: #fff; color: #111; }
.name-card .flag { margin-right: 1px; }
/* The icons' line is always there, so every player's chip is one height. */
.chip .ci { display: block; font-size: 9px; line-height: 12px; height: 12px; white-space: nowrap; overflow: hidden; }
/* Chemistry (engine/chemistry.js), nhl-game-logs docs/design-change-up-chem-glow.md:
   gold for 50 goals together, silver (steel, with an icy bloom) for the same
   team, green for a countryman — a hairline of the card, a 3 px ring, a bright
   inner bloom, a wide outer one, breathing on the kind's own beat. A man with a
   link and a countryman wears both rings, the link's inside. Before .lit, whose
   animation wins for its second (the stack's rule is :where'd to the base's
   weight, so .lit, .can and the reduced-motion list still win over it). */
:root { --chem-gold: 255, 196, 0; --chem-gold-hi: 255, 236, 140;
        --chem-silver: 120, 145, 172; --chem-silver-hi: 200, 230, 255;
        --chem-green: 40, 220, 120; --chem-green-hi: 160, 255, 200;
        --beat-history: 2s; --beat-team: 2.6s; --beat-country: 1.7s; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) { --chem-silver: 226, 236, 246; --chem-silver-hi: 190, 225, 255; } }
:root[data-theme="dark"] { --chem-silver: 226, 236, 246; --chem-silver-hi: 190, 225, 255; }
.chip.chem-history { --glow: var(--chem-gold); --hi: var(--chem-gold-hi); --beat: var(--beat-history); }
.chip.chem-team { --glow: var(--chem-silver); --hi: var(--chem-silver-hi); --beat: var(--beat-team); }
.chip.chem-country:not(.chem-history):not(.chem-team) { --glow: var(--chem-green); --hi: var(--chem-green-hi); --beat: var(--beat-country); }
.chip:is(.chem-history, .chem-team, .chem-country) {
  box-shadow: 0 0 0 1px var(--card), 0 0 0 3px rgb(var(--glow)), 0 0 6px 2px rgba(var(--hi), .95), 0 0 16px 7px rgba(var(--glow), .85);
  animation: chem-glow var(--beat) ease-in-out infinite;
}
@keyframes chem-glow { 50% { box-shadow: 0 0 0 1px var(--card), 0 0 0 3px rgb(var(--glow)), 0 0 3px 1px rgba(var(--hi), .5), 0 0 8px 3px rgba(var(--glow), .45); } }
/* the stack (a link and countrymen): the link's ring inside, the country's outside, both blooms */
.chip:is(.chem-history, .chem-team):where(.chem-country) {
  box-shadow: 0 0 0 1px var(--card), 0 0 0 3px rgb(var(--glow)), 0 0 0 4px var(--card), 0 0 0 6px rgb(var(--chem-green)),
    0 0 8px 6px rgba(var(--hi), .9), 0 0 22px 11px rgba(var(--chem-green), .75);
  animation: chem-glow-2 var(--beat) ease-in-out infinite;
}
@keyframes chem-glow-2 { 50% { box-shadow: 0 0 0 1px var(--card), 0 0 0 3px rgb(var(--glow)), 0 0 0 4px var(--card), 0 0 0 6px rgb(var(--chem-green)), 0 0 4px 3px rgba(var(--hi), .5), 0 0 10px 5px rgba(var(--chem-green), .4); } }
/* the slot letters in the kind's colour (the link's on a stacked man): the tie reads inside the chip too */
.chip:is(.chem-history, .chem-team, .chem-country) .cs { color: rgb(var(--glow)); opacity: 1; text-shadow: 0 0 4px rgba(var(--hi), .9); }
/* the flag's halo, on the country's beat (the chips, the bench rows, the name card) */
.flag.on { box-shadow: 0 0 0 1.5px rgb(var(--chem-green)), 0 0 8px 3px rgba(var(--chem-green), 1); animation: flag-glow var(--beat-country) ease-in-out infinite; }
@keyframes flag-glow { 50% { box-shadow: 0 0 0 1.5px rgb(var(--chem-green)), 0 0 3px 1px rgba(var(--chem-green), .5); } }
/* the name card's lines in the same three */
.name-card .slot-line small.chem-history { color: #e0a600; font-weight: 700; }
.name-card .slot-line small.chem-team { color: #6f8aa6; font-weight: 700; }
.name-card .slot-line small.chem-country { color: #1fb765; font-weight: 700; }
@media (prefers-color-scheme: dark) { :root:not([data-theme="light"]) .name-card .slot-line small.chem-team { color: #c9d8e8; } }
:root[data-theme="dark"] .name-card .slot-line small.chem-team { color: #c9d8e8; }
/* The sparkles (the design's C): two stars on the chip's corners, twinkling a
   half-beat apart; a stacked man's second star in green. The line change
   screen's ⇄ badge is .chip.in::after (below): the star yields it the ::after
   (:not(.in)) and the other star moves to the free corner on that chip. */
.chip:is(.chem-history, .chem-team, .chem-country)::before, .chip:is(.chem-history, .chem-team, .chem-country):not(.in)::after {
  content: "✦"; position: absolute; z-index: 1; font-size: 12px; line-height: 1; font-weight: 400; pointer-events: none;
  color: rgb(var(--hi)); text-shadow: 0 0 3px rgb(var(--glow)), 0 0 8px rgb(var(--glow));
  animation: chem-spark 1.4s ease-in-out infinite;
}
.chip:is(.chem-history, .chem-team, .chem-country)::before { top: -9px; right: -6px; }
.chip:is(.chem-history, .chem-team, .chem-country):not(.in)::after { bottom: -8px; left: -6px; animation-delay: -.7s; font-size: 9px; }
.chip.chem-country:is(.chem-history, .chem-team):not(.in)::after { color: rgb(var(--chem-green-hi)); text-shadow: 0 0 3px rgb(var(--chem-green)), 0 0 8px rgb(var(--chem-green)); }
.chip.in:is(.chem-history, .chem-team, .chem-country)::before { top: auto; right: auto; bottom: -8px; left: -6px; font-size: 9px; }
@keyframes chem-spark { 0%, 100% { transform: scale(1) rotate(0); opacity: 1; } 50% { transform: scale(.25) rotate(90deg); opacity: .3; } }
/* The flip (a tap on a chip) after the chemistry rules, at their weight: its .3 s
   squeeze takes the glow's animation as .lit does (R1: before, a glowing chip
   swapped faces without the turn). */
.chip.flipping { animation: chip-flip .3s ease-in-out; }
.chip.lit { animation: chip-lit 1.1s ease-out; }
@keyframes chip-lit { 0% { background: var(--ok); color: #fff; transform: scale(1.06); } 100% { transform: none; } }
.lineups.final .lineup { padding: 8px; }
.name-card .slot-line { margin-top: 6px; font-size: 14px; font-weight: 700; color: var(--accent); }
.name-card .slot-line small { display: block; font-weight: 400; color: var(--muted); font-size: 12px; }
.team .play { min-height: 150px; }
.series { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 10px 14px; margin: 10px 0 14px; font-variant-numeric: tabular-nums; }
.series h3 { margin: 0 0 6px; font-size: 18px; }
.series ul { margin: 0; padding: 0; list-style: none; }
.series li { padding: 3px 0; }
.series .muted { color: var(--muted); font-size: 13px; }
/* The post screen's Stats box (nhl-game-logs docs/design-change-up-series-stats.md, section 6;
   mocks/series-stats/ ?look=a, the user's pick, the game sheet): the summary card's look with a
   little less side padding (10 px, 8 on a phone), so the table has the width at 375. */
.stats { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 10px 10px 8px; margin: 10px 0 14px; font-variant-numeric: tabular-nums; }
.stats:empty { display: none; }
.stats-head { display: flex; align-items: center; justify-content: space-between; gap: 8px; margin: 0 4px 6px; }
.stats h3 { margin: 0; font-size: 18px; }
/* the team toggle: the setup card's .seg, joined into one pill */
.stats .seg { flex: 0 1 auto; gap: 0; border: 1px solid var(--card-edge); border-radius: 10px; overflow: hidden; flex-wrap: nowrap; }
.stats .seg button { flex: 0 1 auto; min-width: 64px; max-width: 128px; padding: 5px 10px; border: 0; border-radius: 0; font: inherit; font-size: 12px; font-weight: 700; background: var(--ice); color: var(--text); overflow: hidden; text-overflow: ellipsis; }
.stats .seg button.on { background: var(--accent); color: #fff; }
/* The tables: the name takes what the numbers leave; a tap on a head sorts the column (the
   sorted head in the accent), a tap on a row opens its extras under it. */
.stats-t { width: 100%; border-collapse: collapse; font-size: 12px; line-height: 1.25; }
.stats-t + .stats-t { margin-top: 10px; }
.stats-t th { font-size: 10px; font-weight: 700; letter-spacing: .4px; text-transform: uppercase; color: var(--muted); padding: 4px 2px 5px; text-align: center; white-space: nowrap; border-bottom: 1px solid var(--card-edge); }
.stats-t th[data-sort], .stats-t tr[data-row] { cursor: pointer; user-select: none; -webkit-user-select: none; }
.stats-t th.sorted { color: var(--accent); }
.stats-t td { padding: 5px 2px; text-align: center; white-space: nowrap; border-bottom: 1px solid var(--card-edge); }
.stats-t tr.odd td { background: rgba(120, 150, 180, .10); }
.stats-t th.nm, .stats-t td.nm { text-align: left; max-width: 0; width: 100%; overflow: hidden; text-overflow: ellipsis; padding-left: 4px; }
.stats-t td.num { color: var(--muted); font-size: 11px; }
.stats-t td.pos { color: var(--muted); font-size: 11px; }
.stats-t td.p { font-weight: 800; }
.stats-t td.sub-in::before { content: "✚ "; color: var(--danger); font-size: 10px; }   /* not .sub: the page's sub-line panel */
.stats-t tr.total td { font-weight: 700; border-bottom: 0; border-top: 1px solid var(--card-edge); background: none; }
/* the extras under a tapped row: GWG, PPG, SHG, the big hits, S%, GP; a goalie's GSAx, big saves, posts, shutouts, minutes */
.stats-t tr.more td { text-align: left; font-size: 11px; color: var(--muted); padding: 0 4px 6px 12px; background: none; white-space: normal; }
.stats-t tr.more td b { color: var(--text); font-weight: 700; }
.stats .full { display: none; }
@media (min-width: 600px) { .stats .full { display: inline; } .stats .short { display: none; } }
@media (max-width: 420px) { .stats-t { font-size: 11px; } .stats-t td { padding: 5px 1px; } .stats-t th { padding: 4px 1px 5px; letter-spacing: .2px; } .stats { padding: 10px 8px 8px; } }
/* The post screen's HockeyDex box (nhl-game-logs docs/design-change-up-match-finds.md,
   section 6; mocks/match-finds/ ?look=c, the user's pick): the summary card's look; the men
   found this match as lineup chips four across; past four rows the grid scrolls, its height
   four rows, four gaps and a third of a fifth row, so the cut row says there is more. */
.finds { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 10px 14px; margin: 10px 0 14px; font-variant-numeric: tabular-nums; }
.finds h3 { margin: 0 0 2px; font-size: 18px; }
.finds > p.muted { margin: 0 0 8px; color: var(--muted); font-size: 13px; }
.find-grid { --row: 70px; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 6px; }
.find-grid.scroll { max-height: calc(4 * var(--row) + 4 * 6px + 20px); overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
/* a tile: the chip (its colours inline, app.js chipStyle) with the 2× bust where the slot is */
.find { display: grid; justify-items: center; align-content: start; gap: 1px; padding: 3px 2px 2px; min-width: 0; cursor: pointer; position: relative; font: inherit; line-height: 1.15; -webkit-tap-highlight-color: transparent; }
.find.chip { flex: none; max-width: none; }
.find .avatar { background: rgba(255, 255, 255, .18); }
.find.chip .cn { max-width: 100%; height: 14px; line-height: 14px; }
.find.on { outline: 2px solid var(--accent); outline-offset: 1px; }
.find .dex-mark-px { position: absolute; top: 2px; right: 2px; }
/* the detail: the dex page's card on this page (the dex page scopes its bio under .dex .profile-card) */
.find-detail { margin-top: 10px; border-top: 1px solid var(--card-edge); }
.find-detail .dex-card { border-bottom: 0; padding-bottom: 4px; }
.find-detail .dex-bio p { margin: 0; }
.find-detail .dex-bio p.dex-card-name { font-size: 18px; font-weight: 900; }
.find-detail .dex-open { margin: 2px 0 0; }
.find-detail .dex-open .link { padding-left: 0; }
@media (max-width: 420px) { .mode { padding: 10px 8px; } .mode strong { font-size: 14px; white-space: nowrap; } .mode small { font-size: 11px; } }

/* Team mode: the series playback */
.sboard { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 8px; background: var(--puck); color: var(--puck-text);
  border-radius: 14px; padding: 10px 12px; margin-bottom: 8px; font-variant-numeric: tabular-nums; }
.sside { display: flex; flex-direction: column; min-width: 0; }
.sside.s1 { text-align: right; }
.sside .sn { font-weight: 700; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sside .sscore { font-size: 40px; font-weight: 900; line-height: 1; }
.sside .sshots { font-size: 11px; opacity: .75; }
/* A count that went up: a green chip lights behind it and fades (PACE.tickMs;
   the user's pick of five, mocks/scoreboard-glow/, look 3). */
.sshots .st { display: inline-block; padding: 0 2px; border-radius: 3px; --tick: #2fdc6a; }
.sshots .st.up { animation: chip-tick .9s ease-out; }
@keyframes chip-tick {
  0%, 30% { background: var(--tick); color: #04160b; box-shadow: 0 0 10px var(--tick); }
  100% { background: transparent; box-shadow: 0 0 0 transparent; }
}
.sside.s0 .sn { border-bottom: 3px solid var(--blue); } .sside.s1 .sn { border-bottom: 3px solid var(--red); }
.sside .sn, .sside.s1 .sn { padding-bottom: 2px; margin-bottom: 2px; }
.sside.scored .sscore { animation: pop .5s ease-out; }
.smid { text-align: center; display: flex; flex-direction: column; align-items: center; gap: 1px; }
.smid .sgame { font-size: 11px; text-transform: uppercase; letter-spacing: .6px; opacity: .75; }
.smid .sclock { font-size: 26px; font-weight: 800; line-height: 1; min-height: 26px; }
.smid .speriod { font-size: 12px; font-weight: 700; }
.smid .sdots { font-size: 12px; letter-spacing: 3px; }
.sdots .d0 { color: var(--blue); } .sdots .d1 { color: var(--red); }
.lineups.dim .chip { opacity: .6; }
.lineups.dim .chip.lit, .lineups.dim .chip.flipped { opacity: 1; }
/* The event line sits over centre ice, where the circle and the red line
   ran through the words (user, 2026-10-07): it gets its own sheet of plain
   ice — frosted, so the rink still shows at the edges — and a bigger,
   bolder, glowing line. */
.ice {
  min-height: 96px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 4px;
  padding: 12px 14px; margin: 4px 0 8px; text-align: center;
  background: var(--overlay); border: 1px solid var(--card-edge); border-radius: 16px;
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
.ice.shake { animation: shake .4s; }
.event-line {
  font-size: 24px; font-weight: 800; line-height: 1.2; letter-spacing: -.2px;
  text-shadow: 0 0 10px var(--ice), 0 0 18px var(--ice), 0 1px 0 var(--card);
}
.event-line b { font-weight: 900; text-shadow: 0 0 10px var(--ice), 0 0 2px currentColor; }
@media (max-width: 420px) { .event-line { font-size: 21px; } }
.event-line b.s0 { color: var(--blue); } .event-line b.s1 { color: var(--red); }
.event-line.enter { animation: pass-in .35s cubic-bezier(.2,.9,.3,1.1) both; }
.event-detail { font-size: 13px; color: var(--muted); min-height: 18px; }
#s-callout { top: 46vh; }
/* On a phone the series shout keeps its one line (T7: GIGANTIC SAVE! is the
   longest): a fixed box at left: 50% only gets the right half of the screen
   to shrink-wrap into, so every shout but GOAL! broke in two. Its own width,
   up to the 90vw above. At every width since the sayings (design 5c): the
   box takes the wider of the shout and the saying under it, instead of
   wrapping a long saying under a short shout. The name game's shout had the
   same half-screen box (TOO / MANY / MEN! at 375 px, the 2026-10-14 review,
   #12) and takes the same cure. */
#callout, #s-callout { width: max-content; }
.callout.s0 { color: var(--blue); } .callout.s1 { color: var(--red); } .callout.neutral { color: var(--text); }
.ticker { list-style: none; margin: 0 0 10px; padding: 6px 10px; background: var(--card); border: 1px solid var(--card-edge); border-radius: 12px; min-height: 120px; font-size: 12.5px; }
.ticker li { padding: 2px 0; display: flex; gap: 8px; color: var(--muted); }
.ticker li:first-child { color: var(--text); }
.ticker .tc { flex: 0 0 auto; font-variant-numeric: tabular-nums; opacity: .7; min-width: 44px; }
.ticker li.big { font-weight: 700; }
.controls { display: flex; gap: 8px; }
.controls button { flex: 1; padding: 12px; border: 1px solid var(--card-edge); border-radius: 12px; background: var(--card); font-weight: 800; cursor: pointer; }
.controls button.on { background: var(--accent); color: #fff; border-color: var(--accent); }
/* The pause and the review (nhl-game-logs docs/design-change-up-replay.md,
   section 5): ⏸ Pause first in .controls; paused, the review row slides in
   under the ice — ⏮, the slider over the series so far (a tick at each
   game's start, drawn as --ticks by app.js), ⏭, the scrubbed time — and the
   ice takes a drag (no page scroll under the finger). */
.controls button:disabled { opacity: .45; cursor: default; }
#s-review { display: flex; align-items: center; gap: 6px; margin: -2px 0 8px; animation: review-in .2s ease-out both; }
#s-review[hidden] { display: none; }
@keyframes review-in { from { transform: translateY(-6px); opacity: 0; } to { transform: none; opacity: 1; } }
#s-review button { flex: 0 0 auto; min-width: 44px; height: 44px; padding: 0 8px; border: 1px solid var(--card-edge); border-radius: 12px; background: var(--card); color: var(--text); font-size: 15px; cursor: pointer; }
/* Snap (T9, the replay design section 6): a word among the icons, bold. On a
   phone the time folds onto two or three short lines beside it, so the row
   keeps one line and the slider its room (the scoreboard reads the same
   clock above). */
#s-review #s-snap { font-weight: 800; font-size: 14px; }
#s-review .rt { flex: 0 0 auto; font-size: 12px; font-weight: 700; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
@media (max-width: 420px) { #s-review .rt { white-space: normal; width: 64px; line-height: 1.15; } }
/* The slider: 44 px tall to the touch, the thumb well inside it. */
#s-review input[type="range"] { flex: 1 1 auto; min-width: 72px; height: 44px; margin: 0; padding: 0; cursor: pointer; touch-action: none;
  -webkit-appearance: none; appearance: none; background: var(--ticks, none) transparent; }
#s-review input[type="range"]::-webkit-slider-runnable-track { height: 6px; border-radius: 3px; background: var(--card-edge); }
#s-review input[type="range"]::-moz-range-track { height: 6px; border-radius: 3px; background: var(--card-edge); }
#s-review input[type="range"]::-webkit-slider-thumb { -webkit-appearance: none; appearance: none; width: 24px; height: 24px; margin-top: -9px; border-radius: 50%;
  background: var(--accent); border: 3px solid var(--card); box-shadow: 0 1px 4px rgba(0, 0, 0, .35); }
#s-review input[type="range"]::-moz-range-thumb { width: 18px; height: 18px; border-radius: 50%; background: var(--accent); border: 3px solid var(--card); box-shadow: 0 1px 4px rgba(0, 0, 0, .35); }
#s-review input[type="range"]:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
body.review .ice { cursor: ew-resize; touch-action: none; user-select: none; -webkit-user-select: none; outline: 2px solid var(--accent); outline-offset: -5px; }
/* PAUSED under the clock while the review is open. */
.smid .spaused { font-size: 9px; font-weight: 800; letter-spacing: 1.5px; text-transform: uppercase; opacity: .75; }
/* ul.stars: the game's three stars; canvas.stars is a badge's star strip. */
.series ul.stars { margin: 8px 0 0; padding: 0; list-style: none; }
/* First star one star, second two, third three (user, 2026-10-07). */
/* The star's bust first, then his stars, then his line (user, 2026-10-27). */
.series ul.stars li { display: flex; align-items: center; gap: 8px; margin: 4px 0; }
.series ul.stars li .avatar { order: -1; }
.series ul.stars li::before { content: "★"; color: var(--amber); white-space: nowrap; }
.series ul.stars li:nth-child(2)::before { content: "★★"; }
.series ul.stars li:nth-child(3)::before { content: "★★★"; }

/* Post-game */
.result { font-size: 34px; font-weight: 900; text-align: center; margin: 24px 0 4px; }
.result .nb { white-space: nowrap; }
/* A phone: the winner, then "wins the series 2–1" whole on its own line; a
   game's star on a line of its own, his name unbroken. */
@media (max-width: 420px) {
  .result .rl { display: block; }
  .series .gsep { display: none; } .series .gstar { display: block; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
}
/* The line under the result ("Name game: … · 20 names in the chain") sits on
   the rink's lines and circle: the same frosted sheet as the series' event
   line (user, 2026-10-07). Empty, it takes no room. */
.sub {
  text-align: center; color: var(--text); margin: 0 0 16px; padding: 8px 12px; font-size: 14px; line-height: 1.4;
  background: var(--overlay); border: 1px solid var(--card-edge); border-radius: 12px;
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
}
.sub:empty { display: none; }
.chain-list { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 8px 8px 8px 36px; margin: 0 0 14px; max-height: 50vh; overflow: auto; }
.chain-list li { padding: 6px 4px; border-bottom: 1px solid var(--card-edge); display: flex; justify-content: space-between; gap: 8px; font-variant-numeric: tabular-nums; }
.chain-list li:last-child { border-bottom: 0; }
.chain-list .who { color: var(--muted); font-size: 12px; }
.chain-list .t { color: var(--muted); font-size: 13px; white-space: nowrap; }
.chain-list li.fault { color: var(--danger); }
.actions { display: grid; gap: 8px; justify-items: center; }

/* Online play (the online design, step 1): the home card, the lobby, the room screen. */
.online-card { background: var(--card); border: 1px solid var(--card-edge); border-radius: 14px; padding: 14px; margin-top: 14px; display: grid; gap: 10px; }
.online-card p { margin: 0; color: var(--muted); font-size: 13px; }
.online-card p strong { color: var(--text); font-size: 15px; }
.room { text-align: center; padding: 24px 12px; display: grid; gap: 10px; justify-items: center; }
.room-code { font-size: 44px; font-weight: 900; letter-spacing: 6px; }
.room-link { color: var(--muted); font-size: 13px; margin: 0; overflow-wrap: anywhere; }
.room-seats { list-style: none; padding: 0; margin: 6px 0; display: grid; gap: 6px; font-weight: 700; }
.room-seats li::before { content: "● "; color: var(--ok); font-size: 11px; vertical-align: middle; }
.room-seats li.off::before { color: var(--amber); }
.room-seats li.empty { color: var(--muted); font-weight: 400; }
.room-seats li.empty::before { color: var(--card-edge); }
.online-note { text-align: center; color: var(--amber); font-weight: 600; margin-top: 6px; }
#online-invite .pass-letter { margin: 0 0 10px; }

@media (prefers-reduced-motion: reduce) {
  .name-card.enter, .callout, .callout .wow, .callout .say, .puck .letter.pop, .puck .letter.drop, .answer.shake, .chip.lit, .chip.chem-team, .chip.chem-history, .chip.chem-country, .chip.flipping, .flag.on,
  .chip:is(.chem-history, .chem-team, .chem-country)::before, .chip:is(.chem-history, .chem-team, .chem-country):not(.in)::after,
  .event-line.enter, .ice.shake, .sside.scored .sscore, #s-review { animation: none; }
}

/* Achievements: the crests are 24 × 24 canvases (web/badges.js), shown at 2× and 3× */
.badge { image-rendering: pixelated; image-rendering: crisp-edges; display: block; flex: none; }
.badge-m { width: 48px; height: 48px; }
.badge-l { width: 72px; height: 72px; }
.case { margin: 14px 0 0; text-align: center; }
.case-head { color: var(--muted); font-size: 13px; margin: 0 0 8px; }
.case-head strong { color: var(--text); }
/* The star strip (17 × 5, web/badges.js) under a crest, in whole pixels:
   ×3 under a 2× crest, ×4 under a 3× one. A crest and its strip are a
   column (.crest), the strip centred under the shield. */
canvas.stars { image-rendering: pixelated; image-rendering: crisp-edges; display: block; flex: none; width: 51px; height: 15px; }
.badge-l + canvas.stars { width: 68px; height: 20px; }
.crest { display: inline-flex; flex-direction: column; align-items: center; gap: 3px; flex: none; }
/* The columns are the strip's width (51 px; the 2× crest is 48): six a row
   still fit a 375 px phone. */
.case-grid { display: grid; grid-template-columns: repeat(6, 51px); gap: 8px 10px; justify-content: center; }
.case-b { background: none; border: 0; padding: 0; cursor: pointer; border-radius: 6px; display: flex; justify-content: center; }
.case-b.on, .case-b:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }
.case-detail { font-size: 13px; margin: 10px auto 0; max-width: 420px; }
.unlock { display: grid; justify-items: center; gap: 4px; margin: 6px 0 10px; }
.unlock .crest { margin-bottom: 6px; animation: badge-in .5s cubic-bezier(.2,.9,.3,1.3) both; }
@keyframes badge-in { from { transform: scale(.2) rotate(-12deg); opacity: 0; } to { transform: none; opacity: 1; } }
.unlock-title { color: var(--amber); font-size: 13px; font-weight: 900; letter-spacing: 1px; }
.unlock-name { font-size: 24px; font-weight: 900; }
.unlock-desc, .unlock-who { color: var(--muted); font-size: 13px; }
/* the HockeyDex ladder's cards: the strip at 2×, a letter's gold star at 3× */
.unlock canvas.ladder, .unlock canvas.star { margin: 4px 0 8px; }
.unlock + .unlock { margin-top: 14px; }
.earned { list-style: none; padding: 0; margin: 10px 0; display: grid; gap: 6px; justify-content: center; }
.earned li { display: flex; align-items: center; gap: 10px; text-align: left; }
@media (max-width: 420px) { .case-grid { gap: 6px 4px; } }
@media (prefers-reduced-motion: reduce) { .unlock .crest { animation: none; } }

/* Profiles (nhl-game-logs docs/design-change-up-profiles.md, section 7): the
   home screen's two lines and the profile page. */
.profile-note { color: var(--muted); font-size: 12px; margin: 6px 0 0; }
.profile-note.warn { color: var(--danger); }   /* sync.js's word on this device: forked (S2), no /api (S4) */
.foot-note { color: var(--muted); font-size: 12px; text-align: center; margin: 8px 0 0; }
a.link { display: inline-block; }
.profile .profile-back { margin: 0 0 12px; text-align: center; }
.profile .profile-card { margin-bottom: 12px; gap: 8px; }
.profile .profile-card h2 { font-size: 13px; font-weight: 800; text-transform: uppercase; letter-spacing: .6px; margin: 0; color: var(--muted); }
.profile .profile-card p { margin: 0; }
.profile .muted { color: var(--muted); font-size: 13px; }
.profile-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.profile-list.plain { list-style: disc; padding-left: 20px; gap: 4px; font-size: 14px; }
.profile-list li .link { padding-left: 0; }
.profile-actions { display: flex; gap: 14px; flex-wrap: wrap; }
/* About and privacy (nhl-game-logs docs/design-change-up-android.md, 6e): one card, the notice then the privacy text */
.about .about-part { display: grid; gap: 8px; }
.about .about-part + .about-part { margin-top: 10px; }
.about .about-part p { font-size: 14px; line-height: 1.45; }
.tag-here { font-size: 11px; font-weight: 700; color: var(--ok); text-transform: uppercase; letter-spacing: .5px; }
/* Step 2: sign-in. The Google link drawn as a button (a plain anchor: no
   Google script), the recovery code shown once, the page's one-line notices. */
a.go { display: block; text-align: center; text-decoration: none; box-sizing: border-box; }
.go.quiet { background: var(--ice); color: var(--text); border: 1px solid var(--card-edge); font-size: 15px; padding: 11px; }
.profile-flash { border: 1px solid var(--card-edge); border-left: 4px solid var(--ok); border-radius: 10px; padding: 10px 12px; background: var(--card); margin: 0 0 12px; font-size: 14px; }
.profile-flash.bad { border-left-color: var(--danger); }
.recovery-show { border: 2px dashed var(--accent); border-radius: 12px; padding: 12px; display: grid; gap: 10px; }
.recovery-code { font: 700 22px/1.3 ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; text-align: center; word-break: break-word; user-select: all; }
.recovery-warn { font-weight: 700; font-size: 14px; }
.profile-row { display: flex; gap: 8px; }
.profile-row input[type=text] { flex: 1; min-width: 0; }
.profile-row .go { width: auto; font-size: 15px; padding: 10px 14px; }
.profile-toggle { display: flex; align-items: center; gap: 10px; font-weight: 600; cursor: pointer; }
.profile-toggle input { width: 20px; height: 20px; margin: 0; }
/* Step 4: the handle and delete cards, the standings page's table. */
.go.danger { background: var(--danger); color: #fff; }
.standings-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; margin: 0 -4px; }
.standings-table { border-collapse: collapse; width: 100%; font-size: 13px; min-width: 520px; }
.standings-table th, .standings-table td { padding: 6px 6px; text-align: left; border-bottom: 1px solid var(--card-edge); white-space: nowrap; }
.standings-table th { font-size: 11px; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); font-weight: 800; }
.standings-table .num { text-align: right; font-variant-numeric: tabular-nums; }
.standings-table td.handle { font-weight: 700; }
/* the picture at 1× before the handle (nhl-game-logs docs/design-change-up-standings-pictures.md, D3): 16 px in the 29 px row */
.standings-table td.handle .who { display: inline-flex; align-items: center; gap: 6px; vertical-align: middle; }
.standings-table tr.me td { background: var(--ice); }
.standings-table tr.lit td, #me-line.lit { outline: 2px solid var(--accent); outline-offset: -2px; }
.standings-flag { color: var(--accent); font-size: 12px; }
.standings .profile-card p + .standings-scroll { margin-top: 4px; }
.standings-body { display: grid; gap: 8px; }

/* The HockeyDex page (nhl-game-logs docs/design-change-up-hockeydex.md,
   section 8; M1's mocks/hockeydex/dex.css with R1's changes). The pixel
   skin's rules are in pixel.css. */
.screen.dex { max-width: 760px; }
/* the head: the crest beside the counter, the bar under it */
.dex-top { display: flex; gap: 14px; align-items: center; min-width: 0; }
.dex-crest { margin: 0; display: flex; flex-direction: column; align-items: center; gap: 4px; text-align: center; flex: none; }
.dex-crest figcaption { font-size: 13px; }
.dex-count { flex: 1; min-width: 0; display: grid; gap: 6px; }
.dex-n { margin: 0; font-size: 18px; font-variant-numeric: tabular-nums; }
.dex-n strong { font-size: 30px; font-weight: 900; color: var(--accent); }
.dex-n-label { color: var(--muted); font-size: 14px; }
.dex .nb { white-space: nowrap; }
.dex-bar { height: 12px; border-radius: 6px; background: var(--ice); border: 1px solid var(--card-edge); overflow: hidden; }
.dex-bar span { display: block; height: 100%; min-width: 2px; background: var(--ok); }
.dex-search { width: 100%; padding: 10px 12px; border: 1px solid var(--card-edge); border-radius: 10px; background: var(--ice); color: var(--text); font: inherit; }
/* the letter strip: 26 tabs, found / total under each, a fill along the foot */
.dex-strip { display: grid; grid-template-columns: repeat(auto-fill, minmax(46px, 1fr)); gap: 4px; }
.dex-tab { position: relative; display: grid; justify-items: center; gap: 0; padding: 4px 2px 6px; border: 1px solid var(--card-edge); border-radius: 8px; background: var(--ice); color: var(--text); cursor: pointer; overflow: hidden; min-width: 0; font: inherit; }
.dex-tab b { font-size: 16px; font-weight: 900; line-height: 1.1; }
.dex-tab small { font-size: 9px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.dex-tab i { position: absolute; left: 0; bottom: 0; height: 3px; background: var(--ok); }
.dex-tab.on { background: var(--accent); border-color: var(--accent); color: #fff; }
.dex-tab.on small { color: #fff; }
.dex-tab.on i { background: #fff; }
.dex-tab.none b { color: var(--muted); }
/* the ladder (nhl-game-logs docs/design-change-up-dex-ladder.md, sections 7
   and 8): the strip of twenty stars (127 × 5, web/badges.js) in whole pixels,
   2× under 600 px and 3× above on the page, a fixed scale on a card; the gold
   star of a letter whose men are all found, in its tab's top-right corner,
   the tab's fill gold */
canvas.ladder, canvas.star { image-rendering: pixelated; image-rendering: crisp-edges; display: block; flex: none; }
canvas.ladder, canvas.ladder.x2 { width: 254px; height: 10px; }
canvas.ladder.x3 { width: 381px; height: 15px; }
@media (min-width: 600px) { canvas.ladder:not(.x2) { width: 381px; height: 15px; } }
canvas.star.x2 { width: 10px; height: 10px; }
canvas.star.x3 { width: 15px; height: 15px; }
.dex-ladder { display: grid; gap: 4px; min-width: 0; }
.dex .profile-card p.dex-ladder-line { font-size: 13px; line-height: 1.35; }
.dex-tab .dex-mark { position: absolute; top: 2px; right: 2px; line-height: 0; }
.dex-tab.done i { background: #e8b923; }
.dex-tab.done.on i { background: #ffe37a; }
.dex .profile-card h2.dex-letter, .dex .profile-card h2.dex-open-head { margin: 4px 0 0; font-size: 15px; color: var(--text); text-transform: none; letter-spacing: 0; }
/* the names: chips, found / total, greyed at 0 (still buttons) */
.dex-names { display: flex; flex-wrap: wrap; gap: 5px; }
.dex-chip { border: 1px solid var(--accent); border-radius: 999px; background: var(--card); padding: 3px 9px; font: inherit; font-size: 13px; font-weight: 700; cursor: pointer; color: var(--text); }
.dex-chip span { font-weight: 400; font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
.dex-chip.zero { border-color: var(--card-edge); color: var(--muted); font-weight: 600; }
.dex-chip.on { background: var(--accent); color: #fff; border-color: var(--accent); }
.dex-chip.on span { color: #fff; }
/* the open name: the found men, then one line for the rest (R1) */
.dex-rows { display: grid; gap: 2px; }
.dex-row { min-width: 0; padding: 4px 2px; border-bottom: 1px solid var(--ice-line); font-size: 14px; }
/* the unfound man (nhl-game-logs docs/design-change-up-letters.md, D9; the
   pick B of mocks/letters/, the hangman slots): the first name, then a slot a
   letter — a revealed one (.dex-lit) standing on its line in the accent, a
   hidden one (.dex-q: a button while the bank holds a letter, a span at 0) a
   faint ? on an empty line, punctuation (.dex-punct) as it is. A `?` button
   is 18 × 28 px to tap, its line drawn 15 px wide as M1 drew it; the pill
   under a row with armed letters (D8) */
.dex-row.locked { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; color: var(--muted); }
.dex-row.locked .dex-first { font-weight: 600; white-space: nowrap; }
.dex-row.locked .dex-slots { display: inline-flex; align-items: center; gap: 3px; flex-wrap: wrap; }
.dex-q, .dex-lit, .dex-punct { display: inline-grid; place-items: center; box-sizing: border-box; font: inherit; line-height: 1; }
.dex-q, .dex-lit { position: relative; width: 18px; height: 28px; border: 0; border-radius: 0; background: none; padding: 0; font-weight: 800; font-size: 15px; }
.dex-q::after, .dex-lit::after { content: ''; position: absolute; left: 1px; right: 2px; bottom: 0; height: 2px; background: var(--muted); }
.dex-q { color: color-mix(in srgb, var(--muted) 45%, transparent); }
button.dex-q { cursor: pointer; }
button.dex-q:hover { color: var(--accent); }
button.dex-q:hover::after { background: var(--accent); }
button.dex-q:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.dex-q.armed, button.dex-q.armed:hover { color: #101418; background: var(--amber); }
.dex-q.armed::after { background: #101418; }
.dex-lit { color: var(--accent); }
.dex-lit::after { background: var(--accent); }
.dex-punct { width: 8px; height: 28px; color: var(--muted); }
.dex-meta.dex-hint { flex: 1 1 100%; white-space: normal; color: var(--ok); font-weight: 600; }
.dex .profile-card p.dex-reveal { display: flex; align-items: center; gap: 8px; flex: 1 1 100%; margin: 2px 0 4px 2px; font-size: 14px; color: var(--text); }
.dex-reveal .go { width: auto; padding: 6px 12px; font-size: 14px; }
.dex-reveal .go.quiet { padding: 5px 12px; }
.dex-partly { margin-top: 2px; }
/* the In progress card (D10): a row a man, a link to his place; the slots smaller (every row on one line) */
.dex-progress .dex-row.progress { text-decoration: none; cursor: pointer; }
.dex-progress .dex-row.progress .dex-chev { margin-left: auto; color: var(--accent); font-size: 20px; line-height: 1; }
.dex-progress .dex-row.progress:hover .dex-first { color: var(--accent); }
.dex-progress .dex-row.progress:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.dex-progress .dex-q, .dex-progress .dex-lit { width: 12px; height: 20px; font-size: 13px; }
.dex-progress .dex-q::after, .dex-progress .dex-lit::after { left: 0; right: 1px; }
.dex-progress .dex-punct { height: 20px; }
/* the bank's line (D11): the pixel magnifier (web/badges.js MARKS) at 2× before the words */
.dex .profile-card p.dex-bank { display: flex; align-items: center; gap: 6px; }
canvas.dex-mark-px { width: 18px; height: 22px; image-rendering: pixelated; image-rendering: crisp-edges; display: block; flex: none; }
.dex-row.found { display: flex; align-items: center; gap: 8px; cursor: pointer; flex-wrap: wrap; }
.dex-row.found:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
.dex-row.found.open { background: color-mix(in srgb, var(--accent) 10%, transparent); }
.dex-name { border: 2px solid; border-radius: 6px; padding: 1px 7px; font-weight: 800; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 100%; }
.dex-meta { color: var(--muted); font-size: 13px; white-space: nowrap; }
.dex .profile-card p.dex-more { margin: 6px 0 0; color: var(--muted); font-size: 14px; }
.dex-more .link { padding: 0 4px; font-size: 14px; }
.dex-locked { margin-top: 2px; }
/* the portrait box: the band at 20 % behind the bust; the canvas in the
   pixel skin, the monogram in classic (section 9) */
.dex-pic { flex: none; display: inline-grid; place-items: center; background: color-mix(in srgb, var(--band) 20%, transparent); border-radius: 6px; }
.dex-pic.s2 { width: 56px; height: 32px; }
.dex-pic.s4 { width: 112px; height: 64px; }
canvas.dex-portrait { image-rendering: pixelated; image-rendering: crisp-edges; display: block; }
.dex-mono { display: grid; place-items: center; width: 100%; height: 100%; border-radius: 6px; border-bottom: 4px solid; font-weight: 900; letter-spacing: .5px; }
.dex-pic.s2 .dex-mono { font-size: 14px; }
.dex-pic.s4 .dex-mono { font-size: 28px; border-bottom-width: 6px; }
:root:not([data-skin="pixel"]) canvas.dex-portrait { display: none; }
/* the detail card under its row: the portrait and the card's numbers side by
   side (R1; they wrap under each other only when the row cannot hold both),
   the bio under them */
.dex-card { display: flex; gap: 10px 14px; align-items: center; padding: 10px 6px 12px; border-bottom: 1px solid var(--card-edge); flex-wrap: wrap; }
.dex-bio { flex: 1 1 100%; min-width: 0; display: grid; gap: 2px; font-size: 13px; font-variant-numeric: tabular-nums; }
.dex .profile-card .dex-bio p { margin: 0; }
.dex .profile-card .dex-bio p.dex-card-name { font-size: 18px; font-weight: 900; }
/* the lineup card's back, as a flipped chip: its own .cb and .ca rules */
.chip.dex-back { flex: none; max-width: none; width: max-content; padding: 0; border-color: #101418; background: #101418; }
.chip.dex-back .cf { display: none; }
.chip.dex-back .cb { position: static; transform: none; min-height: 0; }
.dex-card[data-kind="goalie"] .chip.dex-back .cb { min-width: 96px; padding: 4px 6px; }
.dex-caret { font-family: system-ui, sans-serif; }
.dex .profile-card.dex-results h2 { margin: 0; }
@media (max-width: 420px) {
  .dex-top { gap: 10px; }
  .dex-n strong { font-size: 24px; }
}
/* the standings page's HockeyDex list (hockeydex design, D12) */
.standings-table.dex-table { min-width: 0; }
/* The two tables that fit a phone without a sideways scroll (the dex list,
   an open badge's holders) ran 14–17 px past a 360 px screen once each row
   carried its picture (the standings pictures design, R1): 3 px of side
   padding under 420 px takes 30 px back (the pixel skin's wider digits need
   it at 360); the row's height is untouched. */
@media (max-width: 419px) {
  .standings-table.dex-table th, .standings-table.dex-table td,
  .standings-table.badge-holders th, .standings-table.badge-holders td { padding-left: 3px; padding-right: 3px; }
}
#dex-me-line.lit { outline: 2px solid var(--accent); outline-offset: -2px; }
.standings-dex { font-size: 12px; }
/* the ladder's stars lit after a handle (the ladder design, D10) */
.standings-stars { font-size: 12px; font-weight: 800; color: var(--amber); white-space: nowrap; }

/* The standings page's Badges list (nhl-game-logs
   docs/design-change-up-badge-standings.md, section 9; M1's
   mocks/standings/badges.css, look (b)). The chips are a filter, small and
   outlined, the one on ringed; the tabs are the HockeyDex's .dex-tab, filled
   when open: a view. */
.standings-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 5px; }
.chips-label { flex-basis: 100%; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.standings-chip { font: inherit; font-size: 12px; font-weight: 700; line-height: 1.2; padding: 4px 7px; border: 1px solid var(--card-edge); border-radius: 999px; background: var(--card); color: var(--text); cursor: pointer; }
.standings-chip.on { border-color: var(--accent); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.standings-chip:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.standings-tabs { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.standings-tabs .dex-tab { padding: 6px 4px 7px; }
/* the by-player table: as the board, a little narrower; its panel is a grid
   item of the card, told it may shrink, so the table's own box scrolls */
.standings-table.badge-table { min-width: 470px; }
#badge-card > [role="tabpanel"] { min-width: 0; }
#badge-me-line.lit { outline: 2px solid var(--accent); outline-offset: -2px; }
/* The Online board and Rivalries (nhl-game-logs
   docs/design-change-up-online-standings.md, D7, D8): the board's 520 px floor,
   which fits the 535 px box of a desktop card and scrolls in its box on a phone;
   the pair table fits a phone or scrolls too. A tab's small line (a count that
   grows) wraps rather than being clipped at 360 px. The sub-heading is the table
   head's look, the body's 8 px gap made 12 above and 4 below. */
#board-tabs .dex-tab small { white-space: normal; }
.standings-table.pairs-table { min-width: 0; }
.standings-sub { margin: 4px 0 -4px; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.pair-v { margin: 0 2px; font-weight: 400; color: var(--muted); }
#online-me-line.lit { outline: 2px solid var(--accent); outline-offset: -2px; }
/* the grid: the case's (.case-grid, .case-b), five a row — the fifteen open
   badges in three rows, inside a pixel card at 375 — the detail under it */
.case-grid.badge-grid { grid-template-columns: repeat(5, 51px); gap: 10px 16px; margin-top: 2px; }
.profile .profile-card .badge-sep { margin: 12px 0 0; font-size: 11px; font-weight: 800; text-transform: uppercase; letter-spacing: .5px; color: var(--muted); }
.badge-detail { display: grid; gap: 8px; border-top: 1px solid var(--card-edge); padding-top: 12px; margin-top: 4px; }
.badge-detail-head { display: flex; gap: 14px; align-items: center; }
.badge-words { display: grid; gap: 2px; min-width: 0; }
.badge-name { font-size: 16px; font-weight: 800; overflow-wrap: anywhere; }
.badge-held, .badge-desc { font-size: 12px; color: var(--muted); }
.standings-table.badge-holders { min-width: 0; font-size: 12px; }
.badge-holders th, .badge-holders td { padding: 4px 6px; }
.badge-holders td.stars-cell { padding-top: 2px; padding-bottom: 2px; }
@media (max-width: 420px) { .case-grid.badge-grid { gap: 8px 10px; } }

/* The profile picture (nhl-game-logs docs/design-change-up-avatar.md, sections
   6 and 7; the user's picks, section 16; the markup is web/avatar.js
   avatarHtml, the CSS the M1 mock's, mocks/profile-pic/index.html). The box:
   the bust on its team's band at 20 % (the dex-pic's backing) at 2×, 3× or
   4×; both skins draw the bust (D5), the classic one in a rounded frame. */
.avatar { display: inline-grid; place-items: center; flex: none; position: relative; background: color-mix(in srgb, var(--band, #1c5fb8) 20%, transparent); border-radius: 8px; }
.avatar.s1 { width: 28px; height: 16px; border-radius: 4px; }   /* the standings tables' rows */
.avatar.s2 { width: 56px; height: 32px; }
.avatar.s3 { width: 84px; height: 48px; }
.avatar.s4 { width: 112px; height: 64px; }
.avatar canvas { image-rendering: pixelated; image-rendering: crisp-edges; display: block; }
/* a picture not painted yet (the pool still on its way) is the box's size, not a canvas's
   default 300 × 150 lying over the home's buttons and the standings rows (code review 2026-10-29 #4) */
.avatar canvas:not([data-painted]):not(.pin) { width: 100%; height: 100%; }
/* the badge pinned on the picture (nhl-game-logs docs/design-change-up-og.md,
   D10, section 8; the user's picks, section 15): the crest at half the box's
   scale centred on the box's top-right corner, half outside — 1× at s2 and
   s3, 2× at s4; none at s1 (no room at 28 × 16). On the 2× boxes an OG pin is
   the O G pill instead, 14 × 9 at 1×, inside the corner, two pixels in. */
.avatar .pin { position: absolute; width: 24px; height: 24px; top: -12px; right: -12px; z-index: 1; }
.avatar.s4 .pin { width: 48px; height: 48px; top: -24px; right: -24px; }
.avatar.s2 .pin.pill { width: 14px; height: 9px; top: 2px; right: 2px; }
.avatar.s1 .pin { display: none; }
/* the overhang's room: every box but the standings' sits left of words (the
   home's name band, the Picture card's name, the scoreboard's and the lobby's
   names, a room seat's), which a pin half outside would cover (W2's check at
   375); the pill inside the corner needs none */
.avatar.s4:has(> .pin) { margin-right: 20px; }
.avatar.s2:has(> .pin:not(.pill)), .avatar.s3:has(> .pin) { margin-right: 8px; }
/* the tile (the scoreboard, D the tile): a frame; whose turn it is lights it */
.avatar.tile { border: 2px solid var(--card-edge); box-sizing: content-box; }
.scoreboard .avatar.tile { border-color: #3a4552; }
.scoreboard .seat.on .avatar.tile { border-color: var(--ok); box-shadow: 0 0 8px var(--ok); }
/* the scoreboard's seats: the 2× tile beside the name (mirrored on the right), the lives under the name; the dot by the name goes */
.scoreboard .seat { flex-direction: row; align-items: center; gap: 8px; }
.scoreboard .seat.right { flex-direction: row-reverse; }
.swords { display: flex; flex-direction: column; min-width: 0; gap: 2px; }
.scoreboard .seat.on .sname::before, .scoreboard .seat.right.on .sname::after { content: none; }

/* The home block (D7; the pick D, the locker): the bust at 4× beside a name
   band in the player's team colour (the box's --primary, the text in
   --on-primary, the --band as its border); a long name wraps onto a second
   line (section 16: the sheet showed "Guest Franci…" cut at 375 in Pixel). */
.me { margin: 0 0 14px; text-align: center; }
.me-name { margin: 6px 0 0; font-size: 22px; font-weight: 900; line-height: 1.15; }
.me-sub { margin: 2px 0 0; color: var(--muted); font-size: 13px; }
.me-sub .link { padding: 0 2px; }
.me-sub .warn { color: var(--danger); }   /* sync.js's word on this device: forked (S2), no /api (S4) */
.me-locker { display: flex; align-items: center; gap: 12px; text-align: left; padding: 12px; }
.me-locker .me-name { margin: 0; }
.me-words { min-width: 0; }
.me-name.band { display: inline-block; padding: 2px 10px; border-radius: 6px; background: var(--primary, #1c5fb8); color: var(--on-primary, #fff); border: 2px solid var(--band, #1c5fb8); font-size: 20px; max-width: 100%; overflow-wrap: anywhere; }
a.me-name.band { text-decoration: none; }   /* the name is the link to the Profile page */
a.me-name.band:hover, a.me-name.band:focus-visible { text-decoration: underline; text-underline-offset: 3px; }

/* The daily streak (nhl-game-logs docs/design-change-up-streaks.md, D10, D13,
   D14; the picks, section 16; the CSS as mocks/streaks/index.html had it):
   the chip beside the name band inside .me-line — the flame at 2× (web/badges.js
   flameHtml: the two frames stacked, the flicker by opacity at 500 ms, still
   under reduced motion) and the count on a warm tint, cold on the socket grey
   — and the words as a second line under the dex line (.me-streak). */
.flame-chip { display: inline-flex; align-items: center; gap: 4px; vertical-align: middle; margin-left: 6px; padding: 2px 8px 2px 5px; border-radius: 999px; background: color-mix(in srgb, #ff7a1a 16%, transparent); font-weight: 900; font-size: 15px; color: var(--text); line-height: 1; }
.flame-chip.cold { background: color-mix(in srgb, #6b7480 16%, transparent); color: var(--muted); }
.flame-chip .flame { position: relative; display: block; width: 18px; height: 22px; }
.flame-chip.x3 .flame { width: 27px; height: 33px; }
.flame-chip canvas { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; image-rendering: crisp-edges; display: block; }
.flame-chip canvas.f2 { opacity: 0; }
.flame-chip.lit canvas.f1 { animation: flame-f1 1s steps(1, end) infinite; }
.flame-chip.lit canvas.f2 { animation: flame-f2 1s steps(1, end) infinite; }
@keyframes flame-f1 { 0%, 49% { opacity: 1; } 50%, 100% { opacity: 0; } }
@keyframes flame-f2 { 0%, 49% { opacity: 0; } 50%, 100% { opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .flame-chip canvas { animation: none !important; } .flame-chip canvas.f2 { opacity: 0; } }
.me-line { display: inline-flex; align-items: center; flex-wrap: wrap; gap: 4px 0; max-width: 100%; }
.me-streak { margin-top: 2px; }

/* The Profile page's Streak card (D14): the flame at 3×, the two lines, the
   last 28 days as a 7 × 4 grid of dots — lit for a day played, today's
   ringed, the days still to come hidden — under a fixed M T W T F S S row. */
.streak-head { display: flex; align-items: center; gap: 12px; }
.streak-head .flame-chip { margin: 0; padding: 4px 10px 4px 6px; font-size: 20px; }
.streak-now { margin: 0; font-size: 20px; font-weight: 900; }
.streak-head .muted { margin: 2px 0 0; font-size: 13px; }
.streak-grid { display: grid; grid-template-columns: repeat(7, 22px); gap: 6px 8px; justify-content: start; align-items: center; justify-items: center; }
.streak-grid .wd { font-size: 11px; font-weight: 700; color: var(--muted); }
.streak-grid .day { display: block; width: 14px; height: 14px; border-radius: 50%; background: var(--ice-line); }
.streak-grid .day.on { background: #ff7a1a; }
.streak-grid .day.today { outline: 2px solid var(--accent); outline-offset: 2px; }
.streak-grid .day.future { visibility: hidden; }
.streak-card .muted { margin: 0; font-size: 13px; color: var(--muted); }

/* The pages board: a scoreboard sheet under Play online, one page at a time
   between two yellow arrows, the dots under it saying how many. The page's
   name is underlined to say it is a link. */
.pages-board {
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: 4px;
  margin: 14px 0 0; padding: 8px 6px 6px; border-radius: 14px; overflow: hidden;
  background: var(--puck); color: var(--puck-text);
  touch-action: pan-y; /* a sideways swipe rolls the page (app.js), up and down still scrolls */
}
.pb-arrow { display: grid; place-items: center; width: 44px; height: 44px; padding: 0; border: 0; background: none; color: #ffd60a; cursor: pointer; border-radius: 8px; }
.pb-arrow svg { width: 14px; height: 26px; fill: currentColor; filter: drop-shadow(0 0 4px rgba(255, 214, 10, .55)); }
.pb-arrow:hover, .pb-arrow:focus-visible { background: rgba(255, 214, 10, .14); }
.pb-arrow:active svg { transform: scale(.9); }
.pb-page { display: flex; flex-direction: column; align-items: center; gap: 2px; min-width: 0; padding: 4px 0; color: inherit; text-decoration: none; text-align: center; }
.pb-name { font-weight: 800; font-size: 20px; letter-spacing: .5px; text-transform: uppercase; text-decoration: underline; text-decoration-thickness: 2px; text-underline-offset: 4px; }
.pb-sub { font-size: 12px; opacity: .7; }
.pb-page:hover .pb-name, .pb-page:focus-visible .pb-name { text-decoration-thickness: 4px; }
.pb-page.roll-next { animation: pb-in-next .22s ease-out; }
.pb-page.roll-prev { animation: pb-in-prev .22s ease-out; }
@keyframes pb-in-next { from { transform: translateX(40%); opacity: 0; } }
@keyframes pb-in-prev { from { transform: translateX(-40%); opacity: 0; } }
.pb-dots { grid-column: 1 / -1; display: flex; justify-content: center; gap: 6px; }
.pb-dots i { width: 6px; height: 6px; border-radius: 50%; background: currentColor; opacity: .3; }
.pb-dots i.on { background: #ffd60a; opacity: 1; }
@media (prefers-reduced-motion: reduce) { .pb-page.roll-next, .pb-page.roll-prev { animation: none; } }

/* the lobby's block: the 2× picture and the name */
.me-row { display: flex; align-items: center; gap: 10px; text-align: left; margin: 0; }
/* the room's seats with their pictures: the on/off dot moves from the row to the name */
.room-seats.pics { gap: 8px; }
.room-seats.pics li { display: flex; align-items: center; gap: 10px; justify-content: center; min-height: 36px; line-height: 1.2; }
.room-seats.pics li::before { content: none; }
.room-seats.pics li.on > span:not(.avatar)::before { content: "● "; color: var(--ok); font-size: 11px; vertical-align: middle; }
.room-seats.pics li.off > span:not(.avatar)::before { content: "● "; color: var(--amber); font-size: 11px; vertical-align: middle; }
/* the challenge's empty seat: the invitee's name, in grey (nhl-game-logs docs/design-change-up-open-rooms.md, 5b) */
.room-seats li.empty.invitee { font-style: italic; }

/* The lobby's open rooms and challenges (the open-rooms design, 5a): a row a
   room, the host's 2× picture, the handle and the rules, the age, a Join. */
#online-create-row { display: grid; gap: 8px; }
.open-rows { list-style: none; padding: 0; margin: 6px 0 0; display: grid; gap: 8px; }
.open-rows li { display: flex; align-items: center; gap: 10px; text-align: left; min-height: 36px; line-height: 1.25; }
.open-rows .open-text { flex: 1; min-width: 0; overflow-wrap: anywhere; font-size: 14px; }
.open-rows .open-ago { color: var(--muted); font-size: 12px; }
.open-rows .open-join { flex: none; }
.open-rows li.open-none { color: var(--muted); font-size: 13px; display: block; }
.online-card .online-waiting { justify-self: start; text-align: left; font-weight: 700; }

/* The Profile page's Picture card (the avatar design, section 8; the pick E,
   the last finds) and the HockeyDex's assign (section 9; the pick D, tap the
   portrait): the current picture big beside its words, the last finds as
   buttons in a grid (the one assigned outlined), the card's portrait as the
   control (a dashed outline; solid on the player assigned) and the sheet
   under the card. The markup is profile.js renderPicture and hockeydex.js,
   the CSS the M1 mock's. */
.pick-now { display: flex; gap: 12px; align-items: center; }
.pick-words { min-width: 0; }
.profile .profile-card p.pick-name { font-size: 18px; font-weight: 900; }
.picture-body { display: grid; gap: 8px; }
.pick-grid { display: grid; grid-template-columns: repeat(auto-fill, 56px); gap: 8px; justify-content: start; }
.pick { background: none; border: 0; padding: 0; cursor: pointer; border-radius: 8px; display: grid; justify-items: center; gap: 2px; font: inherit; color: var(--muted); }
.pick.on .avatar, .pick:focus-visible .avatar { outline: 3px solid var(--accent); outline-offset: 2px; }
.pick:disabled { opacity: .5; cursor: default; }
/* the badge on the picture (nhl-game-logs docs/design-change-up-og.md, D11):
   the crests held under the name at 2× (the case's size), each a button, None
   last; the pinned one outlined as the picture's find is; off without a picture */
.pin-row { display: grid; gap: 6px; }
.pin-grid { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.pin-pick { background: none; border: 0; padding: 0; cursor: pointer; border-radius: 8px; display: grid; place-items: center; min-width: 48px; min-height: 48px; font: inherit; color: var(--text); }
.pin-pick.pin-none { padding: 0 12px; border: 1px solid var(--card-edge); font-size: 14px; font-weight: 700; }
.pin-pick.on, .pin-pick:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
.pin-pick:disabled { opacity: .5; cursor: default; }
.profile .profile-card p.profile-name { font-size: 18px; }
.dex-card .dex-pic.tappable { outline: 2px dashed var(--accent); outline-offset: 3px; cursor: pointer; }
.dex-card .dex-pic.assigned { outline: 2px solid var(--ok); outline-offset: 3px; cursor: pointer; }
.dex-card .dex-pic:focus-visible { outline-style: solid; outline-color: var(--accent); }
.pic-sheet { margin: 6px 0 4px 6px; padding: 10px 12px; background: var(--card); border: 1px solid var(--card-edge); border-radius: 12px; box-shadow: 0 8px 24px rgba(0, 0, 0, .14); max-width: 300px; font-size: 14px; }
.dex .profile-card .pic-sheet p { margin: 0; }
.pic-sheet .pic-sheet-row { display: flex; gap: 8px; margin-top: 8px; }
.pic-sheet .go { width: auto; padding: 8px 14px; font-size: 14px; }
.dex .profile-flash { margin: 0 0 12px; }

/* The line change (nhl-game-logs docs/design-change-up-line-change.md, section 6; the
   user's pick A, the rows under the card; mocks/line-change/?look=a). The head: the
   step's name and its line, the clock as a small puck (the name phase's ring, the
   seconds where the letter sits). */
.lc-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin: 2px 0 10px; }
.lc-head .lc-title { font-size: 22px; font-weight: 900; letter-spacing: .2px; line-height: 1.1; }
.lc-head .lc-sub { font-size: 12px; color: var(--muted); margin-top: 3px; }
/* (the sub line's parts each unbreakable: a narrow head breaks it at its dot) */
.lc-head .lc-sub .nb { white-space: nowrap; }
.lc-head .puck { width: 64px; height: 64px; flex: 0 0 auto; }
.lc-head .puck .letter { font-size: 22px; font-weight: 900; padding-bottom: 0; }
/* One block a seat: the card, the bench under it, the seat's hint. */
.lc-seats { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
.lc-seats.two { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: 8px; }
.lc-seat { display: grid; gap: 7px; min-width: 0; align-content: start; }
.lc-seat .lineup { padding: 8px; }
/* The hint and the wait line as a strip (docs/design-change-up-line-change-polish.md, D3):
   the card's colour and edge, the name and the slots in the accent. */
.lc-seat .lc-hint, .lc-foot .lc-wait { background: var(--card); border: 1px solid var(--card-edge); border-radius: 8px; padding: 6px 10px; color: var(--text); font-size: 12px; line-height: 1.35; text-align: center; }
.lc-seat .lc-hint b { color: var(--accent); }
.lc-foot { display: grid; gap: 8px; margin-top: 12px; }
.lc-foot .lc-wait { font-size: 13px; }
/* The selection: the chosen bench man, the slots he may take lit (a dashed accent ring
   that breathes), the others dimmed while he is chosen; a man who is not where the final
   card had him keeps a small mark, so the player sees what changed. */
.chip.can { cursor: pointer; outline: 2px dashed var(--accent); outline-offset: 2px; animation: lc-can 1.4s ease-in-out infinite; }
@keyframes lc-can { 0%, 100% { outline-color: var(--accent); } 50% { outline-color: transparent; } }
.lc-seat.picking .chip.filled:not(.can), .lc-seat.picking .chip.callup { opacity: .45; }
.chip.in::after { content: "⇄"; position: absolute; top: -6px; right: -6px; width: 14px; height: 14px; border-radius: 50%; background: var(--accent); color: #fff; font-size: 9px; line-height: 14px; text-align: center; }
/* The rows: the peek's (.brow), each a button; past seven men they scroll in their box. */
.lc-bench { display: grid; gap: 3px; margin: 0; padding: 0; list-style: none; }
.lc-bench .brow { width: 100%; font: inherit; font-size: 11px; font-weight: 700; cursor: pointer; -webkit-tap-highlight-color: transparent; }
.lc-bench .brow:disabled { cursor: default; opacity: .45; }
.brow.sel { outline: 2px solid var(--accent); outline-offset: 2px; box-shadow: 0 4px 12px rgba(15, 27, 43, .22); }
/* The flag on a row, before the name (the row's gap spaces it), here and in the peek; a
   man sent off the final card wears the chip's ⇄ between his name and his OVR (D1, D2). */
.brow .flag { flex: 0 0 auto; margin-right: 0; }
.brow .bx { flex: 0 0 auto; width: 14px; height: 14px; border-radius: 50%; background: var(--accent); color: #fff; font-size: 9px; line-height: 14px; text-align: center; }
/* (the padding and its margin: room for the chosen row's outline inside the scrolling box, which clips) */
.lc-bench.scroll { max-height: calc(7 * 22px + 6 * 3px + 8px + 10px); padding: 5px; margin: -5px; overflow-y: auto; overscroll-behavior: contain; scrollbar-width: thin; }
@media (prefers-reduced-motion: reduce) { .chip.can { animation: none; } }

/* Two languages (nhl-game-logs docs/design-change-up-languages.md, 6d): a
   French page hides the data-t text until web/lang.js applyStrings has filled
   it and set data-strings, so it never flashes the English of the markup. */
html[data-lang="fr"]:not([data-strings]) [data-t],
html[data-lang="fr"]:not([data-strings]) [data-t-html] { visibility: hidden; }

/* The EN | FR seg (nhl-game-logs docs/design-change-up-languages.md, 6e): the
   top right of the home screen, above the title's line; the seg itself as the others. */
.seg.lang-seg { justify-content: flex-end; }
.seg.lang-seg button { flex: 0 0 auto; min-width: 44px; }

/* Historic Lines (nhl-game-logs docs/design-change-up-historic-lines.md, sections 8 and 16:
   look A, the case; moved from mocks/historic/index.html as drawn): the head's week strip and
   bank line, the shared parts of a line (the era line, the nickname, the three men, the blank
   plate, the moment, the unknown and shadow portrait boxes, the sheet), the grid of crests and
   the detail under it. */
.hl-week { display: inline-flex; gap: 3px; align-items: center; margin-right: 4px; vertical-align: middle; }
.hl-week i { display: block; width: 9px; height: 9px; border-radius: 50%; background: var(--ice-line); border: 1px solid var(--card-edge); box-sizing: border-box; }
.hl-week i.on { background: #ff7a1a; border-color: #ff7a1a; }
.dex .profile-card p.hl-bank { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; font-size: 13px; }
.dex .profile-card p.hl-bank strong { color: var(--text); }
.hl-head-crests { display: flex; gap: 4px; }
.hl-era { font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .5px; font-weight: 800; white-space: nowrap; }
.hl-era b { color: var(--text); }
.hl-nick { font-size: 15px; font-weight: 900; }
.hl-men { display: flex; gap: 6px; flex-wrap: wrap; align-items: center; min-width: 0; }
.hl-man { display: inline-flex; align-items: center; gap: 6px; min-width: 0; }
.hl-name { font-weight: 700; font-size: 14px; white-space: nowrap; }
/* a hidden man: a blank plate the width of a name, a faint ? */
.hl-blank { display: inline-grid; place-items: center; width: 74px; height: 20px; border-radius: 5px; background: color-mix(in srgb, var(--muted) 14%, transparent); color: color-mix(in srgb, var(--muted) 55%, transparent); font-weight: 900; font-size: 14px; }
.hl-when { font-size: 12px; color: var(--muted); }
.hl-when.iced { color: var(--ok); font-weight: 700; }
.hl-when.rev { color: var(--accent); font-weight: 700; }
/* the portrait box of an unknown man (grey line): the plate's grey; of a
   revealed man not yet found: the shadow bust on a grey band */
.dex-pic.unknown { background: color-mix(in srgb, var(--muted) 14%, transparent); color: color-mix(in srgb, var(--muted) 55%, transparent); font-weight: 900; font-size: 18px; }
.dex-pic.shadow { background: color-mix(in srgb, var(--muted) 20%, transparent); }
:root:not([data-skin="pixel"]) .dex-pic.shadow canvas { display: none; }
:root:not([data-skin="pixel"]) .dex-pic.shadow::after { content: '?'; font-weight: 900; font-size: 16px; color: color-mix(in srgb, var(--muted) 70%, transparent); }
/* the sheet (the dex's pic-sheet) under a grey line */
.hl-sheet { margin: 6px 0 4px; }
.hl-grid { display: grid; grid-template-columns: repeat(6, 51px); gap: 10px 8px; justify-content: center; margin-top: 2px; }
.hl-grid .case-b { flex-direction: column; align-items: center; gap: 2px; }
.hl-grid .case-b small { font-size: 10px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; line-height: 1.1; }
.hl-grid .case-b.iced small { color: var(--text); font-weight: 800; }
.hl-grid .case-b.rev small { color: var(--accent); font-weight: 800; }
@media (max-width: 420px) { .hl-grid { gap: 8px 4px; } }
@media (min-width: 600px) { .hl-grid { grid-template-columns: repeat(10, 51px); gap: 12px 14px; } }
.hl-detail { display: grid; gap: 8px; border-top: 1px solid var(--card-edge); padding-top: 12px; margin-top: 8px; }
.hl-detail-head { display: flex; gap: 14px; align-items: center; }
.hl-detail-words { display: grid; gap: 2px; min-width: 0; }
.hl-detail .hl-men { gap: 10px; }
.hl-detail .hl-man { flex-direction: column; gap: 3px; align-items: center; width: 74px; text-align: center; }
.hl-detail .hl-name { white-space: normal; font-size: 13px; line-height: 1.15; }
