/* The guest phones: "Live".

   Chosen by Scott on 26 October 2026, from three directions drawn as a brand-new iPhone
   app (Live, Pass, Poster), after he asked to start the phones' design over. Live is
   modelled on Apple's Live Activities and its Sports app: a glowing pill at the top says
   what is live, one big card carries the thing that matters, the numbers are huge and
   lime, and everything else stays quiet. It is dark first, because the room is dim and
   the television is near-black, and it has a light twin for phones set to light mode,
   which keeps the same jobs for the lime: the live dot, the main button, the leader, and
   the card that matters.

   Loaded after styles.css by the guest pages only (index, board, 404), which carry
   html.ios. The host console never loads it.

   Carried over, because they were decided rather than styled:
   - One accent, the lime (22 September 2026). On dark it is a word, a figure and a fill.
     On light it is only ever a fill, with dark ink on it: the bright lime is 1.4:1 on a
     light ground.
   - Every word clears 4.5:1 on its own ground.
   - The states keep their meanings (saved, queued, error, locked, changed, over the max),
     as the colour of the number and the glyph beside it.
   - A text glyph never stands in for an icon: the sign key is drawn. */

html.ios {
  color-scheme: dark light;
  /* Dark first. */
  --bg:            #000000;
  --surface:       #1C1C1E;
  --surface-2:     #2C2C2E;
  --surface-sunk:  #2C2C2E;
  --feature:       #1C1C1E;
  --feature-2:     #2C2C2E;
  --feature-raise: #2C2C2E;
  --fill:          rgba(118,118,128,0.26);
  --ink:           #F5F5F7;
  --ink-soft:      #D1D1D6;
  --ink-mute:      #9A9AA1;   /* 6.1:1 on a card */
  --ink-ghost:     #5A5A60;
  --on-feature:    #F5F5F7;
  --on-feature-mute:#9A9AA1;
  --figure:        #BDDA4F;   /* the big numbers */
  --figure-glow:   0 0 40px rgba(189,218,79,0.35);
  --line:          rgba(84,84,88,0.55);
  --card-shadow:   0 0 0 0 transparent;
  --lime-shadow:   0 12px 34px rgba(189,218,79,0.26);
  --stake-bg:      #1C1C1E;   /* the card that matters */
  --stake-ink:     #F5F5F7;
  --stake-mute:    #9A9AA1;
  --state-saved:   #30D158;  --state-saved-bg: #12301A;
  --state-queued:  #FFB340;  --state-queued-bg:#3A2A0C;
  --state-error:   #FF6961;  --state-error-bg: #3B1412;
  --state-lock:    #9A9AA1;  --state-lock-bg:  #2C2C2E;
  --font-ui:  -apple-system, BlinkMacSystemFont, "SF Pro Text", system-ui, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  --font-dsp: -apple-system, BlinkMacSystemFont, "SF Pro Display", system-ui, "Segoe UI", Roboto, sans-serif;
  --font-num: ui-rounded, "SF Pro Rounded", -apple-system, BlinkMacSystemFont, system-ui, "Segoe UI", Roboto, sans-serif;
  --r-card: 28px; --r-big: 40px; --r-tile: 18px;
  /* The shared rules list these inside box-shadow lists, so they become a shadow that
     draws nothing rather than none, which would make every such list invalid. */
  --lift-1:     0 0 0 0 transparent;
  --lift-2:     0 0 0 0 transparent;
  --lift-press: 0 0 0 0 transparent;
  --edge-dark:  0 0 0 0 transparent;
  --edge-light: 0 0 0 0 transparent;
}
/* The light twin. Same layout and the same jobs for the lime; the card that matters turns
   lime with dark ink on it, because a lime figure cannot sit on a light card. A haunted night
   is dark on every phone, so every light rule skips html.haunted, inside :where() so that it
   weighs no more than it did. */
@media (prefers-color-scheme: light) {
  html.ios:where(:not(.haunted)) {
    --bg:            #F2F2F7;
    --surface:       #FFFFFF;
    --surface-2:     #F2F2F7;
    --surface-sunk:  #E5E5EA;
    --feature:       #FFFFFF;
    --feature-2:     #F2F2F7;
    --feature-raise: #FFFFFF;
    --fill:          rgba(120,120,128,0.14);
    --ink:           #0B0B0D;
    --ink-soft:      #3A3A3F;
    --ink-mute:      #55555B;   /* 6.6:1 on the ground */
    --ink-ghost:     #AEAEB2;
    --on-feature:    #0B0B0D;
    --on-feature-mute:#55555B;
    --figure:        #0B0B0D;
    --figure-glow:   none;
    --line:          rgba(60,60,67,0.16);
    --card-shadow:   0 1px 2px rgba(0,0,0,0.05), 0 10px 28px rgba(0,0,0,0.07);
    --lime-shadow:   0 12px 30px rgba(141,170,36,0.32);
    --stake-bg:      #BDDA4F;
    --stake-ink:     #1F2A05;
    --stake-mute:    #3A4710;   /* 6.4:1 on lime */
    --state-saved:   #1D6B32;  --state-saved-bg: #E3F1E6;
    --state-queued:  #8A4B00;  --state-queued-bg:#FBEBD7;
    --state-error:   #B3261E;  --state-error-bg: #FBE4E2;
    --state-lock:    #55555B;  --state-lock-bg:  #E5E5EA;
  }
}

