/* © 2026 William C. Chesher. All Rights Reserved.
   glitch - the base skin and the student door

   THE TOKENS ARE SET BY THE SERVER, per theme, on :root (app.py::page). Nothing here
   hardcodes a colour; a theme swap is a token swap and no rule below has to know.

   THE MOTION CONTRACT, in one place so no surface can quietly invent its own curve:
     --ease  cubic-bezier(.2,0,.2,1)   the house default, 24 uses in sfhsbta site.css
     --enter cubic-bezier(.16,1,.3,1)  entrances only
     --fast  140ms                     the house default duration, 20 uses
   NOTHING BOUNCES. No overshoot easing anywhere in these files. The audience is fifteen,
   and an overshoot is the fastest way to make a tool read as built for eight-year-olds. */

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  background: var(--surface);
  color: var(--ink);
  font-family: "Barlow", system-ui, -apple-system, sans-serif;
  /* The browser chrome bar appearing mid-question must not resize the layout under a
     thumb that is already moving toward a button (3.6). */
  min-height: 100dvh;
  -webkit-text-size-adjust: 100%;
}

h1, h2, h3 { font-family: var(--display); font-weight: 400; letter-spacing: -.01em; }

/* The mono face is the INSTRUMENT, never the voice: numbers, codes and labels only. */
.meta, .hint, .step, code, .bnum, .brank { font-family: "JetBrains Mono", ui-monospace, monospace; }
.meta, .hint { color: var(--muted); font-size: 13px; letter-spacing: .02em; }

/* ---- ASCII ornaments (the subtle festoon) --------------------------------------------------
   The ascii identity carried through ordinary content -- a neon rule, glitch list bullets, a
   mono `>_` section eyebrow -- CSS-only so it costs nothing and needs no JS on the phone. The
   fuller motif rules and dynamic ornaments live in ornaments.js. */
hr, .glitch-hr { border: 0; height: 2px; margin: 22px 0;
  background: repeating-linear-gradient(90deg, var(--accent) 0 9px, transparent 9px 15px); opacity: .55; }
.glitch-list { list-style: none; padding-left: 0; }
.glitch-list > li { position: relative; padding-left: 1.5em; }
.glitch-list > li::before { content: "\25b8"; position: absolute; left: 0; color: var(--accent);
  font-family: "JetBrains Mono", ui-monospace, monospace; }
.sectional { font-family: "JetBrains Mono", ui-monospace, monospace; font-size: 12px;
  letter-spacing: .18em; text-transform: uppercase; color: var(--muted);
  display: flex; align-items: center; gap: 8px; margin: 0 0 10px; }
.sectional::before { content: ">_"; color: var(--accent); }
/* a full ascii motif rule -- ornaments.js fills .glitch-rule with a MOTIF string */
.glitch-rule { font-family: "JetBrains Mono", ui-monospace, monospace; color: var(--muted);
  letter-spacing: .04em; text-align: center; overflow: hidden; white-space: nowrap; margin: 20px 0; opacity: .7; }

.sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }

/* The wordmark. Lowercase always -- glitch is a lowercase product name -- set in the display
   face and wearing the brand's RGB tear as a STATIC chromatic split (cyan left, magenta right)
   so it reads as the glitch with no animation to gate behind reduced-motion. Token-driven: the
   cyan is the theme's second answer colour and the magenta its accent, so a skin swap recolours
   the split rather than breaking it. */
