/* Shared styles: dark but friendly Halloween, no external fonts, so the app
   works offline once loaded. Sizes use vmin: the TV view is read from a sofa. */

:root {
  --ink: #f6efe6;
  --ink-soft: #c8b8d8;
  --night: #1b1030;
  --night-deep: #120a22;
  --plum: #2c1b4d;
  --pumpkin: #ff9f5a;
  --mint: #8ed7c0;
  --pink: #f9a8c9;
  --warn: #ffd166;
  --radius: 18px;
  --font: "Trebuchet MS", "Segoe UI", system-ui, -apple-system, sans-serif;
}

/* Bundled fonts (assets/fonts/README.md). */
@font-face {
  font-family: "Special Elite";
  src: url("../assets/fonts/SpecialElite-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Architects Daughter";
  src: url("../assets/fonts/ArchitectsDaughter-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Playfair Display SC";
  src: url("../assets/fonts/PlayfairDisplaySC-Bold.ttf") format("truetype");
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Metamorphous";
  src: url("../assets/fonts/Metamorphous-Regular.ttf") format("truetype");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Nunito Sans";
  src: url("../assets/fonts/NunitoSans-Variable.ttf") format("truetype");
  font-weight: 200 1000;
  font-style: normal;
  font-display: swap;
}

/* The shop's look (05-sklep/motyw in halloween-shop) on the pages people
   read up close: home, editor, remote, account. The TV keeps its themes. */
body.brand {
  --ink: #fcfcfc;
  --ink-soft: #c3ccd3;
  --night: #16222d;
  --night-deep: #0c141b;
  --plum: #1a2a35;
  --gold: #c8a875;
  --gold-deep: #947c60;
  --font: "Nunito Sans", "Trebuchet MS", "Segoe UI", system-ui, -apple-system, sans-serif;
  background: #0c141b;
  background: var(--night-deep);
  font-size: 17px;
}
body.brand h1, body.brand h2, body.brand h3,
body.brand .join h1, body.brand .home h1 {
  font-family: "Playfair Display SC", Georgia, serif;
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--gold);
}
body.brand .btn--ghost { border-color: rgba(200, 168, 117, .45); color: var(--ink); }
/* Hover only where a pointer can hover: a tapped button on a phone would keep the gold border (owner 2026-10-12). */
@media (hover: hover) { body.brand .btn--ghost:hover { border-color: var(--gold); } }
body.brand .btn:not(.btn--ghost):not(.btn--danger) { color: var(--night-deep); }
body.brand .input, body.brand .field input, body.brand .field select, body.brand .join__code {
  border-color: rgba(200, 168, 117, .35);
  background: var(--night);
}
body.brand .input:focus, body.brand .field input:focus, body.brand .field select:focus { outline: none; border-color: var(--gold); }
body.brand .linkbox, body.brand .now, body.brand .game-list__item { border: 1px solid rgba(200, 168, 117, .22); }
body.brand .game-list__item:hover { border-color: var(--gold); }
body.brand a { color: var(--gold); }
/* Links styled as buttons stay buttons: no underline, button colours. */
a.btn, a.btn:hover { text-decoration: none; }
body.brand a.btn--ghost { color: var(--ink); }
body.brand .field__note strong, body.brand .linkbox strong { color: var(--gold); }
body.brand .home__cards > a { border: 1px solid rgba(200, 168, 117, .22); color: var(--ink); }
body.brand .home__cards > a:hover { border-color: var(--gold); }
body.brand .home__cards h2 { font-size: 1.25rem; }
.brand-logo { display: block; width: min(360px, 80vw); height: auto; margin: 0 0 18px; }
.brand-logo--small { width: min(260px, 70vw); margin: 0 auto 14px; }
.visually-hidden { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

* { box-sizing: border-box; }

/* Plain values before each var(): a browser without custom properties (old
   TV browsers) still gets readable colours instead of black on white. */
html, body {
  margin: 0;
  padding: 0;
  min-height: 100%;
  background: #120a22;
  background: var(--night-deep);
  color: #f6efe6;
  color: var(--ink);
  font-family: "Trebuchet MS", "Segoe UI", sans-serif;
  font-family: var(--font);
}

kbd {
  background: rgba(255, 255, 255, .12);
  border-radius: 6px;
  padding: 1px 7px;
  font-family: inherit;
  font-size: .95em;
}

.btn {
  font: inherit;
  font-weight: 700;
  color: #1b1030;
  color: var(--night);
  background: #ff9f5a;
  background: var(--pumpkin);
  border: none;
  border-radius: 18px;
  border-radius: var(--radius);
  padding: 14px 28px;
  cursor: pointer;
}

@media (hover: hover) { .btn:hover { filter: brightness(1.08); } }
.btn:focus-visible { outline: 3px solid var(--mint); outline-offset: 3px; }

.btn--big { font-size: 1.6rem; padding: 18px 56px; }

.btn--ghost {
  background: transparent;
  color: var(--ink);
  border: 2px solid rgba(255, 255, 255, .25);
  padding: 8px 16px;
  font-weight: 600;
}

/* ------------------------------------------------------------ landing */

.home {
  max-width: 900px;
  margin: 0 auto;
  padding: 48px 24px 64px;
}

.home h1 { font-size: 2.6rem; margin: 0 0 8px; }
.home p { color: var(--ink-soft); line-height: 1.55; }

.home__cards {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  margin-top: 32px;
}

.home__card {
  display: block;
  background: var(--plum);
  border-radius: var(--radius);
  padding: 24px;
  color: var(--ink);
  text-decoration: none;
  border: 2px solid transparent;
}

.home__card:hover { border-color: var(--pumpkin); }
.home__card h2 { margin: 0 0 8px; font-size: 1.4rem; }
.home__card p { margin: 0; font-size: .98rem; }
.home__card--soon { opacity: .55; }

/* How to host (help/): a text page in the shop's look. */
.guide { max-width: 720px; margin: 0 auto; padding: 32px 20px 64px; }
.guide h1 { font-size: 2.2rem; margin: 0 0 10px; }
.guide h2 { font-size: 1.35rem; margin: 36px 0 10px; }
.guide .lead { color: var(--ink-soft); line-height: 1.55; margin: 0 0 18px; }
.guide p, .guide li { line-height: 1.55; }
.guide ul, .guide ol { padding-left: 1.3em; margin: 0; }
.guide li { margin: 0 0 10px; }
.guide a { color: var(--gold); }
.guide__back { display: inline-block; margin-bottom: 18px; text-decoration: none; }
.guide__toc { display: flex; flex-wrap: wrap; gap: 8px 14px; font-size: .95rem; }

/* --------------------------------------------------------------- setup */

.setup {
  max-width: 1100px;
  margin: 0 auto;
  padding: 32px 24px 64px;
}

.setup__head h1 { font-size: 2.4rem; margin: 0 0 6px; }
.setup__lead { color: var(--ink-soft); margin: 0 0 24px; max-width: 60ch; line-height: 1.5; }

.setup__grid {
  display: grid;
  gap: 20px;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  align-items: start;
}

.panel {
  background: var(--plum);
  border: 2px solid rgba(255, 255, 255, .08);
  border-radius: var(--radius);
  padding: 18px 20px 22px;
  margin: 0;
}

.panel legend {
  font-weight: 700;
  font-size: 1.1rem;
  padding: 0 8px;
  color: var(--pumpkin);
}

.panel--warn { border-color: rgba(255, 209, 102, .45); }
.panel--wide { grid-column: 1 / -1; }

.field { display: block; margin-bottom: 14px; }
/* A password field with a "show password" eye (owner 2026-10-14). */
.pass { position: relative; display: block; }
.pass .input { padding-right: 46px; }
.pass__eye { position: absolute; right: 6px; top: 50%; transform: translateY(-50%); width: 36px; height: 36px; border: 0; border-radius: 50%; background: none; color: var(--ink-soft, #aab6bf); cursor: pointer; display: grid; place-items: center; padding: 0; }
.pass__eye:hover, .pass__eye[aria-pressed="true"] { color: var(--gold, #c8a875); }
.pass__eye svg { display: block; }
.pass__slash[hidden] { display: none; }
.field span { display: block; margin-bottom: 4px; font-size: .95rem; }

.field input, .field select, .field textarea {
  font: inherit;
  width: 100%;
  padding: 10px 12px;
  border-radius: 12px;
  border: 2px solid rgba(255, 255, 255, .18);
  background: var(--night);
  color: var(--ink);
}

.field__note { color: var(--ink-soft); font-size: .92rem; line-height: 1.45; margin: 8px 0 0; }

.list { margin: 6px 0 0; padding-left: 20px; color: var(--ink-soft); line-height: 1.5; font-size: .95rem; }
.list--warn { color: var(--warn); }

.places {
  display: grid;
  gap: 10px;
  grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
}

.place {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-areas: "check art" "name name" "tip tip";
  gap: 4px 8px;
  align-items: center;
  background: var(--night);
  border-radius: 14px;
  padding: 10px;
  cursor: pointer;
  border: 2px solid transparent;
}

.place:hover { border-color: rgba(255, 159, 90, .5); }
.place input { grid-area: check; width: 20px; height: 20px; accent-color: var(--pumpkin); }
.place__art { grid-area: art; width: 100%; max-height: 54px; object-fit: contain; }
.place__name { grid-area: name; font-weight: 700; font-size: .98rem; }
.place__tip { grid-area: tip; color: var(--ink-soft); font-size: .82rem; line-height: 1.35; }
.place:has(input:not(:checked)) { opacity: .45; }

.places__actions { display: flex; gap: 10px; margin-top: 14px; }

.setup__start { grid-column: 1 / -1; text-align: center; padding-top: 8px; }
.error { color: #ff8c8c; font-weight: 700; }

/* --------------------------------------------------------------- stage */

.stage {
  position: fixed;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  overflow: hidden;
  background: #1b1030;
  background: radial-gradient(circle at 50% 18%, var(--plum) 0%, var(--night) 45%, var(--night-deep) 100%);
}

.stage__bg { position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; }
.stage__bg[hidden] { display: none; }

/* Theme clips (transitions, effects): a full-stage video above the images,
   below the views; fades out when it ends. */
.stage__video {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  width: 100%; height: 100%; object-fit: cover; background: transparent;
  opacity: 0;  /* invisible until the first frame plays: no black flash */
}
.stage__video.is-ready { opacity: 1; }
.stage__video.is-fading { opacity: 0; transition: opacity .4s ease; }
.stage__freeze { opacity: 1; }  /* a copied frame: visible as soon as it is shown */
.stage__video[hidden] { display: none; }
/* Drawn effects (src/effects.js): a transparent canvas over the pictures and clips, below the views. */
.stage__fx { position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.stage__fx[hidden] { display: none; }
/* The idle loop (theme backgroundVideo) sits under the clips and hides with a task on. */
.stage.is-text-task .stage__loop, .stage.is-photo-task .stage__loop { visibility: hidden; }
/* The task loop (theme taskVideo) shows only while a task is on; the still under it covers the first frame. */
.stage__task-loop { visibility: hidden; }
.stage.is-text-task .stage__task-loop.is-ready, .stage.is-photo-task .stage__task-loop.is-ready { visibility: visible; }
.task.is-waiting { opacity: 0; }
.task { transition: opacity .4s ease; }
.task.is-flash-in, .task.is-flash-out { transition: none; }

/* CRT switch-on / switch-off of the task (themes with taskFlash). */
[data-task-flash] .task.is-flash-in .card { animation: crt-on .6s cubic-bezier(.2, .9, .3, 1) both; }
[data-task-flash] .task.is-flash-out .card { animation: crt-off .42s ease-in both; }
[data-task-flash] .task.is-flash-in .card::before, [data-task-flash] .task.is-flash-out .card::before {
  content: ""; position: absolute; top: -8%; right: -8%; bottom: -8%; left: -8%;
  background: radial-gradient(ellipse at center, rgba(255, 244, 220, 1) 0%, rgba(255, 236, 200, .85) 35%, rgba(255, 230, 190, 0) 72%);
  pointer-events: none; z-index: 2;
}
[data-task-flash] .task.is-flash-in .card::before { animation: crt-glow-in .6s ease-out both; }
[data-task-flash] .task.is-flash-out .card::before { animation: crt-glow-out .42s ease-in both; }

@keyframes crt-on {
  0% { opacity: 0; transform: scale(1.02, .01); filter: brightness(3); }
  35% { opacity: 1; transform: scale(1.02, .01); filter: brightness(3); }
  60% { transform: scale(1, 1.04); filter: brightness(1.8); }
  100% { transform: scale(1, 1); filter: brightness(1); }
}
@keyframes crt-off {
  0% { opacity: 1; transform: scale(1, 1); filter: brightness(1); }
  40% { transform: scale(1.02, .06); filter: brightness(2.4); }
  75% { opacity: 1; transform: scale(.3, .01); filter: brightness(3); }
  100% { opacity: 0; transform: scale(0, .01); filter: brightness(3); }
}
@keyframes crt-glow-in { 0% { opacity: 0; } 30% { opacity: 1; } 100% { opacity: 0; } }
@keyframes crt-glow-out { 0% { opacity: 0; } 45% { opacity: 1; } 100% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  [data-task-flash] .task.is-flash-in .card, [data-task-flash] .task.is-flash-out .card,
  [data-task-flash] .task.is-flash-in .card::before, [data-task-flash] .task.is-flash-out .card::before { animation: none; }
}

/* Theme background image (data/themes.js); "none" shows the drawn scene. */
.stage__image {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  background: var(--stage-image, none) center / cover no-repeat;
}

/* A veil over the photo so the card and the code stay readable. */
.stage__image::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  background: rgba(0, 0, 0, var(--stage-dim, 0));
}

/* Text and photo tasks: a theme may swap in a second image (a frame with a
   clear middle) and restyle the card; without one, these fall back to the
   above. The task images sit on two layers over the idle image and cross-fade
   (owner's ask, 2026-10-09: in "Pumpkins" the pictures cut in abruptly);
   in themes with show/hide clips the fade runs under the clip. */
.stage__image > i {
  position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  background-size: cover; background-position: center; background-repeat: no-repeat;  /* longhands: the shorthand would wipe the image set below */
  opacity: 0;
  transition: opacity .8s ease;
}
.stage__image-text { background-image: var(--stage-text-image, var(--stage-image, none)); }
.stage__image-photo { background-image: var(--stage-photo-image, var(--stage-image, none)); }
.is-text-task .stage__image-text, .is-photo-task .stage__image-photo { opacity: 1; }
.stage__image::after { transition: background-color .8s ease; }
.is-text-task .stage__image::after { background: rgba(0, 0, 0, var(--text-dim, var(--stage-dim, 0))); }
@media (prefers-reduced-motion: reduce) {
  .stage__image > i, .stage__image::after { transition: none; }
}
.is-text-task .card {
  background: var(--text-card-bg, var(--card-bg, #ffe9c9));
  color: var(--text-card-ink, var(--card-ink, #2b1b3d));
}
[data-text-frame] .is-text-task .card--tv, [data-text-frame].is-text-task .card--tv {
  box-shadow: none; max-width: 66vw; padding: 2vmin 4vmin;
}
[data-text-frame].is-text-task .card--preview { max-width: 60%; }

/* Text task typography from the theme (all optional). */
.is-text-task .card__text {
  font-family: var(--text-font, inherit);
  font-weight: var(--text-weight, 700);
  font-style: var(--text-font-style, normal);
  text-transform: var(--text-transform, none);
  letter-spacing: var(--text-spacing, 0);
  line-height: var(--text-line-height, 1.25);
}
[data-text-frame] .is-text-task .card--tv .card__text { font-size: var(--text-size, 6vmin); }
[data-text-frame].is-text-task .card--preview .card__text { font-size: 2.2em; }

/* Text task inside a theme box (textFrame): the card becomes the box, no
   background, text sized by theme.fitText to fill it. */
[data-text-box] .is-text-task .card--tv, [data-text-box].is-text-task .card--tv,
[data-text-box].is-text-task .card--preview {
  position: absolute; left: var(--tframe-left); top: var(--tframe-top); width: var(--tframe-w); height: var(--tframe-h);
  max-width: none; max-height: none; padding: 2% 4%; gap: 0; border-radius: 0;
  background: transparent; box-shadow: none; justify-content: center; overflow: hidden;
}
[data-text-box] .is-text-task .card--tv .card__text, [data-text-box].is-text-task .card--tv .card__text,
[data-text-box].is-text-task .card--preview .card__text { max-width: 100%; }
.is-text-task .card__text { text-shadow: var(--text-shadow, none); }
.is-photo-task .photo-frame > img:first-child { filter: var(--photo-filter, none); }

/* Smoke under the riddle (theme.smoke, "Cute Ghost", owner's ask
   2026-10-09): the text box fills with white smoke that thickens over
   about 2.5 s, two blurred clouds on top of each other; the riddle fades
   in on the dense middle a moment later. */
[data-smoke] .is-text-task .card--tv, [data-smoke].is-text-task .card--tv, [data-smoke].is-text-task .card--preview {
  overflow: visible; padding: 9% 11%; isolation: isolate;  /* the smoke's z-index -1 stays inside the card */
}
[data-smoke] .is-text-task .card--tv::before, [data-smoke] .is-text-task .card--tv::after,
[data-smoke].is-text-task .card--preview::before, [data-smoke].is-text-task .card--preview::after {
  content: ""; position: absolute;
  pointer-events: none; z-index: -1;
  /* Two pre-rendered smoke blobs with ragged, noisy outlines (assets/themes/duszek/smoke-*.png from
     tools/smoke.py): cheap to animate, unlike an SVG displacement filter (owner's ask 2026-10-12). */
  inset: -22% -18%;
  background: url("../assets/themes/duszek/smoke-a.png") center / 100% 100% no-repeat;
  filter: blur(1.2vmin);
  animation: smoke-in 2.6s cubic-bezier(.2, .6, .3, 1) both;
}
[data-smoke] .is-text-task .card--tv::after, [data-smoke].is-text-task .card--preview::after {
  transform-origin: 46% 58%;
  inset: -26% -22%;
  background: url("../assets/themes/duszek/smoke-b.png") center / 100% 100% no-repeat;
  filter: blur(2.2vmin);
  animation-duration: 3.2s; animation-delay: .25s;
}
[data-smoke] .is-text-task .card--tv .card__text, [data-smoke].is-text-task .card--preview .card__text {
  position: relative; animation: smoke-text 1.4s 1.3s ease-out both;
}
/* The riddle leaves as it came: the smoke thins and drifts up over about 2 s, the text fades first (owner's ask 2026-10-12). */
[data-smoke] .is-text-task .is-smoke-out .card--tv::before, [data-smoke] .is-text-task .is-smoke-out .card--tv::after {
  animation: smoke-out 2.2s cubic-bezier(.4, 0, .8, .6) both;
}
[data-smoke] .is-text-task .is-smoke-out .card--tv::after { animation-duration: 2.6s; }
[data-smoke] .is-text-task .is-smoke-out .card--tv .card__text { animation: smoke-text-out .9s ease-in both; }
@keyframes smoke-out {
  0% { opacity: 1; transform: scale(1.06); }
  100% { opacity: 0; transform: scale(1.25) translateY(-6%); }
}
@keyframes smoke-text-out { from { opacity: 1; } to { opacity: 0; } }
@keyframes smoke-in {
  0% { opacity: 0; transform: scale(.55); }
  45% { opacity: .55; transform: scale(.85); }
  100% { opacity: 1; transform: scale(1.06); }
}
@keyframes smoke-text { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  [data-smoke] .is-text-task .card--tv::before, [data-smoke] .is-text-task .card--tv::after,
  [data-smoke] .is-text-task .card--tv .card__text,
  [data-smoke] .is-text-task .is-smoke-out .card--tv::before, [data-smoke] .is-text-task .is-smoke-out .card--tv::after,
  [data-smoke] .is-text-task .is-smoke-out .card--tv .card__text { animation: none; }
}

/* The riddle inside the glass ball (theme.glass, "Witch Vespera", owner's ask
   2026-10-13): a soft shade deep in the glass behind the text, the text itself
   glowing in the ball's teal, and the ball's surface (top highlight, bright rim)
   painted over it so the letters read as set inside the sphere. The circle is
   placed from theme.placeFrame (--glass-*), relative to the text box (--tframe-*). */
[data-glass] .is-text-task .card--tv { overflow: visible; isolation: isolate; }
[data-glass] .is-text-task .card--tv::before, [data-glass] .is-text-task .card--tv::after {
  content: ""; position: absolute; pointer-events: none; border-radius: 50%;
  left: calc(var(--glass-left) - var(--tframe-left)); top: calc(var(--glass-top) - var(--tframe-top));
  width: var(--glass-w); height: var(--glass-h);
}
[data-glass] .is-text-task .card--tv::before {
  z-index: -1;
  /* The mist deep in the ball: a darker teal core the letters stand in, and the sphere's shadow side. */
  background:
    radial-gradient(ellipse 42% 36% at 50% 54%, rgba(2, 26, 32, .62), rgba(2, 26, 32, .3) 60%, rgba(2, 26, 32, 0) 100%),
    radial-gradient(circle at 50% 50%, rgba(2, 26, 32, 0) 58%, rgba(2, 26, 32, .22) 86%, rgba(2, 26, 32, 0) 97%);
}
[data-glass] .is-text-task .card--tv::after {
  z-index: 1;
  /* The surface: a broad highlight veiling the top lines, a small one low on the left, the bright rim. */
  background:
    radial-gradient(ellipse 64% 34% at 50% 18%, rgba(255, 255, 255, .42), rgba(255, 255, 255, .14) 60%, rgba(255, 255, 255, 0) 100%),
    radial-gradient(ellipse 38% 18% at 28% 82%, rgba(255, 255, 255, .22), rgba(255, 255, 255, 0) 100%),
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 70%, rgba(200, 255, 245, .14) 84%, rgba(255, 255, 255, .42) 94%, rgba(255, 255, 255, .14) 100%);
}
/* A photo in the glass: the surface (highlight, rim) over it too, placed from the photo box. */
[data-glass] .is-photo-task .card--tv { overflow: visible; isolation: isolate; }
[data-glass] .is-photo-task .card--tv::after {
  content: ""; position: absolute; pointer-events: none; border-radius: 50%; z-index: 1;
  left: calc(var(--glass-left) - var(--frame-left)); top: calc(var(--glass-top) - var(--frame-top));
  width: var(--glass-w); height: var(--glass-h);
  background:
    radial-gradient(ellipse 64% 34% at 50% 18%, rgba(255, 255, 255, .42), rgba(255, 255, 255, .14) 60%, rgba(255, 255, 255, 0) 100%),
    radial-gradient(ellipse 38% 18% at 28% 82%, rgba(255, 255, 255, .22), rgba(255, 255, 255, 0) 100%),
    radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0) 70%, rgba(200, 255, 245, .14) 84%, rgba(255, 255, 255, .42) 94%, rgba(255, 255, 255, .14) 100%);
}
[data-glass] .is-text-task .card--tv .card__text {
  color: var(--glass-ink, #e4fff7); opacity: .92;
  text-shadow: 0 0 .25vmin rgba(4, 28, 34, .95), 0 0 .8vmin rgba(4, 28, 34, .7), 0 0 2.6vmin rgba(120, 235, 215, .9), 0 0 6vmin rgba(90, 210, 190, .6);
}

/* Photo task: a third image, when the theme has one (the layer above). */
.is-photo-task .stage__image::after { background: rgba(0, 0, 0, var(--photo-dim, var(--stage-dim, 0))); }

/* Photo inside the theme's picture frame: the card becomes the frame's
   rectangle (variables set from theme.placeFrame), the photo is contained
   in it, tinted, with an inner shadow; the caption hangs below the frame. */
[data-photo-frame] .is-photo-task .card--tv, [data-photo-frame].is-photo-task .card--tv {
  position: absolute; left: var(--frame-left); top: var(--frame-top); width: var(--frame-w); height: var(--frame-h);
  max-width: none; max-height: none; padding: 0; gap: 0; border-radius: 0;
  background: transparent; box-shadow: none; justify-content: center;
}
[data-photo-frame] .is-photo-task .card--tv .photo-frame, [data-photo-frame].is-photo-task .card--tv .photo-frame {
  width: auto; max-width: 100%; max-height: 100%;
}
[data-photo-frame] .is-photo-task .card--tv .photo-frame > img:first-child,
[data-photo-frame].is-photo-task .card--tv .photo-frame > img:first-child {
  max-width: var(--frame-w); max-height: var(--frame-h); width: auto; height: auto; border-radius: 0;
}
[data-photo-frame] .is-photo-task .photo-frame::after, [data-photo-frame].is-photo-task .photo-frame::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0;
  background: var(--photo-scanlines, none), var(--photo-tint, transparent);
  box-shadow: inset 0 0 3vmin rgba(0, 0, 0, .55);
  pointer-events: none;
}
/* Themes may soften the photo's edges into the screen (mask), round it and
   scale it a little so it fills the box like a broadcast picture. */
[data-photo-frame] .is-photo-task .photo-frame, [data-photo-frame].is-photo-task .photo-frame {
  -webkit-mask-image: var(--photo-mask, none); mask-image: var(--photo-mask, none);
  border-radius: var(--photo-radius, 0);
  transform: scale(var(--photo-scale, 1));
}
/* theme.photoFill: the photo covers the whole box (cropped), so a mask can shape it (Vespera's disc). */
[data-photo-fill] .is-photo-task .card--tv .photo-frame { width: 100%; height: 100%; }
[data-photo-fill] .is-photo-task .card--tv .photo-frame > img:first-child {
  width: 100%; height: 100%; max-width: none; max-height: none; object-fit: cover;
}
[data-photo-fill] .is-photo-task .photo-frame::after { box-shadow: none; }
[data-photo-frame] .is-photo-task .card--tv .card__text, [data-photo-frame].is-photo-task .card--tv .card__text {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%); width: 60vw;
  margin-top: var(--photo-caption-gap, 2vmin);  /* clears the frame's lower bar */
  font-size: 3.6vmin; color: var(--ink); text-shadow: 0 .3vmin 1.5vmin rgba(0, 0, 0, .8);
}
[data-photo-frame].is-photo-task .card--preview .card__text { font-size: 1.3em; margin-top: var(--photo-caption-gap-preview, .6em); }

.moon {
  position: absolute;
  top: 6vmin;
  right: 10vmin;
  width: 14vmin;
  height: 14vmin;
  border-radius: 50%;
  background: #ffe9c9;
  background: var(--moon, #ffe9c9);
  box-shadow: 0 0 12vmin rgba(255, 233, 201, .35);
}

.hills {
  position: absolute;
  left: -10%;
  right: -10%;
  bottom: -6vmin;
  height: 26vmin;
  background:
    radial-gradient(60% 100% at 20% 100%, #24143f 0 70%, transparent 71%),
    radial-gradient(55% 100% at 62% 100%, #1d1036 0 70%, transparent 71%),
    radial-gradient(70% 100% at 95% 100%, #24143f 0 70%, transparent 71%);
  background:
    radial-gradient(60% 100% at 20% 100%, var(--hill-a, #24143f) 0 70%, transparent 71%),
    radial-gradient(55% 100% at 62% 100%, var(--hill-b, #1d1036) 0 70%, transparent 71%),
    radial-gradient(70% 100% at 95% 100%, var(--hill-a, #24143f) 0 70%, transparent 71%);
}

.view {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2vmin;
  padding: 4vmin;
  text-align: center;
}

.view[hidden] { display: none; }

.view__round { margin: 0; color: var(--mint); font-size: 3vmin; letter-spacing: .1em; text-transform: uppercase; }
.view__label { margin: 0; font-size: 8vmin; font-weight: 700; }
.view__label--huge { font-size: 18vmin; color: var(--pumpkin); text-shadow: 0 0 6vmin rgba(255, 159, 90, .6); }
.view__sub { margin: 0; color: var(--ink-soft); font-size: 3.4vmin; }

.clock { margin: 0; font-size: 22vmin; font-weight: 700; line-height: 1; font-variant-numeric: tabular-nums; }

.reminder {
  display: flex;
  align-items: center;
  gap: 2vmin;
  background: rgba(0, 0, 0, .3);
  border-radius: 3vmin;
  padding: 2vmin 3vmin;
  max-width: 80vw;
}

.reminder__art { width: 12vmin; height: 12vmin; object-fit: contain; }
.reminder__text { margin: 0; font-size: 3.2vmin; color: var(--ink-soft); white-space: pre-line; }

.card {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2vmin;
  background: #ffe9c9;
  background: var(--card-bg, #ffe9c9);
  color: #2b1b3d;
  color: var(--card-ink, #2b1b3d);
  border-radius: 4vmin;
  padding: 4vmin 6vmin;
  max-width: 86vw;
  box-shadow: 0 2vmin 6vmin rgba(0, 0, 0, .45);
}

.card__art { width: min(52vmin, 70vw); max-height: 46vmin; object-fit: contain; }
.card__text { margin: 0; font-size: 5.4vmin; font-weight: 700; line-height: 1.25; white-space: pre-line; text-align: center; }
.card__timer { margin: 0; color: var(--ink-soft); font-size: 3.4vmin; font-variant-numeric: tabular-nums; }

.recap {
  margin: 1vmin 0 3vmin;
  columns: 2;
  color: var(--ink-soft);
  font-size: 2.6vmin;
  text-align: left;
}

.badge {
  position: absolute;
  top: 3vmin;
  left: 3vmin;
  background: var(--warn);
  color: var(--night);
  font-weight: 700;
  font-size: 3vmin;
  padding: 1vmin 3vmin;
  border-radius: 2vmin;
}

.badge[hidden], .blank[hidden] { display: none; }

/* The candy shop board on the TV (owners 2026-10-19): the owners' parchment, 16:9, letterboxed on black;
   each theme's picture and text boxes come from data/themes.js (shopBoard), set by applyShopBoard in src/tv.js. */
.shop-board { position: absolute; inset: 0; background: #000; display: flex; align-items: center; justify-content: center; z-index: 3; }  /* above the stage; the black screen (later in the page, same level) covers it */
.shop-board[hidden] { display: none; }
.shop-board__card { position: relative; width: min(100vw, 177.78vh); aspect-ratio: 16 / 9; container-type: inline-size; }
.shop-board__img { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.shop-board__title, .shop-board__text { position: absolute; margin: 0; display: flex; align-items: center; justify-content: center; text-align: center;
  font-family: "Metamorphous", Georgia, serif; color: #3a2712; line-height: 1.15; }
.blank { position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: #000; z-index: 3; }
/* The end of the game: black comes in very slowly over the farewell's last frame and the end text (owner 2026-10-14). */
.end-black { position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: #000; opacity: 0; z-index: 8; transition: opacity 5s ease-in-out; }
.end-black.is-on { opacity: 1; }
.end-black[hidden] { display: none; }

/* The gong: a short flash of light over the whole screen. */
body.is-gong .stage { animation: gong-flash 1.1s ease-out; }

@keyframes gong-flash {
  0% { filter: brightness(3.2); }
  30% { filter: brightness(1.6); }
  100% { filter: brightness(1); }
}

@media (prefers-reduced-motion: reduce) {
  body.is-gong .stage { animation: none; }
}

/* ------------------------------------------------------------ TV start */

.start {
  min-height: 100vh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 18px;
  padding: 24px;
  text-align: center;
}

.start h1 { font-size: 3rem; margin: 0; }
.start__lead { color: var(--ink-soft); max-width: 46ch; margin: 0; line-height: 1.5; }

/* ------------------------------------------------------------- pairing */

.pairing {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  /* Above the riddle card, with a veil, so the QR code stays readable
     when the code is shown mid-game (Q / menu). */
  z-index: 5;
  background: rgba(5, 8, 20, .72);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2vmin;
  text-align: center;
}

.pairing[hidden] { display: none; }
.welcome__kicker { margin: 0; font-size: 5vmin; font-weight: 500; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); text-shadow: 0 .4vmin 2vmin rgba(0, 0, 0, .75); }
.welcome__logo { display: block; width: 56vmin; max-width: 80vw; height: auto; margin: 1vmin auto 0; filter: drop-shadow(0 .6vmin 3vmin rgba(0, 0, 0, .8)); }
.welcome__theme { margin: 2.5vmin 0 0; font-size: 4.2vmin; font-weight: 500; letter-spacing: .1em; text-transform: uppercase; color: var(--gold, #c8a875); text-shadow: 0 .4vmin 2vmin rgba(0, 0, 0, .75); }
.welcome__theme:empty { display: none; }
.pairing__kicker { font-size: 3.2vmin; }
.pairing__logo { width: 34vmin; margin-bottom: 2vmin; }
.welcome {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 1vmin;
  padding: 6vmin;
  text-align: center;
  z-index: 1;
  pointer-events: none;  /* a board, not a control: clicks go to the menu */
  transition: opacity 2.6s ease-out, filter 2.6s ease-out, transform 2.6s ease-out;
}
/* The board leaves like smoke: blurs, lifts a little and thins out (owner's ask, 2026-10-08). */
.welcome.is-gone { opacity: 0; filter: blur(2.5vmin); transform: translateY(-3vmin) scale(1.06); }
.welcome[hidden] { display: none; }
.welcome__title { margin: 0; font-size: 9vmin; font-weight: 700; line-height: 1.1; text-shadow: 0 .6vmin 3vmin rgba(0, 0, 0, .75); }
.pairing__label { margin: 0; font-size: 4vmin; color: var(--ink-soft); text-shadow: 0 .3vmin 1.5vmin rgba(0, 0, 0, .7); }
.pairing__qr { width: 34vmin; height: 34vmin; background: #fff; padding: 1.5vmin; border-radius: 2vmin; }
.pairing__qr svg { width: 100%; height: 100%; display: block; }
.pairing__code { margin: 0; font-size: 13vmin; font-weight: 700; letter-spacing: .14em; line-height: 1; text-shadow: 0 .5vmin 2.5vmin rgba(0, 0, 0, .7); }
.pairing__close { margin-top: 2vmin; font-size: 2.6vmin; }
.pairing__close[hidden] { display: none; }
.pairing__url { margin: 0; font-size: 2.4vmin; color: var(--ink-soft); word-break: break-all; max-width: 80vw; text-shadow: 0 .3vmin 1.5vmin rgba(0, 0, 0, .7); }

.task {
  position: absolute;
  top: 0; right: 0; bottom: 0; left: 0;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 4vmin;
}

.task[hidden] { display: none; }
.card--tv { max-width: 90vw; max-height: 90vh; }
.card--tv .card__art { width: auto; max-width: 84vw; max-height: 64vh; border-radius: 2vmin; }
.card--tv .card__text { font-size: 6vmin; }
.card--tv .card__text[hidden] { display: none; }

.watermark {
  position: absolute;
  top: 3vmin;
  right: 3vmin;
  padding: 1vmin 2.4vmin;
  border: .5vmin solid var(--warn);
  color: var(--warn);
  font-weight: 700;
  font-size: 3.2vmin;
  letter-spacing: .12em;
  transform: rotate(-6deg);
  opacity: .85;
}

.watermark[hidden] { display: none; }
/* The TV's PREVIEW marks (owner's ask 2026-10-08, two corners since 2026-10-13):
   one in the top right, one in the bottom left, each half the old single
   mark's size and tilted 15 degrees the other way, always on while the game has no pass
   or the party day has not come, faint enough to read the riddle through. */
.watermark--preview {
  top: 0; right: 0; bottom: 0; left: 0; width: auto;
  padding: 0; border: none; transform: none; opacity: 1;
  pointer-events: none;
  z-index: 6;  /* above the riddle and the boards, under the menu */
}
.watermark__mark {
  position: absolute;
  font-family: "Nunito Sans", "Arial Black", "Trebuchet MS", sans-serif;  /* the bundled variable font goes to 1000; Trebuchet only has bold */
  font-size: 7.75vw; font-weight: 1000; line-height: 1; letter-spacing: .06em; white-space: nowrap;
  color: var(--warn);
  -webkit-text-stroke: .15vw rgba(0, 0, 0, .35);
  text-shadow: 0 0 1vw rgba(0, 0, 0, .5);
  opacity: .18;  /* bolder and fainter (owner 2026-10-13) */
  transform: rotate(15deg);  /* the other way than the old mark's -8deg, and steeper (owner 2026-10-13) */
}
.watermark__mark--tr { top: 12vh; right: 3vw; }
.watermark__mark--bl { bottom: 12vh; left: 3vw; }

.corner-code {
  position: absolute;
  bottom: 2vmin;
  right: 3vmin;
  z-index: 4;
  /* Readable on any background: light text on a dark pill, so the code
     stays legible over a white photo or a bright riddle card. */
  color: rgba(255, 255, 255, .85);
  background: rgba(5, 8, 20, .62);
  padding: .5vmin 1.4vmin;
  border-radius: 1vmin;
  font-size: 2.6vmin;
  letter-spacing: .2em;
}

.corner-code[hidden] { display: none; }
.badge--status { top: auto; bottom: 3vmin; left: 50%; transform: translateX(-50%); font-size: 2.4vmin; }

.notice--warn { color: var(--warn); max-width: 60ch; }

/* On-screen menu for a TV without a keyboard (remote pointer, mouse, touch).
   Mirrors the emergency keys; a small dot until opened. */
.tv-menu { position: absolute; bottom: 2vmin; left: 2vmin; display: flex; align-items: center; gap: 1vmin; z-index: 10; }  /* above every board */
.tv-menu[hidden] { display: none; }
.tv-menu__toggle {
  font: inherit; font-size: 3vmin; line-height: 1; width: 6vmin; height: 6vmin; border-radius: 50%;
  border: .3vmin solid rgba(255, 255, 255, .25); background: rgba(0, 0, 0, .35); color: rgba(255, 255, 255, .55);
  cursor: pointer; padding: 0;
}
.tv-menu__toggle:hover, .tv-menu.is-open .tv-menu__toggle { color: #fff; border-color: rgba(255, 255, 255, .6); }
.tv-menu__items { display: flex; flex-wrap: wrap; gap: 1vmin; }
.tv-menu__items[hidden] { display: none; }
.tv-menu__items .btn { font-size: 2.4vmin; padding: 1.2vmin 2vmin; background: rgba(0, 0, 0, .55); border-radius: 2vmin; }
.tv-menu__items kbd { margin-left: .6em; font-size: .85em; opacity: .7; }

/* The corners wake with the mouse (owner 2026-10-13): the menu dot and the
   room code are invisible until the pointer moves (or the screen is
   touched), then fade out again a few seconds later; an open menu stays. */
.corner-code, .tv-menu { opacity: 0; pointer-events: none; transition: opacity .35s ease; }
body.is-pointer-awake .corner-code, body.is-pointer-awake .tv-menu, .tv-menu.is-open { opacity: 1; pointer-events: auto; }

/* --------------------------------------------------------------- pilot */

body.pilot { background: var(--night-deep); }

.join {
  max-width: 480px;
  margin: 0 auto;
  padding: 40px 20px;
  text-align: center;
}

.join h1 { margin: 0 0 6px; }
.join__form { display: flex; gap: 10px; justify-content: center; margin-top: 16px; }

.join__code {
  font: inherit;
  font-size: 1.8rem;
  font-weight: 700;
  letter-spacing: .3em;
  text-transform: uppercase;
  text-align: center;
  width: 12ch;
  padding: 10px;
  border-radius: 12px;
  border: 2px solid rgba(255, 255, 255, .2);
  background: var(--night);
  color: var(--ink);
}

.party { max-width: 640px; margin: 0 auto; padding: 14px 16px 40px; }

.party__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin-bottom: 12px;
}

.party__room { display: flex; align-items: center; gap: 10px; }
.party__code { font-weight: 700; letter-spacing: .2em; font-size: 1.2rem; }
.party__tv { color: var(--ink-soft); font-size: .9rem; }

.dot { width: 12px; height: 12px; border-radius: 50%; background: #ff6b6b; display: inline-block; }
.dot--on { background: #5be39b; }

.tag {
  border: 2px solid var(--warn);
  color: var(--warn);
  border-radius: 8px;
  padding: 2px 8px;
  font-size: .8rem;
  font-weight: 700;
}

.now {
  background: var(--plum);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-bottom: 10px;
}

.now__label { margin: 0; font-size: .8rem; text-transform: uppercase; letter-spacing: .1em; color: var(--mint); }
.now__label--center { text-align: center; }
.now--effects .row { margin: 10px 0 0; justify-content: center; }
.now__task { margin: 4px 0 0; font-weight: 700; font-size: 1.15rem; }
.now__left { margin: 2px 0 10px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.now__actions { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.now__actions--second { margin-top: 8px; }
/* The start board (owner's ask, 2026-10-08): one big button, 25 % of the screen's height and 80 % of its width, until the game starts. */
.restart-row { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; margin: 0 0 12px; }
.restart-row[hidden] { display: none; }
.start-board { width: 80vw; max-width: 100%; min-height: 25vh; margin: 0 auto 14px; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 10px; background: var(--plum); border-radius: var(--radius); padding: 14px; text-align: center; }
.start-board[hidden] { display: none; }
.start-board__btn { font-size: 1.4rem; padding: 16px 32px; }
.start-board__note { margin: 0; font-size: .85rem; color: var(--ink-soft); }
.blank-row { width: 80vw; max-width: 100%; margin: 0 auto 14px; display: flex; justify-content: center; }
.blank-row .switch { flex-wrap: wrap; justify-content: center; }
.blank-row .field__note { width: 100%; text-align: center; font-size: .8rem; }
.now__actions .btn.is-on { border-color: var(--mint); color: var(--mint); }

.switch { display: inline-flex; align-items: center; gap: 8px; color: var(--ink-soft); font-size: .95rem; }
.switch input[type=checkbox] { width: 20px; height: 20px; accent-color: var(--pumpkin); }
.preview-off { display: flex; margin: 4px 0 8px; }

.options { padding: 4px 4px 10px; }

.shop-row { gap: 10px; }
.shop-edit { width: 80vw; max-width: 100%; margin: 0 auto 14px; }
.shop-edit[hidden] { display: none; }
.shop-edit textarea { resize: vertical; }
.passed { margin: 12px 0 0; }
.passed[hidden], .tasks[hidden] { display: none; }
.passed__toggle { width: 100%; }
.tasks--passed { margin-top: 8px; }
.tasks { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.task-row { min-width: 0; }

.task-row {
  display: flex;
  align-items: center;
  gap: 12px;
  background: var(--night);
  border-radius: 14px;
  padding: 10px 12px;
  border: 2px solid transparent;
}

.task-row.is-shown { opacity: .6; }
.task-row.is-now { border-color: var(--pumpkin); opacity: 1; }
.task-row__body { flex: 1; min-width: 0; }
.task-row__title { margin: 0; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.task-row.is-shown .task-row__title::before { content: "✔ "; color: var(--mint); }
.task-row__note { margin: 2px 0 0; color: var(--ink-soft); font-size: .85rem; overflow-wrap: anywhere; }
.task-row .btn { padding: 10px 16px; white-space: nowrap; }
.tasks.is-locked .btn { opacity: .35; pointer-events: none; }

/* -------------------------------------------------------------- editor */

.editor { max-width: 640px; margin: 0 auto; padding: 16px 16px 48px; }
.editor h1 { margin: 0 0 12px; }
.editor__h2 { font-size: 1.1rem; margin: 22px 0 4px; color: var(--pumpkin); }
.editor__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; }
.editor__foot { margin-top: 24px; flex-wrap: wrap; }
.save-state { color: var(--ink-soft); font-size: .9rem; }

.input {
  font: inherit;
  width: 100%;
  padding: 10px 12px;
  border-radius: 12px;
  border: 2px solid rgba(255, 255, 255, .18);
  background: var(--night);
  color: var(--ink);
  /* Native widgets (calendar icon, select arrow, spinners) drawn for a dark
     background, so the date picker icon is visible on phones. */
  color-scheme: dark;
}
.input::-webkit-calendar-picker-indicator {
  cursor: pointer;
  opacity: .95;
  width: 1.4em;
  height: 1.4em;
}

.input--mono { font-family: ui-monospace, monospace; font-size: .85rem; }
.input--small { width: auto; padding: 6px 10px; }
.input--tiny { width: 7ch; padding: 6px 8px; }
.input--area { resize: vertical; margin-top: 8px; }

.row { display: flex; gap: 10px; align-items: center; margin: 10px 0; }
.row[hidden] { display: none; }  /* `hidden` must beat the flex display: the pass form showed an empty list */
.row--split > * { flex: 1; }
.row--wrap { flex-wrap: wrap; }
.row--spread { justify-content: space-between; }
.row .btn { white-space: nowrap; }

.btn--tiny { padding: 6px 10px; font-size: .9rem; }
.btn--danger { background: #ff6b6b; }

.game-list { list-style: none; margin: 0 0 10px; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 8px; }
.game-list__item {
  font: inherit; font-weight: 700; width: 100%; text-align: left;
  background: var(--plum); color: var(--ink); border: 2px solid transparent;
  border-radius: 14px; padding: 14px; cursor: pointer;
}
.game-list__item:hover { border-color: var(--pumpkin); }

.linkbox { background: var(--plum); border-radius: var(--radius); padding: 10px 14px; margin-top: 8px; }
.linkbox .row { margin: 6px 0 0; }
/* Explanations behind a "Details" button (a native disclosure, no script). */
/* The button hugs what it explains (8px) and leaves a field's worth of air (18px) below. */
.more { margin: 0 0 18px; }
.field + .more { margin-top: -6px; }
.row + .more { margin-top: -2px; }
.row--split + .more { margin-top: -16px; } /* the row's fields carry their own bottom margin */
.editor__h2 + .more { margin-top: 6px; }
.linkbox .more { margin-bottom: 2px; }
.problems + .more { margin-top: 4px; }
.more > summary { list-style: none; display: inline-block; cursor: pointer; }
.more > summary::-webkit-details-marker { display: none; }
.more[open] > summary { color: var(--gold, #c8a875); border-color: var(--gold, #c8a875); }
.more > .field__note { margin-top: 8px; }
.more > .field__note + .field__note { margin-top: 6px; }

.task-cards { list-style: none; margin: 8px 0 0; padding: 0; display: grid; grid-template-columns: minmax(0, 1fr); gap: 12px; }
.task-card { background: var(--plum); border-radius: var(--radius); padding: 12px; min-width: 0; }
.task-card__head { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.task-card__n { font-weight: 700; font-size: 1.1rem; }
.task-card__tools { margin-left: auto; display: flex; gap: 4px; flex-wrap: wrap; justify-content: flex-end; }
.task-card .input { margin-top: 8px; }
.task-card .counter { margin: 4px 0 0; font-size: .8rem; }
.problems { color: var(--warn); font-size: .92rem; min-height: 1.2em; }
.problems:empty { display: none; }

.photo-frame { position: relative; display: block; width: 100%; line-height: 0; }
.photo-frame > img:first-child { width: 100%; height: auto; border-radius: 12px; display: block; }
.photo-frame--edit { margin-top: 10px; }
.photo-frame--empty { aspect-ratio: 4 / 3; background: var(--night); border-radius: 12px; }
.photo-frame--empty::after {
  content: "📷"; position: absolute; inset: 0; display: flex; align-items: center;
  justify-content: center; font-size: 3rem; line-height: 1;
}


.preview {
  position: fixed; inset: 0; background: rgba(0, 0, 0, .85);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 14px; padding: 16px;
}
.preview[hidden] { display: none; }
.preview__tv { width: min(100%, 720px); border: 6px solid #333; border-radius: 10px; background: #000; }
.preview__screen {
  position: relative; aspect-ratio: 16 / 9; overflow: hidden; display: flex; align-items: center; justify-content: center;
  background: radial-gradient(circle at 50% 18%, var(--plum) 0%, var(--night) 45%, var(--night-deep) 100%);
  font-size: 10px;
}
.card--preview { position: relative; max-width: 90%; max-height: 90%; padding: 1.5em 2.5em; border-radius: 1.6em; gap: .8em; }  /* above the .stage__image layer */
.card--preview .card__text { font-size: 2em; }
.card--preview .photo-frame > img:first-child { max-height: 20em; width: auto; max-width: 100%; }
.card--preview .card__text[hidden] { display: none; }
.preview__screen .watermark { font-size: 1.4em; top: 1em; right: 1em; border-width: 2px; }

/* TV photo card */
.card--tv .photo-frame { width: auto; }
.card--tv .photo-frame > img:first-child { max-width: 84vw; max-height: 62vh; width: auto; }
.card--tv .photo-frame[hidden] { display: none; }

.task-row__thumb { width: 56px; height: 42px; object-fit: cover; border-radius: 8px; flex: none; }
.join__steps { max-width: 360px; margin: 14px auto 0; padding-left: 22px; text-align: left; line-height: 1.5; color: var(--ink-soft); }
.join__steps li { margin-bottom: 6px; }
.join__steps strong { color: var(--ink); word-break: break-all; }
.second-qr { width: 220px; margin: 10px auto; background: #fff; padding: 8px; border-radius: 12px; }
.second-qr svg { width: 100%; height: auto; display: block; }
.second-qr[hidden] { display: none; }
.btn.is-on { background: var(--warn); }
.options .switch { display: flex; margin: 6px 0; }
.options__mode { display: flex; gap: 18px; flex-wrap: wrap; }
/* Advanced user (owner's ask, 2026-10-08): delayed launch buttons and the effect delay switch show only then. */
body:not(.is-advanced) .task-row__later, body:not(.is-advanced) #effect-delay-wrap { display: none; }
.now__label--effects { display: flex; justify-content: center; align-items: center; gap: 14px; }
.now__label--effects .switch { display: inline-flex; margin: 0; text-transform: none; letter-spacing: 0; font-size: .9rem; color: var(--ink-soft); }
.task-row__btns { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.task-row .task-row__later { padding: 6px 10px; font-size: .85rem; }

.effects[hidden] { display: none; }
/* Round effect buttons with a line icon and the name underneath (owner's design, 2026-10-12). */
.effects { justify-content: center; gap: 14px 18px; }
/* Icon buttons: three per row (owner 2026-10-19), two for a theme with exactly four (2026-10-13: 3 + 1 looked wrong); --fx-cols from the pilot. */
.effects--grid { display: grid; grid-template-columns: repeat(var(--fx-cols, 3), max-content); justify-content: center; column-gap: 20px; }
.effects--grid[hidden] { display: none; }
.fx { display: flex; flex-direction: column; align-items: center; gap: 6px; width: 84px; padding: 0; border: 0; background: none; color: var(--ink); cursor: pointer; font: inherit; }
.fx__icon { width: 68px; height: 68px; border-radius: 50%; display: grid; place-items: center; box-sizing: border-box; border: 2.5px solid var(--gold, #c8a875); background: var(--night-deep, #16222d); box-shadow: 0 4px 12px rgba(0, 0, 0, .4); transition: transform .12s ease, background .2s ease; }
.fx__icon svg { width: 46px; height: 46px; display: block; stroke: #e6c784; fill: none; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.fx__icon svg .g { fill: #e6c784; stroke: none; }
.fx__label { font-size: .82rem; color: var(--ink-soft); text-align: center; line-height: 1.2; }
.fx:active:not(:disabled) .fx__icon { transform: scale(.94); }
.fx.is-on .fx__icon { background: var(--gold, #c8a875); }
.fx.is-on .fx__icon svg, .fx.is-on .fx__icon svg .g { stroke: var(--night-deep, #16222d); }
.fx.is-on .fx__icon svg .g { fill: var(--night-deep, #16222d); stroke: none; }
.fx:disabled { opacity: .35; cursor: default; }
.btn:disabled { opacity: .35; cursor: default; }  /* every greyed button looks greyed: Hide now, Keep on screen, effects */

.help { margin: 18px 0 0; color: var(--ink-soft); font-size: .92rem; line-height: 1.45; }
.help summary { cursor: pointer; font-weight: 600; color: var(--ink); }
.help p { margin: 6px 0 0; }

/* ---- account and passes (M5) */
.account { max-width: 420px; margin: 0 auto; padding: 24px 16px 48px; }
.account h1 { margin: 0 0 4px; }
.account .lead { color: var(--ink-soft); margin: 0 0 18px; }
.tabs { display: flex; gap: 6px; margin-bottom: 14px; }
/* The admin page: wide tables that scroll sideways on a phone (2026-10-14). */
.admin { max-width: 1100px; }
.admin .count { font-weight: 400; color: var(--ink-soft); font-size: .9rem; }
.table-wrap { overflow-x: auto; margin-bottom: 18px; }
.admin-table { border-collapse: collapse; width: 100%; font-size: .9rem; }
.admin-table th, .admin-table td { text-align: left; padding: 6px 10px; border-bottom: 1px solid rgba(200, 168, 117, .22); white-space: nowrap; vertical-align: top; }
.admin-table th { color: var(--ink-soft); font-weight: 600; }
.tabs .btn { flex: 1; }
.tabs .btn[aria-selected=true] { outline: 3px solid var(--mint); outline-offset: 1px; }
.notice { background: var(--plum); border-radius: var(--radius); padding: 12px 14px; margin: 12px 0; line-height: 1.5; }
.notice--error { border: 1px solid #ff6b6b; }
.account-bar { display: flex; justify-content: space-between; align-items: center; gap: 10px; color: var(--ink-soft); font-size: .92rem; margin-bottom: 10px; flex-wrap: wrap; }
/* "Your games": one tag per game (owners 2026-10-16). */
#pass-box { margin-bottom: 14px; }
#pass-box .field__note:empty { display: none; }
.game-tag { display: inline-block; vertical-align: middle; margin-left: 8px; padding: 2px 8px; border-radius: 999px;
  font-size: .72rem; font-weight: 800; letter-spacing: .06em; background: #3a2f5c; color: #e6dcff; }
.game-tag--party, .game-tag--live { background: #1f4a3d; color: #bff0dc; }
.game-tag--played { background: #333; color: #bbb; }
.game-list--played .game-list__item, .game-list--older .game-list__item { opacity: .65; }
.game-list[hidden] { display: none; }  /* the grid rule above would beat the hidden attribute */
.link--button { background: none; border: 0; padding: 0; font: inherit; text-decoration: underline; cursor: pointer; }
.game-list__meta { display: block; font-size: .85rem; color: var(--ink-soft); }
.link { color: var(--mint); }

/* The photo cropper in the editor (owner's ask, 2026-10-08): a sheet with
   a frame in the theme's photo aspect; the picture moves under it. */
.crop { position: fixed; inset: 0; z-index: 40; background: rgba(0, 0, 0, .8); display: flex; align-items: center; justify-content: center; padding: 12px; }
.crop[hidden] { display: none; }
.crop__sheet { width: min(100%, 560px); background: var(--night); border-radius: var(--radius); padding: 14px 16px; display: flex; flex-direction: column; gap: 10px; }
.crop__title { margin: 0; font-weight: 700; font-size: 1.1rem; }
.crop__box { position: relative; width: 100%; aspect-ratio: 16 / 9; overflow: hidden; background: #000; border-radius: 10px; touch-action: none; user-select: none; cursor: grab; }
.crop__box img { position: absolute; left: 0; top: 0; max-width: none; pointer-events: none; }
.crop__zoom { display: flex; align-items: center; gap: 10px; }
.crop__zoom input { flex: 1; }