html.ios body { background: var(--bg); color: var(--ink); font-size: 17px; line-height: 1.35; }
@media (prefers-color-scheme: light) {
  html.ios:where(:not(.haunted)) body { background: radial-gradient(110% 38% at 50% -6%, rgba(189,218,79,0.30), transparent 70%) no-repeat, #F2F2F7; }
}
/* An app's words are not a document's: a long press on a label does not select it. */
html.ios .app-shell { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }
html.ios .app-shell input { -webkit-user-select: text; user-select: text; }
html.ios ::selection { background: rgba(189,218,79,0.5); }
html.ios input { caret-color: #BDDA4F; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) input { caret-color: #0B0B0D; } }
html.ios button:focus-visible, html.ios summary:focus-visible { outline: 3px solid #BDDA4F; outline-offset: 2px; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) button:focus-visible, html.ios:where(:not(.haunted)) summary:focus-visible { outline-color: #0B0B0D; } }
html.ios .app-top, html.ios .entry { padding-inline: 20px; }

/* The live pill replaces the bottom band: where the night is, said once, at the top. The
   bands' script still runs and its words stay in the page for anything reading them. */
html.ios .app-bot, html.ios .app-credit { display: none; }
/* What the screen already makes obvious, it no longer says. */
html.ios .signup-hint, html.ios .standby-cheeky, html.ios #standbyTeam, html.ios #v-scoring .topbar,
html.ios #v-leaderboard .topbar .sub, html.ios #roundsHelp, html.ios .reveal-head .eyebrow, html.ios .who-label,
html.ios #v-signup .hero-icn, html.ios #etTeam { display: none; }
html.ios label[for="teamName"], html.ios label[for="ladAnswer"] {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---------------- the top: the live pill, and the team on the ladder ---------------- */
html.ios .app-top { display: flex; flex-direction: column; align-items: center; padding-top: 10px; }
html.ios .live-pill { display: inline-flex; align-items: center; gap: 9px; padding: 9px 16px; border-radius: 999px;
  background: var(--surface); box-shadow: var(--card-shadow); font: 600 15px/1.2 var(--font-ui); color: var(--ink); }
html.ios .live-pill.hidden { display: none; }
html.ios .live-pill i { width: 9px; height: 9px; border-radius: 50%; background: #BDDA4F;
  box-shadow: 0 0 0 4px rgba(189,218,79,.18), 0 0 14px rgba(189,218,79,.9); animation: pill-live 2.4s ease-in-out infinite; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .live-pill i { box-shadow: 0 0 0 4px rgba(189,218,79,.35); } }
@keyframes pill-live { 50% { opacity: .55; } }
/* Offline, the dot stops breathing and goes grey: it cannot say "live" while it cannot hear. */
html.ios .live-pill.is-offline i { animation: none; background: var(--ink-ghost); box-shadow: none; }
html.ios .who { align-self: stretch; justify-content: center; gap: 10px; margin: 8px 0 0; min-height: 36px; }
html.ios .who-name { font: 600 16px/1.3 var(--font-ui); color: var(--ink-mute); }
html.ios .who-change { min-height: 36px; margin: 0; padding: 4px 6px; font: 600 16px/1.3 var(--font-ui); color: var(--ink); text-decoration: none; }

/* ---------------- titles ---------------- */
html.ios .topbar h1 { margin: var(--s-6) 0 var(--s-2); font: 800 40px/1.06 var(--font-dsp); letter-spacing: -0.01em; text-wrap: balance; }
html.ios .topbar .sub { margin: 0 0 var(--s-6); font: 500 19px/1.4 var(--font-ui); color: var(--ink-mute); }
html.ios .pane-title { margin-bottom: var(--s-3); padding-left: 0; font: 800 30px/1.1 var(--font-dsp); letter-spacing: 0; }
html.ios .hero-headline, html.ios .locked-answer, html.ios .reveal-rname, html.ios .board-hero-title, html.ios .board-state h1 { text-wrap: balance; }
html.ios .big-label, html.ios .taken-names-label, html.ios .reveal-group {
  display: block; margin: var(--s-5) 0 var(--s-2); padding: 0 4px;
  font: 600 15px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--ink-mute);
}
html.ios .pick-help, html.ios .help, html.ios .lad-action .field-caption {
  margin: var(--s-3) 0 0; padding: 0 4px; font: 500 15px/1.4 var(--font-ui); color: var(--ink-mute); text-align: center;
}

/* ---------------- controls ---------------- */
/* A button switches on at once, as an iPhone's does. The shared rule fades the background
   and not the words, so in the dark twin the label all but vanished, dark ink on dark grey,
   for the fifth of a second the lime took to arrive. */
html.ios .btn-primary, html.ios .btn-secondary {
  min-height: 64px; margin-top: var(--s-4); padding: 18px 22px; border-radius: 999px; box-shadow: none;
  font: 700 20px/1.2 var(--font-ui); transition: transform var(--t-press) var(--ease);
}
html.ios .btn-primary { background: #BDDA4F; color: #1F2A05; box-shadow: var(--lime-shadow); }
html.ios .btn-primary:active { transform: scale(.97); }
/* These two sit on the ground, not on a card, so they take the sunk grey: in the light twin
   the card grey is the ground's own colour, and the button's shape vanished. */
html.ios .btn-primary:disabled { background: var(--surface-sunk); color: var(--ink-mute); box-shadow: none; }
html.ios .btn-secondary { background: var(--surface-sunk); color: var(--ink); }
html.ios .btn-secondary:active { transform: scale(.97); box-shadow: none; }
html.ios .lad-lock { min-height: 78px; font-size: 24px; font-weight: 800; }
html.ios .lad-lock:not(:disabled) { background: #BDDA4F; color: #1F2A05; box-shadow: var(--lime-shadow); }

html.ios .select-lg {
  min-height: 66px; padding: 18px 48px 18px 22px; border-radius: 20px;
  font: 600 21px/1.3 var(--font-ui); color: var(--ink); background-color: var(--surface); box-shadow: var(--card-shadow);
  background-position: right 22px center;
}
html.ios input.select-lg { padding-right: 22px; }
html.ios #ladAnswer { font-size: 21px; font-weight: 600; }
html.ios .select-lg::placeholder { color: var(--ink-mute); font-weight: 500; }
html.ios .select-lg:focus-visible, html.ios input.select-lg:focus { outline: none; box-shadow: 0 0 0 2.5px #BDDA4F; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .select-lg:focus-visible, html.ios:where(:not(.haunted)) input.select-lg:focus { box-shadow: 0 0 0 2.5px #0B0B0D, var(--card-shadow); } }
html.ios .select-lg:active { transform: none; }
html.ios .select-lg.is-set { background-color: var(--surface); color: var(--ink); box-shadow: var(--card-shadow); background-position: right 22px center; }

html.ios .warn { background: var(--state-queued-bg); color: var(--state-queued); box-shadow: none; border-radius: var(--r-tile); padding: 14px 16px; font: 600 15px/1.4 var(--font-ui); }
html.ios .taken-names { margin-top: auto; padding-top: var(--s-6); border-top: 0; }
html.ios .taken-names-list { gap: 8px; }
html.ios .taken-chip { padding: 9px 15px; background: var(--surface); color: var(--ink); box-shadow: var(--card-shadow); font: 600 15px/1.2 var(--font-ui); }

/* The two tabs are an iPhone segmented control: one raised thumb that slides to the tab
   you pick, rather than two buttons taking turns to light up. */
html.ios .tabbar { position: relative; margin-bottom: var(--s-5); padding: 3px; gap: 3px; border-radius: 14px; background: var(--fill); box-shadow: none; }
html.ios .tabbar::before { content: ""; position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc(50% - 4.5px); border-radius: 11px;
  background: #636366; box-shadow: 0 3px 8px rgba(0,0,0,.25); transition: transform var(--t-state) var(--ease); }
html.ios .tabbar:has(.tab:last-child[aria-selected="true"])::before { transform: translateX(calc(100% + 3px)); }
html.ios .tab { position: relative; z-index: 1; min-height: 42px; padding: 9px 12px; border-radius: 11px; font: 700 16px/1.25 var(--font-ui); color: var(--ink); }
html.ios .tab[aria-selected="true"] { background: transparent; color: #FFFFFF; box-shadow: none; }
@media (prefers-color-scheme: light) {
  html.ios:where(:not(.haunted)) .tabbar::before { background: #FFFFFF; box-shadow: 0 3px 8px rgba(0,0,0,.12), 0 3px 1px rgba(0,0,0,.04); }
  html.ios:where(:not(.haunted)) .tab[aria-selected="true"] { color: #0B0B0D; }
}

html.ios .catchup-bar { position: sticky; top: 0; z-index: 3; padding: 16px 18px; border-radius: 18px; background: #BDDA4F; color: #1F2A05; box-shadow: var(--lime-shadow); font: 700 16px/1.35 var(--font-ui); }
html.ios .offline-bar { padding: 15px 20px; background: rgba(58,58,60,.96); color: #FFFFFF; box-shadow: 0 10px 30px rgba(0,0,0,.35); font: 600 15px/1.35 var(--font-ui); }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .offline-bar { background: rgba(28,28,30,.94); } }

/* ---------------- the waiting screens ----------------
   A glyph inside a glowing lime ring, a large title, one line. Nothing else. */
html.ios .hero-card { padding: 0 var(--s-3); background: transparent; color: var(--ink); box-shadow: none; text-align: center; overflow: visible; }
html.ios .hero-card .hero-icn { display: grid; place-items: center; width: 196px; height: 196px; margin: 0 auto var(--s-6); border-radius: 50%;
  background: transparent; color: #BDDA4F; box-shadow: inset 0 0 0 7px #BDDA4F, 0 0 60px rgba(189,218,79,.32), inset 0 0 40px rgba(189,218,79,.16); }
html.ios .hero-card .hero-icn svg { width: 88px; height: 88px; }
@media (prefers-color-scheme: light) {
  html.ios:where(:not(.haunted)) .hero-card .hero-icn { background: #BDDA4F; color: #1F2A05; box-shadow: 0 0 0 10px rgba(189,218,79,.28), 0 18px 40px rgba(141,170,36,.35); }
}
html.ios .hero-card .eyebrow { display: block; margin-bottom: var(--s-2); font: 600 17px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--ink-mute); }
html.ios .hero-headline { margin: 0 0 var(--s-3); font: 800 44px/1.04 var(--font-dsp); letter-spacing: -0.01em; color: var(--ink); }
html.ios .hero-sub { max-width: 28ch; margin: 0 auto; font: 600 20px/1.4 var(--font-ui); color: var(--ink-mute); }
html.ios .breathe-dot { margin-top: var(--s-5); background: #BDDA4F; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .breathe-dot { background: #1F2A05; } }
/* Phones down reads title first: the stage is the headline, the round is the line under it. */
html.ios #v-standby .hero-card { display: flex; flex: 1; flex-direction: column; align-items: center; }
html.ios #v-standby .hero-icn { margin-top: auto; }
html.ios #v-standby .eyebrow { order: 1; margin: 0; font: 800 48px/1.04 var(--font-dsp); letter-spacing: -0.01em; color: var(--ink); }
html.ios #v-standby .hero-headline { order: 2; margin: var(--s-3) 0 0; font: 600 21px/1.35 var(--font-ui); color: var(--ink-mute); }
html.ios #v-standby .monitor-strip { order: 3; margin-top: auto; }
html.ios .monitor-strip { padding: 11px 17px; background: var(--surface); box-shadow: var(--card-shadow); }
html.ios .monitor-text { font: 600 15px/1.2 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--ink); }
html.ios .monitor-dot { background: #FF453A; }
html.ios .hold-card { padding: 36px 24px 30px; border-radius: var(--r-big); background: var(--stake-bg); box-shadow: var(--card-shadow); }
html.ios .hold-card .hero-headline { margin: 0; font-size: 34px; color: var(--stake-ink); }
html.ios .hold-card .breathe-dot { background: #BDDA4F; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .hold-card .breathe-dot { background: #1F2A05; } }
html.ios #ladClosed .hero-card { padding: 32px 24px; border-radius: var(--r-big); background: var(--surface); box-shadow: var(--card-shadow); }
html.ios #ladClosed .hero-headline { font-size: 34px; }

html.ios .gag-card .gag-line { max-width: 28ch; margin: 0 auto var(--s-4); color: var(--ink); font: 600 19px/1.4 var(--font-ui); }
html.ios .gag-card .hero-icn { width: 150px; height: 150px; }
html.ios .gag-card .hero-icn svg { width: 68px; height: 68px; }
html.ios .gag-counter { justify-content: center; align-items: baseline; padding: 14px 18px; border-top: 0; border-radius: 18px; background: var(--surface); box-shadow: var(--card-shadow); }
html.ios .gag-counter-label { font: 600 15px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--ink-mute); }
html.ios .gag-count { font: 800 30px var(--font-num); color: var(--figure); }
html.ios .gag-toggle { min-height: 44px; color: var(--ink); text-decoration: underline; text-underline-offset: 3px; font: 600 17px var(--font-ui); }
html.ios .gag-fine { color: var(--ink-mute); text-align: left; font-size: 15px; }
html.ios .gag-fine strong { color: var(--ink); }

/* ---------------- the Clue Ladder ----------------
   One big card: the clue, a huge number, and the five worths with the live one lit. */
html.ios .stake { padding: 26px 24px 24px; border-radius: var(--r-big); background: var(--stake-bg); color: var(--stake-ink); box-shadow: var(--card-shadow); }
html.ios .stake-eyebrow { font: 600 18px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--stake-mute); }
html.ios .stake-figure { display: flex; align-items: baseline; gap: 10px; margin: 6px 0 4px; font: 800 64px/1 var(--font-num); color: var(--stake-ink); }
html.ios .stake-num { font-size: 176px; line-height: .86; letter-spacing: -0.02em; color: var(--figure); text-shadow: var(--figure-glow); }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .stake-num { color: #1F2A05; } }
html.ios .stake-unit { font: 700 30px var(--font-ui); letter-spacing: 0; }
html.ios .stake-caption { margin-top: var(--s-4); font: 500 17px/1.35 var(--font-ui); color: var(--stake-mute); }
.stake-rungs { display: none; }
html.ios .stake-rungs { display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 7px; margin-top: var(--s-4); }
html.ios .rung { display: grid; place-items: center; height: 44px; border-radius: 14px; background: var(--surface-2); color: var(--ink); font: 800 19px/1 var(--font-num); }
html.ios .rung.is-gone { background: transparent; color: var(--ink-ghost); box-shadow: inset 0 0 0 1.5px var(--line); text-decoration: line-through; }
html.ios .rung.is-now { background: #BDDA4F; color: #1F2A05; box-shadow: 0 8px 22px rgba(189,218,79,.4); }
@media (prefers-color-scheme: light) {
  html.ios:where(:not(.haunted)) .rung { background: rgba(31,42,5,0.10); color: #1F2A05; }
  html.ios:where(:not(.haunted)) .rung.is-gone { background: transparent; color: rgba(31,42,5,0.45); box-shadow: inset 0 0 0 1.5px rgba(31,42,5,0.22); }
  html.ios:where(:not(.haunted)) .rung.is-now { background: #1F2A05; color: #BDDA4F; box-shadow: none; }
}
/* With the keyboard up, the card gives its room to the answer box and the button. */
html.ios .app-shell.kb-open .stake-rungs, html.ios .app-shell.kb-open .stake-caption { display: none; }
html.ios .app-shell.kb-open .stake { padding: 14px 20px; }
html.ios .app-shell.kb-open .stake-num { font-size: 64px; }
html.ios .app-shell.kb-open .stake-unit { font-size: 22px; }
html.ios .lad-action { margin-top: var(--s-4); }
/* On a short screen (an iPhone SE in Safari is 375 by 553) the whole ladder still fits
   without scrolling: the number and the card shrink, nothing is dropped. */
@media (max-height: 700px) {
  html.ios .app-top { padding-top: 6px; }
  html.ios .who { margin-top: 4px; min-height: 32px; }
  html.ios .stake { padding: 16px 18px; border-radius: 30px; }
  html.ios .stake-num { font-size: 96px; }
  html.ios .stake-unit { font-size: 24px; }
  html.ios .stake-rungs { margin-top: 10px; }
  html.ios .rung { height: 34px; border-radius: 11px; font-size: 16px; }
  html.ios .stake-caption { margin-top: 8px; font-size: 15px; }
  html.ios .lad-action { margin-top: var(--s-3); }
  html.ios #ladAnswer { min-height: 54px; padding-block: 12px; }
  html.ios .lad-lock { min-height: 62px; margin-top: 10px; font-size: 21px; }
  html.ios .lad-action .field-caption { margin-top: 8px; }
}
/* Locked: the card turns lime, so a glance across the table says who is done. */
html.ios .locked { padding: 26px 24px; border-radius: var(--r-big); background: #BDDA4F; color: #1F2A05; box-shadow: var(--lime-shadow); }
html.ios .locked-stamp { padding: 7px 14px; border-radius: 999px; background: #1F2A05; color: #BDDA4F; font: 800 15px/1.2 var(--font-ui); text-transform: none; letter-spacing: 0; }
html.ios .locked-answer { margin-top: var(--s-4); font: 800 40px/1.06 var(--font-dsp); letter-spacing: -0.01em; color: #1F2A05; }
html.ios .locked-meta { margin-top: var(--s-3); font: 700 18px/1.4 var(--font-ui); color: #1F2A05; }
html.ios .locked-wait { font: 600 16px/1.4 var(--font-ui); color: #3A4710; }

/* ---------------- entering scores ----------------
   The team is the title and its own picker; the total is the huge number under it; the
   open rounds are one list. */
html.ios #v-scoring .gate { order: 1; margin-top: var(--s-5); }
html.ios #v-scoring .entry-total { order: 2; }
html.ios #v-scoring .rounds { order: 3; }
html.ios #v-scoring .catchup-bar, html.ios #v-scoring .warn { order: 0; }
html.ios #v-scoring .big-label { margin: 0 0 2px; font: 600 16px/1.3 var(--font-ui); }
html.ios #markedTeam { min-height: 48px; padding: 4px 40px 4px 4px; border-radius: 12px; background-color: transparent; box-shadow: none;
  font: 800 30px/1.15 var(--font-dsp); color: var(--ink); background-position: right 4px center; background-size: 22px; }
html.ios #markedTeam.is-set { background-color: transparent; box-shadow: none; background-position: right 4px center; }
html.ios .entry-total { margin: var(--s-2) 0 0; padding: 0 4px; border-radius: 0; background: transparent; color: var(--ink); box-shadow: none; display: flex; align-items: baseline; flex-wrap: wrap; gap: 4px 14px; }
html.ios .entry-total.hidden { display: none; }
html.ios .entry-total .eyebrow { display: none; }
html.ios .entry-total .figure { margin: 0; font: 800 104px/.9 var(--font-num); letter-spacing: -0.02em; color: var(--figure); text-shadow: var(--figure-glow); }
html.ios .entry-total .progress { font: 600 17px/1.3 var(--font-ui); color: var(--ink-mute); }
html.ios .rounds { margin-top: var(--s-5); }
html.ios #rounds:not(:empty) { overflow: hidden; border-radius: var(--r-card); background: var(--surface); box-shadow: var(--card-shadow); }
html.ios .rounds-hold { margin: 0; padding: 22px; background: transparent; box-shadow: none; border-radius: 0; font: 500 17px/1.45 var(--font-ui); color: var(--ink-mute); text-align: left; }
html.ios .row { position: relative; flex-direction: row; flex-wrap: wrap; align-items: center; gap: 2px 0; padding: 15px 14px 11px 20px; }
html.ios .row + .row::before { content: ""; position: absolute; top: 0; left: 20px; right: 0; height: 1px; background: var(--line); }
html.ios .row-label { flex: 1 0 100%; min-width: 0; padding: 0; font: 700 18px/1.3 var(--font-ui); color: var(--ink); }
html.ios .in-wrap { flex: 1 0 100%; gap: 8px; padding: 0; border-radius: 0; background: transparent; box-shadow: none; }
html.ios .row-max { margin-right: auto; font: 500 15px/1.3 var(--font-ui); color: var(--ink-mute); }
html.ios .score-input { flex: 0 0 auto; width: 92px; padding: 8px 12px; border-radius: 14px; text-align: right; font: 800 34px/1.05 var(--font-num); color: var(--ink); }
html.ios .score-input:focus { background: var(--surface-2); box-shadow: inset 0 0 0 2.5px #BDDA4F; }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .score-input:focus { box-shadow: inset 0 0 0 2.5px #0B0B0D; } }
html.ios .score-input::placeholder { color: var(--ink-ghost); font-weight: 700; }
html.ios .row-help { flex: 1 0 100%; margin: 0; padding: 0 0 4px; font: 600 15px/1.3 var(--font-ui); color: var(--state-queued); }
html.ios .in-wrap:focus-within,
html.ios .row:has(.is-saved) .in-wrap, html.ios .row:has(.is-queued) .in-wrap,
html.ios .row:has(.is-error) .in-wrap, html.ios .row:has(.is-changed) .in-wrap,
html.ios .row:has(.is-locked) .in-wrap, html.ios .row.over-max .in-wrap { background: transparent; box-shadow: none; }
html.ios .in-wrap:focus-within .score-input, html.ios .row:has(.is-saved) .score-input { color: var(--ink); }
html.ios .row:has(.is-queued) .score-input, html.ios .row:has(.is-changed) .score-input, html.ios .row.over-max .score-input { color: var(--state-queued); }
html.ios .row:has(.is-error) .score-input { color: var(--state-error); }
html.ios .row:has(.is-locked) .score-input { color: var(--ink-mute); }
html.ios .status { width: 40px; height: 44px; background: transparent; color: var(--ink-ghost); }
html.ios .status svg { width: 22px; height: 22px; }
html.ios .status.is-editing, html.ios .status.is-saving { background: transparent; color: var(--ink-mute); }
html.ios .status.is-saved, html.ios .status.is-error { background: transparent; }
html.ios .status.is-saved .status-icon, html.ios .status.is-error .status-icon { width: 30px; height: 30px; border-radius: 50%; color: #000000; }
html.ios .status.is-saved .status-icon { background: var(--state-saved); }
html.ios .status.is-error .status-icon { background: var(--state-error); }
@media (prefers-color-scheme: light) { html.ios:where(:not(.haunted)) .status.is-saved .status-icon, html.ios:where(:not(.haunted)) .status.is-error .status-icon { color: #FFFFFF; } }
html.ios .status.is-saved svg, html.ios .status.is-error svg { width: 17px; height: 17px; }
html.ios .status.is-queued, html.ios .status.is-changed { background: transparent; color: var(--state-queued); }
html.ios .status.is-locked { background: transparent; color: var(--ink-mute); }
/* A round left blank and saved as blank gets no tick: a tick beside an empty box reads as
   a score that went in. */
html.ios .score-input:placeholder-shown + .status.is-saved { visibility: hidden; }
/* The sign key: drawn, plus over minus, never a text glyph. */
html.ios .sign-toggle { width: 44px; height: 44px; border-radius: 50%; background: var(--surface-2); color: var(--ink); }
html.ios .sign-toggle svg { width: 20px; height: 20px; display: block; }
html.ios .in-wrap:focus-within .sign-toggle { background: var(--surface-2); color: var(--ink); }
html.ios .row.is-neg .sign-toggle { background: #BDDA4F; color: #1F2A05; }
html.ios .done-msg { color: var(--ink); }

/* ---------------- the answers, as they are revealed ---------------- */
/* The Live mark on the answers pulses on each poll, so the screen visibly keeps itself up
   to date; the round it is revealing is already on the pill. */
html.ios .reveal-head { justify-content: flex-end; margin-bottom: var(--s-2); }
html.ios .reveal-live { font: 600 15px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: var(--ink-mute); }
html.ios .reveal-live-dot { background: #30D158; }
html.ios .reveal-hold { padding: 48px 24px; border-radius: var(--r-card); background: var(--surface); box-shadow: var(--card-shadow); }
html.ios .reveal-hold-msg { font: 600 19px/1.4 var(--font-ui); color: var(--ink-mute); }
html.ios .reveal-roundhead { gap: var(--s-3); margin: 0 0 var(--s-4); }
html.ios .reveal-rn { width: 44px; height: 44px; background: #BDDA4F; color: #1F2A05; font: 800 20px var(--font-num); }
html.ios .reveal-rname { font: 800 30px/1.1 var(--font-dsp); letter-spacing: 0; }
html.ios .reveal-group { margin-top: var(--s-5); }
html.ios .reveal-item { gap: var(--s-3); margin: 0 0 10px; padding: 18px; border-radius: 24px; background: var(--surface); box-shadow: var(--card-shadow); }
html.ios .reveal-item.is-revealed { box-shadow: inset 0 0 0 2px var(--state-saved-bg), var(--card-shadow); }
html.ios .reveal-item.is-fresh { animation: ios-reveal 1.2s var(--ease); }
@keyframes ios-reveal { 0% { transform: scale(1.02); box-shadow: inset 0 0 0 3px #BDDA4F, var(--card-shadow); } 100% { transform: none; box-shadow: inset 0 0 0 2px var(--state-saved-bg), var(--card-shadow); } }
html.ios .reveal-inum { flex: 0 0 26px; font: 800 17px var(--font-num); color: var(--ink-mute); text-align: left; }
html.ios .reveal-q { margin-bottom: var(--s-2); font: 500 17px/1.45 var(--font-ui); }
html.ios .reveal-a { font: 800 22px/1.3 var(--font-ui); color: var(--state-saved); }
html.ios .reveal-note { font: 500 15px/1.45 var(--font-ui); color: var(--ink-mute); }
html.ios .reveal-pending { font: 600 15px var(--font-ui); color: var(--ink-mute); }
html.ios .reveal-pending::before { background: var(--ink-ghost); }

/* ---------------- standings ----------------
   The leader is a lime card of its own; everyone else is one list under it. */
html.ios #v-leaderboard .topbar h1 { margin-top: var(--s-5); font-size: 36px; }
html.ios .pub-board { gap: 0; margin-top: var(--s-4); background: transparent; box-shadow: none; }
html.ios .pub-row { position: relative; border-radius: 0; background: var(--surface); box-shadow: none; }
html.ios .pub-row + .pub-row::before { content: ""; position: absolute; top: 0; left: 74px; right: 0; height: 1px; background: var(--line); }
html.ios .pub-row:not(.leader):first-child, html.ios .pub-row.leader + .pub-row:not(.leader) { border-top-left-radius: var(--r-card); border-top-right-radius: var(--r-card); }
html.ios .pub-row.leader + .pub-row:not(.leader)::before { display: none; }
html.ios .pub-row:last-child { border-bottom-left-radius: var(--r-card); border-bottom-right-radius: var(--r-card); }
html.ios .pub-sum { grid-template-columns: 42px 1fr auto 18px; gap: 14px; min-height: 72px; padding: 12px 18px; }
html.ios .pub-rank { display: grid; place-items: center; width: 42px; height: 42px; border-radius: 50%; background: var(--surface-2); color: var(--ink); font: 800 18px var(--font-num); }
/* A team's name is the content, so it wraps rather than being cut to "Bar Ste...". Pub
   quiz names run long, and only the leader's used to wrap. */
html.ios .pub-name { font: 700 18px/1.3 var(--font-ui); color: var(--ink); white-space: normal; overflow-wrap: anywhere; }
html.ios .pub-total { font: 800 32px var(--font-num); color: var(--ink); }
html.ios .pub-chev { width: 18px; height: 18px; color: var(--ink-ghost); }
html.ios .pub-body { grid-template-columns: 1fr; gap: 0; padding: 0 22px 14px 74px; }
html.ios .pub-cell { padding: 9px 0; border-radius: 0; background: transparent; box-shadow: inset 0 -1px 0 var(--line); font: 500 15px/1.3 var(--font-ui); color: var(--ink-mute); }
html.ios .pub-cell-v { font: 800 16px var(--font-num); color: var(--ink); }
html.ios .pub-row.leader { margin-bottom: 12px; border-radius: var(--r-card); background: #BDDA4F; box-shadow: var(--lime-shadow); }
/* The leader's name has the card's full width, with the badge and the total on the line
   under it. Beside a 44px total the name had a third of the card, and on any phone narrower
   than 390 a long name broke mid-word: "Universall / y Challeng / ed". The total keeps the
   same column as everyone else's. */
html.ios .pub-row.leader .pub-sum { grid-template-columns: 46px minmax(0, 1fr) 18px; grid-template-areas: "name name chev" "rank total ."; row-gap: 10px; min-height: 0; padding: 18px; }
html.ios .pub-row.leader .pub-rank { grid-area: rank; width: 46px; height: 46px; background: #1F2A05; color: #BDDA4F; font-size: 21px; }
html.ios .pub-row.leader .pub-name { grid-area: name; font: 800 21px/1.2 var(--font-dsp); color: #1F2A05; }
html.ios .pub-row.leader .pub-total { grid-area: total; justify-self: end; font-size: 44px; line-height: 1; color: #1F2A05; }
html.ios .pub-row.leader .pub-chev { grid-area: chev; }
html.ios .pub-row.leader .pub-chev { color: rgba(31,42,5,0.55); }
html.ios .pub-row.leader .pub-cell { color: #3A4710; box-shadow: inset 0 -1px 0 rgba(31,42,5,0.15); }
html.ios .pub-row.leader .pub-cell-v { color: #1F2A05; }
html.ios .pub-empty { color: var(--ink-mute); }
/* On the narrowest phones, 320 wide, the totals give back room so a name breaks once rather
   than one word to a line. */
@media (max-width: 359px) {
  html.ios .pub-sum, html.ios .pub-row.leader .pub-sum { gap: 10px; padding-inline: 14px; }
  html.ios .pub-total { font-size: 28px; }
  html.ios .pub-row.leader .pub-total { font-size: 36px; }
}

/* ---------------- the shared results page and the 404 ---------------- */
html.ios .board-page { padding-top: max(var(--s-5), env(safe-area-inset-top)); }
html.ios .board-hero { padding: 26px 24px; border-radius: var(--r-big); background: #BDDA4F; color: #1F2A05; box-shadow: var(--lime-shadow); }
html.ios .board-hero .eyebrow, html.ios .board-winner-label { font: 700 15px/1.3 var(--font-ui); text-transform: none; letter-spacing: 0; color: #3A4710; }
html.ios .board-hero-title { font: 800 36px/1.06 var(--font-dsp); letter-spacing: -0.01em; }
html.ios .board-hero-when { font: 600 15px/1.35 var(--font-ui); color: #3A4710; }
html.ios .board-winner { border-top: 1px solid rgba(31,42,5,0.15); }
html.ios .board-winner-name { font: 800 22px/1.2 var(--font-dsp); color: #1F2A05; }
html.ios .board-winner-score { font: 800 80px/1 var(--font-num); color: #1F2A05; }
html.ios .board-frozen { font: 500 15px/1.4 var(--font-ui); color: var(--ink-mute); }
html.ios .board-state h1 { font: 800 36px/1.06 var(--font-dsp); }
html.ios .board-page .app-sig { opacity: 1; color: var(--ink-mute); font: 500 12px/1.3 var(--font-ui); letter-spacing: 0; }

/* ---------------- a haunted night ----------------
   Decorations the host switches on from the console's Setup tab for a Halloween night
   (27 October 2026, Scott's pick of three: "Haunted"). They hang on the Live look rather
   than replacing it. The lime turns to slime: every lime box is wet and drips. A web hangs
   in the top corner with its spider in it, and the spider comes down on its thread to watch
   over Phones down, which is why the monitoring line names spirits. Five pairs of eyes blink
   in the dark on the waiting screens, under a faint violet night. It is dark only (Scott,
   the same evening): a phone set to light goes dark while the decorations are up, because
   they are made for the dark. None of it does a job or covers a word, all of it is hidden
   from screen readers, and under reduce motion it holds still. */
.haunt { display: none; }
html.ios.haunted .haunt { display: block; }
html.ios.haunted { color-scheme: dark; }
html.ios.haunted { --slime-14: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 14'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23BDDA4F'/%3E%3Cstop offset='1' stop-color='%2398B72C'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M0 0H24C18 0 16.6 3 16.4 8L16.2 1.8C16.2 3.8 19.2 5.8 19.2 6.8A7.2 7.2 0 1 1 4.8 6.8C4.8 5.8 7.8 3.8 7.8 1.8L7.6 8C7.4 3 6 0 0 0Z'/%3E%3Cellipse cx='9.4' cy='5.2' rx='2.1' ry='3' fill='white' fill-opacity='.62'/%3E%3Crect x='9.2' y='6' width='1.5' height='1.0' rx='.75' fill='white' fill-opacity='.32'/%3E%3C/svg%3E"); --slime-20: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 20'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23BDDA4F'/%3E%3Cstop offset='1' stop-color='%2398B72C'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M0 0H24C18 0 16.6 3 16.4 8L16.2 7.8C16.2 9.8 19.2 11.8 19.2 12.8A7.2 7.2 0 1 1 4.8 12.8C4.8 11.8 7.8 9.8 7.8 7.8L7.6 8C7.4 3 6 0 0 0Z'/%3E%3Cellipse cx='9.4' cy='11.2' rx='2.1' ry='3' fill='white' fill-opacity='.62'/%3E%3Crect x='9.2' y='6' width='1.5' height='1.8' rx='.75' fill='white' fill-opacity='.32'/%3E%3C/svg%3E"); --slime-26: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 26'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23BDDA4F'/%3E%3Cstop offset='1' stop-color='%2398B72C'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M0 0H24C18 0 16.6 3 16.4 8L16.2 13.8C16.2 15.8 19.2 17.8 19.2 18.8A7.2 7.2 0 1 1 4.8 18.8C4.8 17.8 7.8 15.8 7.8 13.8L7.6 8C7.4 3 6 0 0 0Z'/%3E%3Cellipse cx='9.4' cy='17.2' rx='2.1' ry='3' fill='white' fill-opacity='.62'/%3E%3Crect x='9.2' y='6' width='1.5' height='7.8' rx='.75' fill='white' fill-opacity='.32'/%3E%3C/svg%3E"); --slime-40: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 40'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23BDDA4F'/%3E%3Cstop offset='1' stop-color='%2398B72C'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M0 0H24C18 0 16.6 3 16.4 8L16.2 27.8C16.2 29.8 19.2 31.8 19.2 32.8A7.2 7.2 0 1 1 4.8 32.8C4.8 31.8 7.8 29.8 7.8 27.8L7.6 8C7.4 3 6 0 0 0Z'/%3E%3Cellipse cx='9.4' cy='31.2' rx='2.1' ry='3' fill='white' fill-opacity='.62'/%3E%3Crect x='9.2' y='6' width='1.5' height='21.8' rx='.75' fill='white' fill-opacity='.32'/%3E%3C/svg%3E"); --slime-bump: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 10'%3E%3Cdefs%3E%3ClinearGradient id='g' x1='0' y1='0' x2='0' y2='1'%3E%3Cstop offset='0' stop-color='%23BDDA4F'/%3E%3Cstop offset='1' stop-color='%2398B72C'/%3E%3C/linearGradient%3E%3C/defs%3E%3Cpath fill='url(%23g)' d='M0 0H40C34 0 31 7 20 7.6C9 7 6 0 0 0Z'/%3E%3Cellipse cx='15' cy='4.4' rx='4' ry='1.2' fill='white' fill-opacity='.4'/%3E%3C/svg%3E");
  --slime-gloss: linear-gradient(180deg, rgba(255,255,255,0.24), rgba(255,255,255,0) 46%);
  --slime-wet: inset 0 1.5px 0 rgba(255,255,255,0.55), inset 0 -10px 18px rgba(96,128,12,0.22); }
html.ios.haunted body { background:
  radial-gradient(120% 45% at 50% -8%, rgba(124,58,237,0.28), transparent 70%) no-repeat,
  radial-gradient(110% 40% at 50% 108%, rgba(124,58,237,0.16), transparent 70%) no-repeat,
  var(--bg); }

/* Slime. A drip strip hangs from the bottom edge of each lime box and oozes down when the box
   appears, so it arrives with whatever brought the box: a page, a new leader, a button
   coming alive. The drips sit clear of the corners and of the words below them. */
@keyframes haunt-ooze { from { transform: scaleY(0); } to { transform: none; } }
html.ios.haunted .pub-row.leader { overflow: visible; z-index: 1; background-image: var(--slime-gloss); box-shadow: var(--lime-shadow), var(--slime-wet); }
html.ios.haunted .pub-row.leader::after { content: ""; position: absolute; left: 24px; right: 24px; top: calc(100% - 3px); height: 28px; pointer-events: none;
  background: var(--slime-20) no-repeat 3% 0 / 20px 20px, var(--slime-bump) no-repeat 15% 0 / 46px 9px, var(--slime-14) no-repeat 29% 0 / 16px 14px,
    var(--slime-bump) no-repeat 44% 0 / 50px 8px, var(--slime-26) no-repeat 60% 0 / 22px 26px, var(--slime-bump) no-repeat 77% 0 / 44px 9px,
    var(--slime-14) no-repeat 97% 0 / 17px 15px;
  transform-origin: 50% 0; animation: haunt-ooze 1.1s cubic-bezier(.3,.8,.4,1) both; filter: drop-shadow(0 3px 5px rgba(120,150,20,0.4)); }
html.ios.haunted .btn-primary:not(:disabled) { position: relative; background-image: var(--slime-gloss); box-shadow: var(--lime-shadow), var(--slime-wet); }
html.ios.haunted .btn-primary:not(:disabled)::after { content: ""; position: absolute; left: 30px; right: 30px; top: calc(100% - 3px); height: 24px; pointer-events: none;
  background: var(--slime-20) no-repeat 0 0 / 20px 22px, var(--slime-bump) no-repeat 14% 0 / 44px 9px, var(--slime-bump) no-repeat 50% 0 / 60px 7px,
    var(--slime-bump) no-repeat 84% 0 / 44px 9px, var(--slime-14) no-repeat 100% 0 / 17px 16px;
  transform-origin: 50% 0; animation: haunt-ooze 1.1s cubic-bezier(.3,.8,.4,1) both; filter: drop-shadow(0 3px 4px rgba(120,150,20,0.35)); }
html.ios.haunted .hero-card .hero-icn { position: relative; }
html.ios.haunted .hero-card .hero-icn::after { content: ""; position: absolute; left: 50%; top: calc(100% - 12px); width: 84px; height: 52px; margin-left: -42px; pointer-events: none;
  background: var(--slime-26) no-repeat 2px 3px / 20px 26px, var(--slime-40) no-repeat 30px 8px / 26px 40px, var(--slime-20) no-repeat 62px 4px / 19px 20px;
  transform-origin: 50% 0; animation: haunt-ooze 1.3s cubic-bezier(.3,.8,.4,1) .2s both;
  filter: drop-shadow(0 0 8px rgba(189,218,79,0.45)); }
html.ios.haunted .rung { position: relative; }
html.ios.haunted .rung.is-now { background-image: var(--slime-gloss); box-shadow: 0 8px 22px rgba(189,218,79,.4), var(--slime-wet); }
html.ios.haunted .rung.is-now::after { content: ""; position: absolute; left: 10px; right: 10px; top: calc(100% - 3px); height: 16px; pointer-events: none;
  background: var(--slime-bump) no-repeat 0 0 / 24px 7px, var(--slime-14) no-repeat 62% 0 / 16px 15px; transform-origin: 50% 0; animation: haunt-ooze .9s cubic-bezier(.3,.8,.4,1) both; }

/* The Live dot is a drop of the slime, still breathing, and grey and still when offline. */
html.ios.haunted .live-pill i { position: relative; width: 9px; height: 12px; border-radius: 0; background: transparent; box-shadow: none;
  filter: drop-shadow(0 0 4px rgba(189,218,79,0.75)); }
html.ios.haunted .live-pill i::before { content: ""; position: absolute; left: 0.5px; bottom: 0.5px; width: 8px; height: 8px; border-radius: 50% 0 50% 50%;
  transform: rotate(-45deg); background: radial-gradient(circle at 40% 40%, #F6FFD6 0 14%, #C9E65A 38%, #93B22B 100%); }
html.ios.haunted .live-pill.is-offline i { filter: none; }
html.ios.haunted .live-pill.is-offline i::before { background: var(--ink-ghost); }

/* Eyes in the dark, where the waiting dot breathed: five pairs, because one pair on its own
   looked strange (Scott). The dot is the near pair. Its four <i> are further off, so smaller
   and dimmer, each with its own slant and its own beat, and they keep to the dot's band, clear
   of the words above and below it. */
.breathe-dot i { display: none; }
html.ios.haunted .breathe-dot { position: relative; width: 34px; height: 12px; border-radius: 0; background: transparent; animation: none; }
html.ios.haunted .breathe-dot i { display: block; position: absolute; left: var(--x); top: var(--y); width: 34px; height: 12px; scale: var(--near); opacity: var(--near); }
html.ios.haunted .breathe-dot::before, html.ios.haunted .breathe-dot::after,
html.ios.haunted .breathe-dot i::before, html.ios.haunted .breathe-dot i::after { content: ""; position: absolute; top: 2px; width: 13px; height: 8px;
  border-radius: 50% 50% 50% 50% / 70% 70% 30% 30%; background: #D9F26B; box-shadow: 0 0 10px rgba(217,242,107,0.75);
  animation: haunt-blink var(--beat, 5.2s) var(--from, 0s) infinite; }
html.ios.haunted .breathe-dot::before, html.ios.haunted .breathe-dot i::before { left: 1px; rotate: var(--slant, 16deg); }
html.ios.haunted .breathe-dot::after, html.ios.haunted .breathe-dot i::after { right: 1px; rotate: calc(var(--slant, 16deg) * -1); }
html.ios.haunted .breathe-dot i:nth-child(1) { --x: -62px;  --y: 7px;  --near: .72; --slant: 6deg;  --beat: 6.4s; --from: -2.2s; }
html.ios.haunted .breathe-dot i:nth-child(2) { --x: 70px;   --y: -8px; --near: .78; --slant: 24deg; --beat: 5.8s; --from: -4.1s; }
html.ios.haunted .breathe-dot i:nth-child(3) { --x: -104px; --y: 1px;  --near: .5;  --slant: 0deg;  --beat: 7.6s; --from: -1.1s; }
html.ios.haunted .breathe-dot i:nth-child(4) { --x: 112px;  --y: 11px; --near: .54; --slant: 12deg; --beat: 4.7s; --from: -3.3s; }
html.ios.haunted .breathe-dot i:nth-child(3)::before, html.ios.haunted .breathe-dot i:nth-child(3)::after { border-radius: 50%; }
@keyframes haunt-blink { 0%, 90%, 97%, 100% { scale: 1; } 93% { scale: 1 0.12; } }

/* The web, in the top corner of the screen and kept to the top band, and its spider at the
   hub. On Phones down the spider lowers on its thread to watch the table, and climbs back
   when the night moves on. */
html.ios .haunt-web { position: absolute; top: env(safe-area-inset-top, 0px); right: env(safe-area-inset-right, 0px); width: 150px; height: 77px; z-index: -1;
  fill: none; stroke: rgba(235,235,245,0.3); stroke-width: 0.9; stroke-linecap: round; pointer-events: none; }
html.ios .haunt-spider { position: absolute; top: calc(env(safe-area-inset-top, 0px) + 12px); right: calc(env(safe-area-inset-right, 0px) + 27px); width: 40px; height: 40px;
  z-index: -1; pointer-events: none; transition: transform 1.2s cubic-bezier(.3,1.3,.5,1); }
html.ios .haunt-spider::before { content: ""; position: absolute; left: 50%; bottom: 50%; width: 1px; height: 0; background: rgba(235,235,245,0.5);
  transition: height 1.2s cubic-bezier(.3,1.3,.5,1); }
html.ios .app-shell[data-stage="standby"] .haunt-spider { transform: translateY(176px); }
html.ios .app-shell[data-stage="standby"] .haunt-spider::before { height: 176px; }
html.ios .haunt-spider svg { position: relative; display: block; width: 40px; height: 40px; filter: drop-shadow(0 0 5px rgba(124,58,237,0.75)); }
html.ios .haunt-spider .legs { fill: none; stroke: #5A5A62; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }
html.ios .haunt-spider .body { fill: #2C2C30; stroke: #5A5A62; stroke-width: 0.8; }
html.ios .haunt-spider .shine { fill: #FFFFFF; fill-opacity: 0.16; }
html.ios .haunt-spider .eye { fill: #D9F26B; filter: drop-shadow(0 0 1.5px #D9F26B); }

/* Reduce motion: every decoration stays, and none of them moves. */
@media (prefers-reduced-motion: reduce) {
  html.ios.haunted .breathe-dot::before, html.ios.haunted .breathe-dot::after,
  html.ios.haunted .breathe-dot i::before, html.ios.haunted .breathe-dot i::after { animation: none !important; }
  html.ios .haunt-spider, html.ios .haunt-spider::before { transition: none !important; }
}