.brand {
  font-size: clamp(38px, 9vw, 72px); margin: 0 0 24px; letter-spacing: -.01em; line-height: 1;
  color: var(--ink);
  text-shadow: -.03em 0 var(--a2, #05d9e8), .03em 0 var(--accent, #ff2e97);
}
/* the bang -- the brand is "glitch!" across the board (operator, 2026-09-22). Magenta, and it
   inherits the wordmark's chromatic split. The common-noun "glitch" (a quiz) keeps no bang. */
.bang { color: var(--accent); }

.door {
  min-height: 100dvh;
  display: flex; flex-direction: column; justify-content: center;
  /* 16px side gutter, generous and uneven vertically -- nothing is centred in a box it
     does not fill. */
  padding: 32px 16px 15vh;
  max-width: 520px; margin: 0 auto;
}

.joinform { display: flex; flex-direction: column; gap: 10px; }
label { font-size: 14px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }

input[type="text"], input[type="password"], input[type="number"], input:not([type]), textarea, select {
  font: inherit; font-size: 20px;
  background: rgba(255,255,255,.05);
  color: var(--ink);
  border: 1px solid rgba(255,255,255,.14);   /* a hairline, not a box */
  border-radius: 10px;
  padding: 14px 16px;
  width: 100%;
  transition: border-color var(--fast) var(--ease), background var(--fast) var(--ease);
}
input:focus-visible, textarea:focus-visible, select:focus-visible, button:focus-visible, a:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 2px;
}
#code { font-family: "JetBrains Mono", monospace; font-size: 32px; letter-spacing: .22em; text-align: center; }

button, .big {
  font: inherit; font-weight: 600; font-size: 18px;
  background: var(--accent); color: var(--surface);
  border: 0; border-radius: 10px;
  /* 48px minimum target: a thumb, one-handed, under a timer. */
  padding: 15px 22px; min-height: 52px;
  cursor: pointer; text-decoration: none; text-align: center;
  transition: transform var(--fast) var(--ease), opacity var(--fast) var(--ease);
}
button:active { transform: scale(.985); }        /* weight, not springiness */
button:disabled { opacity: .35; cursor: default; }
button.quiet { background: transparent; color: var(--muted); border: 1px solid rgba(255,255,255,.14); }
button.danger { color: var(--wrong); }

.bad { color: var(--wrong); font-weight: 600; }
.good { color: var(--correct); font-weight: 600; }

/* ---- the avatar grid ---- */
.avatars { border: 0; padding: 0; margin: 8px 0 0; }
.avatars legend { font-size: 14px; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }
.av { display: inline-block; }
.av input { position: absolute; opacity: 0; }
.av span {
  display: block; padding: 4px; border-radius: 12px;
  border: 1px solid transparent;
  transition: transform var(--fast) var(--ease), border-color var(--fast) var(--ease);
}
.av input:checked + span { border-color: var(--accent); transform: scale(1.06); }
.av input:focus-visible + span { outline: 2px solid var(--accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  /* A REAL reduced path, not a disabled one: state still changes, it just arrives rather
     than travels. Vestibular sensitivity is common and this is a room of children. */
  *, *::before, *::after {
    animation-duration: 1ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 1ms !important;
  }
}

/* ---- team mode: one device, one team ---- */
.named { display: flex; gap: 8px; align-items: stretch; }
.named input { flex: 1; }
.reroll { flex: none; font-size: 14px; padding: 0 14px; min-height: 0;
  background: transparent; color: var(--muted); border: 1px solid rgba(255,255,255,.16); }
.reroll:hover { color: var(--accent); border-color: var(--accent); }
.members { border: 0; padding: 0; margin: 4px 0 0; display: grid; gap: 8px; }
.members legend { font-size: 14px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--muted); }
.members legend .hint { text-transform: none; letter-spacing: 0; margin-left: 6px; }
.member { font-size: 17px; padding: 11px 14px; }

/* The nice 404: the door's own shape, a big quiet number, the way back. */
.notfound-code { font-family: "JetBrains Mono", monospace; font-size: 64px; letter-spacing: .12em;
  color: var(--muted); margin: 0; line-height: 1; opacity: .6; }
.notfound-why { max-width: 36ch; line-height: 1.6; font-size: 15px; }
.notfound-why a { color: var(--accent); }
.notfound-path { margin: 0; }
.notfound-path code { font-size: 12px; color: var(--muted); }
.notfound-acts { display: flex; gap: 10px; flex-wrap: wrap; justify-content: center; margin-top: 8px; }
.notfound-acts .btn { display: inline-flex; align-items: center; min-height: 44px; padding: 0 18px; border-radius: 999px;
  text-decoration: none; border: 1px solid rgba(255,255,255,.2); color: var(--ink); font-size: 15px; }
.notfound-acts .btn.go { background: var(--accent); color: var(--surface); border-color: var(--accent); }
