/* Light is the default and dark follows the viewer's system setting.
   Both palettes define the same ten tokens, so a theme set by a
   facilitator still overrides either one — themes are applied as inline
   custom properties on :root, which beat any stylesheet rule.

   `color-scheme` matters as much as the colours: without it, form
   controls, scrollbars and focus rings stay light on a dark page. */
:root{
  color-scheme:light dark;
  --bg:#f3f6fb; --panel:#ffffff; --panel2:#e9eef7; --line:#d3dcea;
  --ink:#111823; --dim:#57647c; --accent:#1668d8; --gold:#8a6212;
  --ok:#177f4a; --bad:#c0392b;
  /* Themeable shape/type (docs/architecture.md §12). A theme overrides
     these on :root at runtime; pills stay pill-shaped deliberately. */
  --radius:14px; --font:'Segoe UI',system-ui,Arial,sans-serif;
}

@media (prefers-color-scheme: dark){
  :root{
    --bg:#0e1420; --panel:#182234; --panel2:#1f2c44; --line:#2b3a58;
    --ink:#e8edf6; --dim:#93a0b8; --accent:#2e9df7; --gold:#e0b34b;
    --ok:#37c47a; --bad:#e05555;
  }
}

/* The facilitator overriding the room. `data-theme` is stamped on the
   root by sse.js and has to win in *both* directions — forcing light on a
   viewer whose phone is in dark mode is exactly as necessary as the
   reverse, which a lone dark block would not achieve. */
:root[data-theme="dark"]{
  --bg:#0e1420; --panel:#182234; --panel2:#1f2c44; --line:#2b3a58;
  --ink:#e8edf6; --dim:#93a0b8; --accent:#2e9df7; --gold:#e0b34b;
  --ok:#37c47a; --bad:#e05555;
}
:root[data-theme="light"]{
  --bg:#f3f6fb; --panel:#ffffff; --panel2:#e9eef7; --line:#d3dcea;
  --ink:#111823; --dim:#57647c; --accent:#1668d8; --gold:#8a6212;
  --ok:#177f4a; --bad:#c0392b;
}
*{box-sizing:border-box;margin:0;padding:0}
html,body{height:100%}
:root{font-size:16px}
body{background-color:var(--bg);color:var(--ink);font-family:var(--font);-webkit-tap-highlight-color:transparent;
  background-size:cover;background-position:center;background-attachment:fixed;
  /* A wallpaper is blended with --bg so it takes the palette's hue and
     keeps only its own light and shade (docs/architecture.md §12.3).
     Without this a cool image under a warm palette simply clashes, which
     is what per-surface backgrounds otherwise make easy to do. It also
     doubles as a readability scrim. No image: the colour shows alone. */
  background-blend-mode:luminosity}
.wrap{max-width:68.75rem;margin:0 auto;padding:1rem}
h1{font-size:1.625rem;letter-spacing:.5px}
h2{font-size:1.25rem;color:var(--ink)}
.dim{color:var(--dim)}
.card{background:var(--panel);border:1px solid var(--line);border-radius:var(--radius);padding:1rem;margin:0.75rem 0}
.btn{display:inline-block;background:var(--panel2);border:1px solid var(--line);color:var(--ink);
  border-radius:var(--radius);padding:0.875rem 1.125rem;font-size:1.0625rem;cursor:pointer;user-select:none;text-align:center}
