:root {
  --bg: #0b0d12; --fg: #eef1f6; --muted: #9aa3b2; --accent: #5aa0ff;
  --card: #151922; --line: #262c38; --warn: #ffcf57; --danger: #ff5d5d;
}
* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; background: var(--bg); color: var(--fg);
  font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; -webkit-text-size-adjust: 100%; }
body { min-height: 100dvh; }
a { color: var(--accent); }
.wrap { max-width: 560px; margin: 0 auto; padding: 20px; }
h1 { font-size: 1.5rem; margin: 0 0 8px; }
h2 { font-size: 1.1rem; margin: 18px 0 6px; }
p { line-height: 1.5; color: var(--fg); }
.muted { color: var(--muted); font-size: .92rem; }
.card { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 16px; margin: 14px 0; }
.warn { border-color: var(--warn); }
.warn b { color: var(--warn); }
button, .btn { font: inherit; cursor: pointer; border-radius: 12px; border: 1px solid var(--line);
  background: #1d2330; color: var(--fg); padding: 14px 18px; width: 100%; margin-top: 10px; }
button.primary { background: var(--accent); color: #04122b; border-color: var(--accent); font-weight: 700; }
button.ghost { background: transparent; }
/* light-blue (голубой) call-to-action — the "turn on the flashlight" button */
button.accent-blue { background: #2bc0ee; color: #042233; border-color: #2bc0ee; font-weight: 700; }
button:disabled { opacity: .5; cursor: default; }
.row { display: flex; gap: 10px; }
.row > * { flex: 1; }
.pill { display: inline-block; padding: 4px 10px; border-radius: 999px; background: #1d2330; color: var(--muted); font-size: .8rem; }
.lang { position: absolute; top: 10px; right: 12px; font-size: .85rem; }
.lang a { margin-left: 8px; cursor: pointer; }
.credit { margin-top: 18px; font-size: .82rem; color: var(--muted); text-align: center; }
.hidden { display: none !important; }

/* full-screen flash layer for the audience */
#flash { position: fixed; inset: 0; background: #000; z-index: 1; transition: none; }
/* #stage scrolls so the consent screen is fully reachable on short/phone viewports;
   it is transparent, so the fixed #flash layer shows through behind it. */
#stage { position: fixed; inset: 0; z-index: 2; overflow-y: auto; -webkit-overflow-scrolling: touch; }
#stage .wrap { min-height: 0; padding-bottom: 40px; }
#stopbtn { position: fixed; top: 12px; right: 12px; z-index: 3; width: auto; margin: 0;
  pointer-events: auto; background: rgba(0,0,0,.55); border-color: rgba(255,255,255,.4); color: #fff; padding: 10px 14px; }
#statuspill { position: fixed; bottom: 12px; left: 50%; transform: translateX(-50%); z-index: 3;
  background: rgba(0,0,0,.5); color: #fff; padding: 6px 12px; border-radius: 999px; font-size: .8rem; pointer-events: none; }
#brightToast { position: fixed; bottom: 52px; left: 50%; transform: translateX(-50%); z-index: 4;
  max-width: 86vw; text-align: center; background: rgba(20,16,4,.92); color: var(--warn);
  border: 1px solid var(--warn); padding: 10px 16px; border-radius: 999px; font-size: .9rem;
  font-weight: 600; pointer-events: none; box-shadow: 0 4px 18px rgba(0,0,0,.5); }
#wave { position: fixed; left: 8px; width: calc(100vw - 16px); bottom: 44px; height: 44px; z-index: 3;
  background: rgba(0,0,0,.5); border-radius: 8px; pointer-events: none; }
#diag { position: fixed; left: 8px; bottom: 12px; z-index: 4; font-size: 11px; color: #9aa3b2;
  background: rgba(0,0,0,.55); padding: 3px 7px; border-radius: 6px; pointer-events: none; font-variant-numeric: tabular-nums; }

/* operator */
table { width: 100%; border-collapse: collapse; }
td, th { text-align: left; padding: 6px 4px; border-bottom: 1px solid var(--line); font-size: .92rem; }
.qrbox { background: #fff; padding: 14px; border-radius: 14px; text-align: center; }
.qrbox img { width: 100%; max-width: 320px; image-rendering: pixelated; }
.big { font-size: 2rem; font-weight: 800; }
.transport button { width: auto; }
#blackout { background: var(--danger); color: #fff; border-color: var(--danger); font-weight: 800; }
.nudge { display: flex; align-items: center; gap: 10px; }
.nudge input { flex: 1; }
input[type=password], input[type=text] { width: 100%; padding: 12px; border-radius: 10px; border: 1px solid var(--line);
  background: #0f131b; color: var(--fg); font: inherit; }

/* Round 10: responsive operator/studio console — use the full width on desktop instead of a
   560px phone-strip. Scoped to .op-console (operator.html ONLY); the audience /join page uses
   bare .wrap and is untouched. Mobile = unchanged single column. Robust to public-mode
   hide/reorder: a 2- then 3-column grid that flows cards; top-level header/welcome/play/status/
   credit span all columns. */
@media (min-width: 980px) {
  .op-console { max-width: 1240px; display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 16px; align-items: start; grid-auto-flow: row dense; }
  .op-console > h1, .op-console > #pubWelcome, .op-console > #playSound,
  .op-console > p.muted, .op-console > .credit, .op-console > details { grid-column: 1 / -1; }
  .op-console .card { margin: 0; }
}
@media (min-width: 1440px) {
  .op-console { max-width: 1560px; grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
/* Advanced-controls disclosure (public studio): laid out as its own full-width grid inside */
.op-adv { margin: 14px 0; }
.op-adv > summary { cursor: pointer; padding: 12px 16px; background: var(--card); border: 1px solid var(--line);
  border-radius: 12px; list-style: none; font-weight: 600; color: var(--muted); }
.op-adv[open] > summary { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
.op-adv > summary::-webkit-details-marker { display: none; }

/* round 11 — progressive disclosure (pt 2): on /studio, only the Start button shows until the first
   Start; .reveal blocks (STOP/BLACKOUT, the cards, presets, QR, share) appear when .pre-start clears. */
.op-console.pre-start .reveal,
.op-console.pre-start #shareBlock { display: none !important; }
/* the Start button's loading spinner (pt 2) — pure CSS, no asset */
.spin { display: inline-block; width: 0.9em; height: 0.9em; vertical-align: -0.1em; margin-left: 6px;
  border: 2px solid rgba(0,0,0,.25); border-top-color: #04222c; border-radius: 50%; animation: cls-spin 0.7s linear infinite; }
@keyframes cls-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) { .spin { animation: none; } }
/* round 11 (pt 10): the Live-presets card fills its full-width disclosure (not a narrow column) */
#studioCard { width: 100%; }
/* round 11 (pt 19): the audience scrolling marquee — a SEPARATE text overlay above the flash layer
   (z-index 4 > #flash 1 / #stage 2). Text + translucent bg only; a smooth horizontal transform (no
   luminance pulsing) so it can never affect the epilepsy flash-rate cap. Short text simply repeats. */
#marquee { position: fixed; left: 0; right: 0; bottom: env(safe-area-inset-bottom, 0); z-index: 4;
  overflow: hidden; white-space: nowrap; pointer-events: none; background: rgba(0,0,0,.45); color: #fff;
  font: 600 5vw/1.6 system-ui, -apple-system, sans-serif; text-shadow: 0 1px 3px #000; padding: 6px 0; }
#marquee.hidden { display: none; }
#marqueeInner { display: inline-block; padding-left: 100%; animation: cls-marq 12s linear infinite; }
@keyframes cls-marq { from { transform: translateX(0); } to { transform: translateX(-100%); } }

/* round 16 (#1): the SHARE-THIS-SHOW QR on the audience's live (flashing) screen.
   SIZE — a QR is read reliably at roughly 10x its own width, and a friend's camera is 30-50 cm away,
   so it has to be a real object (~3 cm), not a badge: min(44vw, 26vh, 186px) lands at ~29-30 mm on a
   phone, which a modern camera reads comfortably at 30-40 cm while leaving most of the screen to the
   light show. The 26vh term keeps a short/landscape screen from being swallowed by it, and the 186px
   cap stops a tablet painting a billboard. At 600px source / ~180px box a DPR-2/3 phone downsamples
   by <=1.7x, so the modules stay crisp (image-rendering: pixelated, like the console .qrbox).
   PLACE — bottom-centre, ABOVE the waveform strip (which owns 44-88px), clear of the top-right Stop
   button and the bottom marquee. The whole upper screen therefore stays pure colour: the light show
   itself (and photos of it) is unchanged, and the code sits on the edge nearest a person beside you.
   CONTRAST — solid white card with a dark ring: it must still scan over a WHITE flash frame, so the
   card can never be translucent. It is a static image: no luminance change, no effect on the flash-
   rate governor. */
#shareQr { position: fixed; left: 50%; transform: translateX(-50%); z-index: 5;
  bottom: calc(116px + env(safe-area-inset-bottom, 0px));
  display: flex; flex-direction: column; align-items: center; gap: 6px; max-width: 92vw; }
#shareQrCap { background: rgba(0,0,0,.62); color: #fff; font-size: .76rem; font-weight: 600;
  line-height: 1.25; text-align: center; padding: 4px 10px; border-radius: 999px; max-width: 86vw;
  text-shadow: 0 1px 2px #000; pointer-events: none; }
#shareQrBox { position: relative; padding: 8px; line-height: 0; border-radius: 14px; cursor: pointer;
  background: #fff; border: 2px solid rgba(0,0,0,.55); box-shadow: 0 6px 22px rgba(0,0,0,.45); }
#shareQrImg { display: block; width: min(44vw, 26vh, 186px); height: auto; aspect-ratio: 1 / 1;
  image-rendering: pixelated; }
/* The explicit "hide" affordance — a real ✕ beside the card, so nobody has to guess that the card is
   tappable. 44x44 to meet the WCAG 2.5.8 target size, and placed just OUTSIDE the card rather than on
   its corner: overlapping the quiet zone (or the top-right finder pattern behind it) is exactly what
   makes a code fail to scan in a dark room, which is the one job this code has. */
#shareQrHide { position: absolute; top: -6px; right: -52px; width: 44px; height: 44px; margin: 0;
  padding: 0; border-radius: 50%; font-size: 15px; line-height: 1; display: flex; align-items: center;
  justify-content: center; background: rgba(0,0,0,.82); color: #fff; border: 1px solid rgba(255,255,255,.45);
  box-shadow: 0 2px 8px rgba(0,0,0,.5); }
#shareQrPill { position: fixed; right: 12px; z-index: 5; width: auto; margin: 0;
  bottom: calc(116px + env(safe-area-inset-bottom, 0px)); padding: 8px 12px; font-size: .85rem;
  background: rgba(0,0,0,.6); color: #fff; border-color: rgba(255,255,255,.4); }
/* Short screens (a phone in landscape): drop the caption and lean on the WIDTH, which is plentiful
   there — sizing off 30vh gave ~19 mm, well under the ~3 cm this file says a camera needs, so the
   code stopped being scannable exactly where there was room for it. */
@media (max-height: 560px) {
  #shareQrImg { width: min(26vw, 46vh, 168px); }
  #shareQrCap { display: none; }
}

/* round 14: VJ pult faux-fullscreen (when the Fullscreen API is unavailable, e.g. iOS Safari) */
#vjCard.vj-faux-full { position: fixed; inset: 0; z-index: 9999; margin: 0; overflow: auto; border-radius: 0; }
#vjCard:fullscreen { overflow: auto; padding: 18px; }
#vjStage { user-select: none; -webkit-user-select: none; touch-action: none; }
/* round 16.2: the XY pad grew, so its vertical faders grow with it — a 170 px fader next to a 300 px
   pad reads as broken, and the pad itself needs the room to make a hue drag precise. */
#vjStage .vj-fader-track { height: min(52vh, 420px); min-height: 300px; }

/* round 15c: audience /join — grandma-test flow. One big confirm button on the first screen; after it,
   a prominent flashlight join + a quiet screen-only fallback so people reach for the flashlight more. */
.cls-bigcta { width: 100%; padding: 18px 16px; font-size: 1.15rem; font-weight: 800; margin-top: 12px; border-radius: 12px; }
#joinScreen.cls-quiet { background: transparent; color: #9aa3b2; border: 1px solid rgba(255,255,255,.16); box-shadow: none; font-weight: 600; padding: 11px 14px; font-size: .96rem; margin-top: 10px; }
.cls-how { margin-top: 16px; }
.cls-how > summary { cursor: pointer; color: #8b93a7; font-size: .9rem; padding: 6px 0; }
.cls-how p { margin-top: 8px; }
.cls-jointip { margin-top: 16px; font-size: .96rem; text-align: center; }

/* ---------------------------------------------------------------------------
   HSG-Fork: Platzzuordnung auf der Publikumsseite. Ein einziges Eingabefeld fuer die
   hallenweit eindeutige Platznummer, gross genug fuer Daumen im Dunkeln, plus die
   Bereichsauswahl als Rueckfallebene fuer Steh- und Gaesteplaetze.
   --------------------------------------------------------------------------- */
#seatBox label { display: block; margin-bottom: 2px; }
.cls-seat-sub { margin: 2px 0 12px; font-size: .86rem; }
#seatInput { font-size: 1.6rem; font-weight: 700; text-align: center; letter-spacing: .08em; padding: 14px 12px; }
#seatInput.ok { border-color: #3ddc84; }
#seatInput.bad { border-color: var(--danger); }
.cls-seat-msg { min-height: 1.35em; margin: 8px 0 0; font-size: .92rem; line-height: 1.35; }
.cls-seat-msg.ok { color: #3ddc84; font-weight: 600; }
.cls-seat-msg.bad { color: var(--danger); }
.cls-seat-msg.busy { color: var(--muted); }
/* Textknopf: sieht wie ein Link aus, ist aber ein Knopf (Tastatur + Screenreader) */
.cls-linkbtn { all: unset; cursor: pointer; display: inline-block; margin-top: 12px; color: var(--accent);
  font-size: .9rem; text-decoration: underline; text-underline-offset: 3px; }
.cls-linkbtn:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; border-radius: 4px; }
.cls-blocklist { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.cls-blocklist button { width: auto; flex: 1 1 44%; margin-top: 0; padding: 12px 10px; font-size: .95rem; text-align: center; }
.cls-blocklist button.on { background: var(--accent); color: #04122b; border-color: var(--accent); font-weight: 700; }
/* Waehrend der Show: dezente Erinnerung, auf welchem Platz dieses Handy angemeldet ist */
.cls-seatpill { display: inline-block; margin: 6px 0 0; padding: 5px 12px; border-radius: 999px;
  background: #1d2330; color: var(--muted); font-size: .82rem; }
.cls-seatpill button { all: unset; cursor: pointer; margin-left: 8px; color: var(--accent); text-decoration: underline; font-size: .82rem; }

/* HSG-Fork: Blockleiste unter der Hallenansicht -- wie viele Handys je Block mitmachen. */
.hall-blocks { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.hall-blocks .hb { flex: 1 1 110px; background: #151922; border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; }
.hall-blocks .hb-name { font-size: .76rem; color: var(--muted); }
.hall-blocks .hb-num { font-size: 1.05rem; font-weight: 700; }
.hall-blocks .hb-bar { height: 4px; border-radius: 2px; background: #242c3a; margin-top: 4px; overflow: hidden; }
.hall-blocks .hb-fill { height: 100%; background: #5aa0ff; }
#cardHall.hall-full { position: fixed; inset: 0; z-index: 9999; margin: 0; overflow: auto; border-radius: 0; }
