:root {
  /* Connections theme: warm marquee. --bg is the flat fallback and the colour for
     text on dark fills; --bg-fun is the page background. */
  --bg: #fff0dc;
  --bg-fun: linear-gradient(165deg, #ffe6bd 0%, #ffd2c4 50%, #f8c4de 100%);
  --fg: #2a1a1e;
  --muted: #6d5648;
  --card: #ffffff;
  --card-border: #f0d9c6;
  --selected: #8a1f4a;
  --selected-fg: #fff;
  --accent: #b4235a;
  --on-accent: #fff;
  --yellow: #f3c94e;
  --green: #9ecf63;
  --blue: #86b7e8;
  --purple: #bb8ad8;
  --coral: #f2a08c;
  --shadow: 0 1px 2px rgba(0,0,0,.06), 0 4px 14px rgba(0,0,0,.05);
  --radius: 18px;
  --max: 760px;
  --gap: 8px;
  /* everything but the 4x4 board: header, meta, message, mistakes, controls, footer */
  --chrome: 236px;
  --cols: 4;
  /* tiles are square: the side is what the page height allows, capped by what the width allows */
  --tile-w: calc((min(100vw, var(--max)) - 32px - (var(--cols) - 1) * var(--gap)) / var(--cols));
  --tile-h: min(clamp(72px, calc((100vh - var(--chrome)) / var(--cols) - var(--gap)), 220px), var(--tile-w));
  /* faces are a fixed share of the tile, or less when a two-line name needs the room
     (2.3 = two lines at 1.15; 7px = the name's margin plus the tile border) */
  --tile-pad: 6px;
  --name-size: clamp(.72rem, 1.75vw, .92rem);
  --face: min(calc(var(--tile-h) * .6), calc(var(--tile-h) - 2.3 * var(--name-size) - 2 * var(--tile-pad) - 7px));
  --board-w: calc(var(--cols) * var(--tile-h) + (var(--cols) - 1) * var(--gap));
}
@supports (height: 100dvh) {
  :root { --tile-h: min(clamp(72px, calc((100dvh - var(--chrome)) / var(--cols) - var(--gap)), 220px), var(--tile-w)); }
}
/* Strands theme: cool lagoon */
body.strands-game {
  --bg: #e2f1f8;
  --bg-fun: linear-gradient(165deg, #c6f1e2 0%, #cbe5ff 50%, #dcd3ff 100%);
  --fg: #151c2e;
  --muted: #4d5a73;
  --card-border: #cbdaee;
  --selected: #25348a;
  --accent: #2b4acb;
}
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #251a1d; --bg-fun: linear-gradient(165deg, #2e2016 0%, #2c1820 50%, #26192f 100%);
    --fg: #f3eae5; --muted: #ab9a90; --card: #35272b; --card-border: #4d3a40;
    --selected: #f3eae5; --selected-fg: #251a1d; --accent: #ff9ab8; --on-accent: #2a1018;
    --shadow: 0 1px 2px rgba(0,0,0,.4);
  }
  :root:not([data-theme="light"]) body.strands-game {
    --bg: #151c27; --bg-fun: linear-gradient(165deg, #11261f 0%, #131e30 50%, #1d1a38 100%);
    --fg: #e8eef6; --muted: #94a2b8; --card: #212b3a; --card-border: #34425c;
    --selected: #e8eef6; --selected-fg: #151c27; --accent: #9db4ff; --on-accent: #0f1630;
  }
}
* { box-sizing: border-box; }
html, body { margin: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; touch-action: manipulation; }
button, select { -webkit-tap-highlight-color: transparent; }
body {
  background: var(--bg-fun, var(--bg)) fixed; color: var(--fg);
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Inter, Roboto, sans-serif;
  line-height: 1.4; padding: 0 16px 8px; min-height: 100vh; display: flex; flex-direction: column;
}
@supports (height: 100dvh) { body { min-height: 100dvh; } }
main { max-width: var(--max); width: 100%; margin: 0 auto; flex: 1; }
header.top { max-width: var(--max); width: 100%; margin: 0 auto; padding: 10px 0 4px; display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: nowrap; }
.brand { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
h1 { margin: 0; font-size: 1.15rem; letter-spacing: -0.01em; font-family: Georgia, "Times New Roman", serif; color: var(--accent); }
.modes { display: flex; gap: 2px; align-items: center; flex: none; margin-left: auto; }
.modes .btn { margin: 0 0 0 4px; }
/* New game menu: a column of levels per board size */
.menu-wrap { position: relative; display: inline-flex; }
.menu { position: absolute; top: calc(100% + 6px); right: 0; z-index: 6; display: grid; grid-template-columns: repeat(var(--menu-cols, 1), auto);
  gap: 2px 6px; padding: 8px; background: var(--card); border: 1px solid var(--card-border); border-radius: 16px; box-shadow: var(--shadow); }
.menu.left { right: auto; left: 0; }
.menu-head { font-size: .72rem; letter-spacing: .06em; color: var(--muted); text-align: center; padding: 0 0 4px; }
.menu-item { font: inherit; font-size: .88rem; padding: 6px 18px; border: 0; border-radius: 10px; background: none; color: var(--fg); cursor: pointer; white-space: nowrap; text-align: center; }
.menu-item:hover:not(:disabled), .menu-item:focus-visible { background: var(--bg); outline: none; }
.menu-item:disabled { opacity: .35; cursor: default; }
.chip-group { display: inline-flex; gap: 0; margin-right: 10px; }
.brand .chip-group { margin-right: 0; }
/* game names are links like the hints: underlined, the current one in bold */
.brand .chip { text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.brand .chip:hover { text-decoration-thickness: 2px; }
/* header links are plain text: bold for the active one, nothing else */
.chip { border: 0; background: none; color: var(--muted); border-radius: 6px; padding: 4px 6px; cursor: pointer; font: inherit; font-size: .9rem; }
.chip:hover { color: var(--fg); }
.chip.active { color: var(--accent); font-weight: 700; }
/* the game names follow the title on its line; a long list scrolls sideways rather than pushing New away */
.brand { min-width: 0; }
.game-list { display: flex; gap: 4px; min-width: 0; overflow-x: auto; scrollbar-width: none; }
.game-list::-webkit-scrollbar { display: none; }
.game-list .chip { flex: none; white-space: nowrap; }
/* share and help are line icons in the text colour */
.chip.icon { display: inline-flex; align-items: center; padding: 4px 5px; }
.chip.icon svg { width: 19px; height: 19px; display: block; }
/* phones: New stays flush top right; if the row is too narrow the game names wrap under the title instead */
@media (max-width: 480px) { header.top { gap: 6px; align-items: flex-start; } .brand { gap: 0 6px; } .chip { padding: 4px; } .chip.icon { padding: 4px 2px; } .modes .btn.small { padding: 4px 10px; margin-left: 2px; } }
@media (max-width: 380px) { h1 { font-size: 1.05rem; } .brand .chip { font-size: .85rem; padding: 4px 3px; } }
.row { display: flex; justify-content: space-between; align-items: center; gap: 12px; flex-wrap: wrap; margin: 0 0 6px; min-height: 30px; }
.practice-bar { display: flex; gap: 10px; align-items: center; font-size: .85rem; color: var(--muted); flex-wrap: wrap; }
.btn.small { padding: 4px 12px; font-size: .85rem; }
.hints { display: flex; gap: 10px; align-items: baseline; margin-right: auto; }
.hints-label { color: var(--muted); font-size: .85rem; margin-right: -2px; }
/* hints are underlined links; once used, the answer shows in bold with no underline */
.hint { font: inherit; font-size: .85rem; padding: 2px 0; border: 0; background: none; color: var(--accent); cursor: pointer;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
.hint:hover:not(:disabled) { text-decoration-thickness: 2px; }
.hint.revealed { text-decoration: none; cursor: default; font-weight: 700; }
.hint.on { font-weight: 700; }
.hint:disabled:not(.revealed) { opacity: .45; cursor: default; }
/* The find field is a magnifier in a circle until it is clicked or holds text. It
   opens leftwards over the row, and the match count floats to its left, so
   nothing on the page moves. 16px so phones don't zoom the page when it takes focus. */
.find-wrap { position: relative; order: 1; flex: none; width: 30px; height: 30px; margin-left: auto; --find-w: min(11rem, 56vw); }
.find { position: absolute; right: 0; top: 0; z-index: 4; width: 30px; height: 30px; padding: 0; font: inherit; font-size: 16px; border-radius: 999px;
  border: 1.5px solid var(--accent); background: var(--card); color: var(--fg); cursor: pointer; transition: width .15s ease; }
.find::placeholder { color: transparent; }
.find:focus, .find:not(:placeholder-shown) { width: var(--find-w); padding: 0 32px 0 12px; cursor: text; }
.find:focus::placeholder { color: var(--muted); }
.find:focus { outline: 2px solid var(--accent); outline-offset: 1px; }
.find-icon { position: absolute; right: 0; top: 0; z-index: 5; width: 30px; height: 30px; padding: 7px; color: var(--accent); pointer-events: none; }
.typed { position: absolute; right: calc(var(--find-w) + 8px); top: 50%; transform: translateY(-50%); z-index: 4; font-size: .85rem; padding: 3px 10px;
  border-radius: 999px; background: var(--accent); color: var(--on-accent); white-space: nowrap;
  max-width: calc(100vw - var(--find-w) - 48px); overflow: hidden; text-overflow: ellipsis; }
/* the open field and its count lie over the hints, so the hints step aside while searching */
.row:has(.find:focus, .find:not(:placeholder-shown)) .hints { visibility: hidden; }
/* Strands: the row above the board is as wide as the board, so the magnifier sits flush right with the grid */
.strands-game .row { max-width: var(--board, 520px); margin-left: auto; margin-right: auto; }
.tile.match { outline: 3px solid var(--accent); outline-offset: -3px; }
.practice-bar select { font: inherit; margin-left: 6px; padding: 4px 8px; border-radius: 8px; border: 1px solid var(--card-border); background: var(--card); color: var(--fg); }
.meta { color: var(--muted); font-size: .85rem; margin: 0 auto 0 0; }
.games { font: inherit; font-size: .85rem; font-weight: 600; color: var(--fg); background: transparent; border: 0;
  border-radius: 6px; padding: 2px 4px 2px 0; margin-right: 6px; max-width: 60%; cursor: pointer;
  text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 3px; }
@media (max-width: 480px) { .games { max-width: 100%; } }
.hidden { display: none !important; }

.grid { display: grid; grid-template-columns: repeat(var(--cols), 1fr); gap: var(--gap); width: var(--board-w); max-width: 100%; margin: 0 auto; }
.tile {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--card) 78%, transparent); border: 1px solid var(--card-border); border-radius: min(var(--radius), calc(var(--tile-h) * .2));
  padding: var(--tile-pad); cursor: pointer; font: inherit; color: inherit;
  transition: transform .08s ease, background .12s ease; height: var(--tile-h); text-align: center; overflow: hidden;
  -webkit-touch-callout: none; -webkit-user-select: none; user-select: none;
}
.tile:active { transform: scale(.97); }
.tile img { width: var(--face); height: var(--face); border-radius: 50%; object-fit: cover; background: var(--card-border); display: block; flex: none; }
/* names break at spaces; only a long word (Mahershala) is hyphenated, never a short surname */
.tile .name { font-size: var(--name-size); line-height: 1.15; margin-top: 5px; font-weight: 600; overflow-wrap: anywhere;
  hyphens: auto; hyphenate-limit-chars: 10 5 5; -webkit-hyphenate-limit-before: 5; -webkit-hyphenate-limit-after: 5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.tile.selected { background: var(--selected); color: var(--selected-fg); border-color: var(--selected); }
.tile.shake { animation: shake .4s; }
.tile.bounce { animation: bounce .35s; }
@keyframes shake { 0%,100% { transform: translateX(0);} 25% { transform: translateX(-5px);} 75% { transform: translateX(5px);} }
@keyframes bounce { 0%,100% { transform: translateY(0);} 50% { transform: translateY(-8px);} }
@media (max-width: 420px) {
  :root { --tile-pad: 4px; }
  .tile .name { margin-inline: -2px; }   /* a little more line for long surnames */
}

.solved { display: flex; flex-direction: column; gap: var(--gap); width: var(--board-w); max-width: 100%; margin-left: auto; margin-right: auto; }
.solved:not(:empty) { margin-bottom: var(--gap); }
.group {
  display: grid; grid-template-columns: auto 1fr; gap: 12px; align-items: center; height: var(--tile-h); overflow: hidden;
  border-radius: var(--radius); padding: 8px 12px; color: #1d1b19; animation: pop .3s ease;
}
@keyframes pop { from { transform: scale(.96); opacity: .2; } to { transform: scale(1); opacity: 1; } }
.group.d0 { background: var(--yellow); } .group.d1 { background: var(--green); }
.group.d2 { background: var(--blue); } .group.d3 { background: var(--purple); }
.group .poster { height: calc(var(--tile-h) - 16px); width: calc((var(--tile-h) - 16px) * 2 / 3); border-radius: 10px; object-fit: cover; background: rgba(0,0,0,.1); }
.group .poster.empty { display: flex; align-items: center; justify-content: center; font-size: 1.6rem; }
.group > div { min-width: 0; }
.group h3 { margin: 0 0 4px; font-size: 1.05rem; }
.group h3 small { font-weight: 400; opacity: .75; }
.group .faces { display: flex; flex-wrap: wrap; gap: 4px 10px; font-size: .85rem; }
.group .faces span { display: inline-flex; align-items: center; gap: 5px; }
.group .faces img { width: 28px; height: 28px; border-radius: 50%; object-fit: cover; }
@media (max-width: 480px), (max-height: 480px) {
  .group { gap: 8px; padding: 6px 8px; }
  .group h3 { font-size: .9rem; margin-bottom: 2px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .group .faces { font-size: .72rem; gap: 2px 8px; }
  .group .faces span { gap: 4px; }
  .group .faces img { width: 18px; height: 18px; }
}

.message { min-height: 1.4em; text-align: center; margin: 8px 0 2px; font-weight: 600; }
.mistakes { display: flex; justify-content: center; align-items: center; gap: 10px; color: var(--muted); font-size: .9rem; }
.dots span { display: inline-block; width: 14px; height: 14px; border-radius: 50%; background: var(--accent); margin: 0 3px; transition: transform .2s, opacity .2s; }
.dots span.gone { transform: scale(0); opacity: 0; }

.controls { display: flex; justify-content: center; gap: 10px; margin: 8px 0; flex-wrap: wrap; }
.btn { font: inherit; font-size: .9rem; padding: 8px 18px; border-radius: 999px; cursor: pointer; border: 1.5px solid var(--accent); background: transparent; color: var(--accent); }
.btn.primary { background: var(--accent); color: var(--on-accent); }
.btn:disabled { opacity: .35; cursor: default; }
@media (max-width: 360px) { .controls { gap: 8px; } .controls .btn { padding: 8px 12px; } }
/* touch screens: the header links, hints and buttons keep their look but get a finger-sized
   hit area (about 44px tall) */
@media (pointer: coarse) {
  .chip, .hint, .btn { position: relative; }
  .chip::after, .hint::after, .btn::after { content: ""; position: absolute; inset: -8px -2px; }
  .hint::after { inset: -10px -5px; }
  .btn::after { inset: -6px 0; }
  .games { padding-block: 11px; margin-block: -9px; }
  .menu-item { padding-block: 10px; }
}

.results { text-align: center; border-top: 1px solid var(--card-border); padding-top: 16px; margin-top: 8px; }
.results h2 { font-family: Georgia, serif; margin: 0 0 8px; }
.emoji { font-size: 1.4rem; line-height: 1.3; margin: 0; font-family: inherit; }
.decoys { list-style: none; padding: 0; margin: 8px auto 0; text-align: left; max-width: 480px; font-size: .9rem; color: var(--muted); }
.decoys li { padding: 6px 0; border-bottom: 1px dashed var(--card-border); }
.decoys b { color: var(--fg); }

footer { max-width: var(--max); margin: 4px auto 0; color: var(--muted); font-size: .7rem; text-align: center; }
footer p { margin: 0; }
footer a { color: inherit; }

.modal { position: fixed; inset: 0; background: rgba(0,0,0,.45); display: flex; align-items: center; justify-content: center; padding: 16px; z-index: 10; }
.modal-card { background: var(--card); color: var(--fg); border-radius: 24px; padding: 24px; max-width: 460px; width: 100%; box-shadow: var(--shadow);
  max-height: calc(100vh - 32px); overflow-y: auto; overscroll-behavior: contain; -webkit-overflow-scrolling: touch; }
@supports (height: 100dvh) { .modal-card { max-height: calc(100dvh - 32px); } }
.modal-card h2 { margin-top: 0; font-family: Georgia, serif; }
.modal-card li { margin: 8px 0; }
.modal-card ul { padding-left: 18px; }
@media (max-width: 480px) {
  .modal-card { padding: 18px 20px; border-radius: 20px; font-size: .92rem; }
  .modal-card h2 { margin-bottom: 8px; }
  .modal-card li { margin: 6px 0; }
}
.share-card { text-align: center; }
.share-card p { color: var(--muted); font-size: .9rem; }
.qr { display: flex; justify-content: center; margin: 8px 0; }
.qr svg { width: 200px; height: 200px; background: #fff; padding: 8px; border-radius: 8px; }
.share-urls { list-style: none; padding: 0 !important; margin: 8px 0 16px; }
.share-urls li { font-family: ui-monospace, Menlo, monospace; font-size: 1rem; padding: 4px 0; }
.share-urls a { color: inherit; }
#help .modal-card { max-width: 360px; padding: 20px; font-size: .9rem; line-height: 1.35; }
#help h2 { font-size: 1.2rem; margin-bottom: 8px; }
#help ul { margin: 0 0 10px; }
#help li { margin: 6px 0; }
.help-foot { color: var(--muted); font-size: .8rem; margin: 0 0 14px; }

/* ---------------------------------------------------------------- strands */
.board { position: relative; }
.strand-lines { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 2; overflow: visible; }
.strand-lines polyline { fill: none; stroke-linecap: round; stroke-linejoin: round; }
.strand-lines .chain-line { stroke: var(--selected); stroke-width: 6; opacity: .55; }
.strand-lines .found-line { stroke: rgba(0,0,0,.28); stroke-width: 4; }

/* the 4x6 board: game.js (fit) sizes --strand-h, --board and --strand-face so the
   whole game fits the viewport without scrolling */
.strands-game { --gap: 6px; }
.strands-game .board { max-width: var(--board, 520px); margin: 0 auto; }
.grid.strands { touch-action: none; user-select: none; -webkit-user-select: none; width: auto; }
.grid.strands.done { touch-action: auto; }
.grid.strands .tile { height: var(--strand-h, 96px); padding: 4px 3px; border-radius: min(var(--radius), calc(var(--strand-h, 96px) * .2)); }
.grid.strands .tile img { pointer-events: none; width: var(--strand-face, 52px); height: var(--strand-face, 52px); }
.grid.strands .tile .name { font-size: clamp(.68rem, calc(var(--strand-h, 96px) * .135), .87rem); margin-top: 3px; line-height: 1.12; }
.grid.strands.tight .tile .name { -webkit-line-clamp: 1; overflow-wrap: normal; }
/* game.js sets --strand to the film's own colour.
   tracing: two or more chain tiles from the same film, halfway to the found colour */
.tile.selected.partial { background: color-mix(in srgb, var(--strand, var(--blue)) 50%, var(--selected)); border-color: var(--strand, var(--blue)); box-shadow: 0 0 0 2px var(--strand, var(--blue)); }
.tile.found { cursor: default; border-color: transparent; color: #1d1b19; background: var(--strand, var(--blue)); }
.tile.hinted { outline: 3px dashed var(--fg); outline-offset: -4px; }
.tile.hinted.match { outline: 3px solid var(--accent); outline-offset: -3px; }   /* a type-to-find match still shows on an outlined cast */
.tile .badge {
  position: absolute; top: 6px; left: 6px; z-index: 3; width: 18px; height: 18px; border-radius: 50%;
  background: var(--fg); color: var(--bg); font-size: .65rem; font-weight: 700; line-height: 18px; text-align: center;
}
.tile.selected .badge { background: var(--selected-fg); color: var(--selected); }
.tile.found .badge { background: rgba(0,0,0,.6); color: #fff; }

/* One status slot under the board: the message (or the chain being traced) and
   the list of found films share it, so the board gets the rest of the page. */
.strands-game .status { display: grid; grid-template-columns: minmax(0, 1fr); margin-top: 5px; }
.strands-game .status > * { grid-area: 1 / 1; }
.strands-game .message { min-height: 24px; margin: 0; font-size: .88rem; line-height: 24px; }
.strands-game .message.chain { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.strands-game .message:not(:empty) + .found-list > * { visibility: hidden; }
.found-list { display: flex; flex-wrap: wrap; gap: 4px 6px; justify-content: center; align-items: center; min-height: 24px; }
.pill { font-size: .75rem; line-height: 1.3; padding: 2px 10px; border-radius: 999px; background: var(--strand, var(--blue)); color: #1d1b19;
  max-width: 17em; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; animation: pop .3s ease; }
.pill small { opacity: .7; }
.strands-game .controls { margin: 5px 0 2px; }
.strands-game .controls .btn { padding: 5px 16px; font-size: .85rem; }
.strands-game footer { margin-top: 2px; }