.btn:active{transform:scale(.98)}
.btn.primary{background:var(--accent);border-color:var(--accent);color:#04101e;font-weight:700}
.btn.ok{background:var(--ok);border-color:var(--ok);color:#04140b;font-weight:700}
.btn.danger{background:transparent;border-color:var(--bad);color:var(--bad)}
.btn.block{display:block;width:100%;margin:0.5rem 0}
.btn[disabled]{opacity:.45;pointer-events:none}
/* The background follows the palette like everything else. It used to be
   a hardcoded #0b111c — written when these surfaces were dark-only — while
   the text colour was already var(--ink). In light mode that put near-black
   text on a near-black box: the team-name field on the join screen, and
   every textinput round, were typed into blind. Found on a phone, because
   the iPad host panel never shows these. */
input[type=text],textarea{width:100%;background:var(--panel);border:1px solid var(--line);color:var(--ink);
  border-radius:var(--radius);padding:0.75rem;font-size:1.0625rem;font-family:inherit}
input[type=text]::placeholder,textarea::placeholder{color:var(--dim);opacity:1}
textarea{min-height:110px;resize:vertical}
.row{display:flex;gap:0.625rem;align-items:center;flex-wrap:wrap}
.grow{flex:1}
.pill{display:inline-block;background:var(--panel2);border:1px solid var(--line);border-radius:999px;
  padding:0.25rem 0.75rem;font-size:0.875rem;color:var(--dim);margin:2px}
.pill.on{color:var(--ok);border-color:var(--ok)}
/* Code a pack shows (docs/architecture.md §6.1). Monospace so columns
   line up, pre-wrap so indentation survives, and scrollable rather than
   wrapped — a long line silently folding back would read as a new
   statement, which is exactly the confusion this element exists to stop. */
.code{background:var(--panel2);border:1px solid var(--line);border-radius:var(--radius);
  padding:0.75rem 0.875rem;margin:0;overflow-x:auto;white-space:pre;
  font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
  font-size:0.9375rem;line-height:1.55;color:var(--ink);tab-size:4}
/* The reveal tally. The bar is a background layer inside the existing
   option row rather than a separate chart, so the text stays exactly
   where the room already read it and nothing reflows between answering
   and revealing. --share is set per row by widgets.js. */
.opt.tally{position:relative;overflow:hidden}
.opt.tally::before{content:"";position:absolute;inset:0 auto 0 0;width:var(--share,0%);
  /* Not --panel2: that is the row's own background, so the bar was the
     same colour as the thing it was drawn on and simply did not exist. */
  background:color-mix(in srgb,var(--accent) 22%,transparent);
  z-index:0;transition:width .35s ease-out}
.opt.tally.tally-answer::before{background:color-mix(in srgb,var(--ok) 26%,transparent)}
.opt.tally.tally-answer{border-color:var(--ok)}
.opt.tally > *{position:relative;z-index:1}
.timer{font-variant-numeric:tabular-nums;font-weight:800;font-size:1.75rem;color:var(--gold)}
.timer.low{color:var(--bad)}
/* Stopped, not running out. Dim rather than red, and never both. */
.timer.paused{color:var(--dim)}
.big{font-size:2.125rem;font-weight:800}
.imgbox{position:relative;width:100%;background:#fff;border-radius:12px;overflow:hidden;touch-action:manipulation}
.imgbox img,.imgbox svg,.imgbox object{display:block;width:100%;height:auto}
/* A blank page (docs/architecture.md §3.12) has no image to give the box
   its height, so it takes one from the page's own shape. The white is
   .imgbox's already: in the room it is a page, and it is the surface the
   ink was drawn on. */
.imgbox.blank{aspect-ratio:var(--slide-aspect,1.7778)}
.zoneMark{position:absolute;border:3px solid var(--accent);border-radius:8px;background:rgba(46,157,247,.15);pointer-events:none}
.zoneMark.good{border-color:var(--ok);background:rgba(55,196,122,.18)}
.heatdot{position:absolute;width:16px;height:16px;border-radius:50%;transform:translate(-50%,-50%);
  border:2px solid #fff;pointer-events:none}
/* Read from the back of a room and over any slide, which is why it is a
   solid dot inside a light ring rather than a tinted blob: a slide can be
   any colour, and the ring is what keeps it visible on the pale ones. */
.pointerDot{position:absolute;width:1.15rem;height:1.15rem;border-radius:50%;
  transform:translate(-50%,-50%);pointer-events:none;z-index:2;
  background:#ff3b2f;border:0.13rem solid rgba(255,255,255,.92);
  box-shadow:0 0 0.85rem rgba(255,59,47,.8);
  opacity:0;transition:opacity 0.1s linear}
.pointerDot.on{opacity:1}
/* Under the dot, over the slide. Never intercepts input: /board is
   read-only and the trail must not become a click target. */
canvas.pointerTrail{position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:1}
/* Under the trail and the dot: what is being pointed at now must never
   be hidden beneath what was drawn a minute ago. */
canvas.inkLayer{position:absolute;inset:0;width:100%;height:100%;
  pointer-events:none;z-index:1}
.heatdot.ok{background:rgba(55,196,122,.9)}
.heatdot.no{background:rgba(224,85,85,.9)}
.lb{width:100%;border-collapse:collapse}
.lb td,.lb th{padding:0.5rem 0.625rem;border-bottom:1px solid var(--line);text-align:left;font-size:1.0625rem}
.lb td:last-child{text-align:right;font-variant-numeric:tabular-nums;font-weight:700}
.center{text-align:center}
.mt{margin-top:0.75rem}
.small{font-size:0.875rem}
.qr{background:#fff;border-radius:12px;padding:12px;display:inline-block}
.banner{font-size:1.375rem;font-weight:700}
/* `flex-wrap` because an ordering row carries a label *and* two buttons
   ("Add to order", "Never happened"), and on a 412px phone — an ordinary
   Android width — their minimum widths do not fit. Without wrapping the
   row simply ran off the side of the screen: the second button was
   unreachable, so a team could place items but never bin the one that
   does not belong. Wrapping engages only when the content overflows, so
   every row that already fitted is unchanged. */
.opt{display:flex;flex-wrap:wrap;gap:12px;align-items:center;background:var(--panel2);
  border:1px solid var(--line);
  border-radius:var(--radius);padding:0.875rem;margin:0.5rem 0;font-size:1.0625rem;cursor:pointer}
/* The label takes the full width once the row has wrapped, so the buttons
   sit together on the line below instead of one per line. */
.opt .grow{flex:1 1 60%}
.opt.sel{border-color:var(--accent);background:rgba(46,157,247,.12)}
.opt .key{font-weight:800;color:var(--gold);min-width:1.5rem}
.result-ok{color:var(--ok);font-weight:800;font-size:1.5rem}
.result-bad{color:var(--bad);font-weight:800;font-size:1.5rem}
