/* Palette — 80s arcade cabinet re-skin (ADR-10, ARCHITECTURE.md). Full
   replacement of the earlier Perforce-brand-compliant palette; the brand
   mapping notes that used to live at the top of this file now live in
   ARCHITECTURE.md's "Style history" section for the record.
   Design brief (verbatim from the person who asked for this): "aim for a
   80s arcade style palette. 8 bit text for titles, some nice sprite-y
   visuals." Titles/labels/buttons use the self-hosted "Press Start 2P"
   pixel font (public/fonts/, OFL-licensed — see public/fonts/OFL.txt);
   body copy stays in a monospace system font, since Press Start 2P is
   unreadable at paragraph sizes. Every text/background pairing below has
   been eyeballed for contrast against a near-black arcade-cabinet
   background — flag anything under ~4.5:1 for body text if you add a
   new pairing. */

@font-face {
  font-family: "Press Start 2P";
  src: url("/fonts/press-start-2p.woff2") format("woff2");
  font-display: swap;
}

:root {
  --bg: #0d0221;            /* cabinet background — near-black purple */
  --bg-panel: #1a0a2e;      /* card/panel surface, one step up from bg */
  --bg-inset: #150a26;      /* recessed surfaces — chat window, inputs */
  --magenta: #ff2fd0;       /* PRIMARY neon accent — headings, "you" bubble, primary buttons */
  --magenta-dim: #b0189a;   /* derived: darker magenta — hover/active state */
  --cyan: #00fff9;          /* secondary neon — links, secondary buttons, "Solid" band */
  --cyan-dim: #00b3af;      /* derived: darker cyan — hover state on cyan elements */
  --yellow: #ffe600;        /* tertiary neon — high scores, coins, warnings */
  --green: #39ff14;         /* success neon — "Strong" band, positive states */
  --green-dim: #1f8a0b;     /* derived: darker green, text-safe on panel bg */
  --ink: #f4f2ff;           /* body text on dark surfaces (14.8:1 on --bg-panel) */
  --muted: #a897d6;         /* derived: dim lavender-grey — secondary/meta text (5.1:1 on --bg-panel) */
  --line: #4a2f7a;          /* panel borders, muted purple */
  --err: #ff3860;           /* hot pink-red — errors, "Developing" band */
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: "Courier New", ui-monospace, Menlo, Consolas, monospace;
  color: var(--ink);
  background: var(--bg);
  position: relative;
  min-height: 100vh;
}

/* CRT scanline overlay — a static, low-opacity repeating gradient (no
   flicker/strobe animation: real CRT flicker reads as charming for a few
   seconds and as a headache/seizure risk for anyone sensitive to it, so this
   stays purely decorative and static). Sits above content via z-index but
   is pointer-events:none so it never blocks clicks. */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 1000;
  pointer-events: none;
  background: repeating-linear-gradient(
    to bottom,
    rgba(255, 255, 255, 0.035) 0px,
    rgba(255, 255, 255, 0.035) 1px,
    transparent 1px,
    transparent 3px
  );
}
/* Faint vignette + starfield-ish radial glow behind everything */
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: -1;
  background:
    radial-gradient(ellipse at 50% -10%, rgba(255, 47, 208, 0.16), transparent 55%),
    radial-gradient(ellipse at 50% 110%, rgba(0, 255, 249, 0.12), transparent 55%);
}

.pixel-font { font-family: "Press Start 2P", "Courier New", monospace; }

header {
  background: var(--bg-panel);
  color: var(--ink);
  padding: 16px 22px;
  display: flex;
  align-items: center;
  gap: 14px;
  border-bottom: 4px solid var(--magenta);
  box-shadow: 0 0 18px rgba(255, 47, 208, 0.45);
}
header .logo-sprite { width: 26px; height: 26px; flex-shrink: 0; image-rendering: pixelated; }
header h1 {
  margin: 0;
  font-family: "Press Start 2P", monospace;
  font-size: 16px;
  letter-spacing: 1px;
  color: var(--magenta);
  text-shadow: 0 0 6px var(--magenta), 0 0 14px rgba(255, 47, 208, 0.6);
}
header .tag { color: var(--cyan); font-size: 12px; letter-spacing: 0.5px; }
header .status { margin-left: auto; font-size: 12px; color: var(--cyan); display: flex; align-items: center; gap: 10px; }
header .status button { padding: 5px 10px; font-size: 11px; }

/* Logo/title as a "go home" control — reset every generic-button style
   below (background/border/box-shadow/press-effect) so it still reads as
   plain header branding, not a CTA button, while staying a real <button>
   for keyboard/screen-reader accessibility (not just a clickable <div>). */
.brand-btn {
  display: flex;
  align-items: center;
  gap: 14px;
  background: none;
  border: 0;
  box-shadow: none;
  padding: 0;
  margin: 0;
  cursor: pointer;
  font: inherit;
}
.brand-btn:hover { background: none; }
.brand-btn:hover h1 { text-shadow: 0 0 10px var(--magenta), 0 0 22px rgba(255, 47, 208, 0.85); }
.brand-btn:active { transform: none; box-shadow: none; }
.brand-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 4px; }

.wrap { max-width: 1180px; margin: 22px auto; padding: 0 16px; }

/* Two-column layout: main flow on the left, weekly leaderboard as a sticky
   right-hand sidebar on wide screens, collapsing to a single stacked column
   (leaderboard last) below the breakpoint. */
.layout { display: grid; grid-template-columns: 1fr 320px; gap: 22px; align-items: start; }
.side-col { position: sticky; top: 22px; }
@media (max-width: 860px) {
  .layout { grid-template-columns: 1fr; }
  .side-col { position: static; }
}

/* "Pixel panel" — a chunky hard-offset shadow instead of a soft drop shadow
   is the single biggest lever for reading as 8-bit UI rather than a
   re-colored modern one; used on every card, button, and bordered box below. */
.card {
  background: var(--bg-panel);
  border: 3px solid var(--line);
  box-shadow: 5px 5px 0 rgba(0, 0, 0, 0.55), 0 0 0 1px rgba(0, 255, 249, 0.08) inset;
  border-radius: 0;
  padding: 20px 22px;
  margin-bottom: 22px;
}

h2 {
  font-family: "Press Start 2P", monospace;
  color: var(--cyan);
  font-size: 13px;
  letter-spacing: 0.5px;
  margin: 0 0 14px;
  text-shadow: 0 0 8px rgba(0, 255, 249, 0.5);
  line-height: 1.6;
}
.muted { color: var(--muted); font-size: 13px; }
label { font-size: 12px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase; color: var(--yellow); display: block; margin: 12px 0 5px; }

select, textarea, input {
  width: 100%;
  padding: 10px 11px;
  border: 2px solid var(--line);
  background: var(--bg-inset);
  color: var(--ink);
  border-radius: 0;
  font: inherit;
}
select:focus, textarea:focus, input:focus { outline: none; border-color: var(--cyan); box-shadow: 0 0 0 2px rgba(0, 255, 249, 0.3); }

button {
  background: var(--magenta);
  color: #000; /* pure black, not navy — a bit more margin on top of magenta's ~5.8:1, see the chat-bubble comment below for why saturated magenta backgrounds need the extra headroom */
  border: 2px solid #1a0a2e;
  padding: 11px 18px;
  border-radius: 0;
  font: inherit;
  font-family: "Press Start 2P", monospace;
  font-size: 11px;
  letter-spacing: 0.5px;
  cursor: pointer;
  box-shadow: 3px 3px 0 rgba(0, 0, 0, 0.7);
  transition: transform 0.05s linear, box-shadow 0.05s linear;
}
button:hover { background: #ff5cdc; }
/* Arcade "press" feel: the button physically moves into its own shadow. */
button:active { transform: translate(3px, 3px); box-shadow: 0 0 0 rgba(0, 0, 0, 0.7); }
button.secondary { background: var(--bg-inset); color: var(--cyan); border: 2px solid var(--cyan); }
button.secondary:hover { background: rgba(0, 255, 249, 0.12); }
button.link { background: transparent; color: var(--cyan); border: 0; box-shadow: none; padding: 6px 4px; font-family: inherit; font-size: 12px; text-decoration: underline; cursor: pointer; }
button.link:active { transform: none; }
button:disabled { opacity: 0.5; cursor: not-allowed; }

.row { display: flex; gap: 10px; align-items: center; }
.persona-box { background: var(--bg-inset); border: 2px solid var(--line); border-left: 4px solid var(--magenta); padding: 12px 14px; font-size: 13px; margin-top: 6px; }
#chat, #app { display: none; }
.subhead { font-size: 12px; color: var(--muted); margin: -6px 0 12px; }

.messages {
  border: 2px solid var(--line);
  height: 380px;
  overflow-y: auto;
  padding: 14px;
  background: var(--bg-inset);
}
.msg { margin-bottom: 12px; display: flex; align-items: flex-end; gap: 6px; }
/* Dark fill + a neon border for identity, NOT a solid neon fill behind body
   text. A solid saturated magenta background technically clears WCAG AA
   contrast against dark text (~5.8:1) but is still genuinely hard to read
   for anything longer than a short label — highly saturated hues cause a
   real perceptual "vibration"/glare effect at paragraph length, independent
   of the contrast-ratio math. Every other panel in this app already uses
   dark-bg + neon-border + neon/white text (see .card, h2, .band-*) — this
   just brings the chat bubbles in line with that, instead of being the one
   place that didn't follow it. */
.msg .bubble { padding: 10px 13px; border: 2px solid; max-width: 74%; font-size: 14px; line-height: 1.4; white-space: pre-wrap; background: var(--bg-inset); color: var(--ink); }
.msg.se { justify-content: flex-end; }
.msg.se .bubble { border-color: var(--cyan); box-shadow: 0 0 6px rgba(0, 255, 249, 0.25); }
.msg.cust .bubble { border-color: var(--magenta); box-shadow: 0 0 6px rgba(255, 47, 208, 0.25); }
.msg .sprite-accent { width: 18px; height: 14px; flex-shrink: 0; image-rendering: pixelated; opacity: 0.9; }
.who { font-size: 10px; color: var(--muted); margin: 0 6px; align-self: center; text-transform: uppercase; letter-spacing: 0.5px; }

/* ---------- Text-to-speech (ADR-14) ---------- */
/* Small icon button, not the full "pixel panel" button style (magenta fill
   + hard-offset shadow) used everywhere else — that's sized/weighted for
   primary actions like "Send" or "Begin Discovery Call"; this needs to sit
   quietly next to a chat bubble without competing with it. */
.msg .speak-btn {
  flex-shrink: 0;
  align-self: center;
  width: 26px;
  height: 26px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-inset);
  border: 2px solid var(--cyan);
  box-shadow: none;
}
.msg .speak-btn:hover { background: rgba(0, 255, 249, 0.12); }
.msg .speak-btn:active { transform: none; }
.msg .speak-btn svg { width: 15px; height: 13px; image-rendering: pixelated; }
/* Active-playback state: a static color/glow change, not a strobe — see
   ARCHITECTURE.md's CRT-scanline note (ADR-10) on why this app avoids
   flicker/animation for photosensitivity reasons. */
.msg .speak-btn.speaking { border-color: var(--green); box-shadow: 0 0 6px rgba(57, 255, 20, 0.45); }

.tts-toggle { margin: 4px 0 12px; }
.tts-toggle .tts-icon { width: 16px; height: 14px; flex-shrink: 0; image-rendering: pixelated; }
.composer { display: flex; gap: 8px; margin-top: 12px; }
/* min-height keeps the original one-line resting size; max-height caps how
   tall the auto-grow (see #input's "input" listener + speech-recognition
   callback in app.js) is allowed to get before it scrolls instead of
   pushing the rest of the page around. resize:none because growth is
   automatic now — a manual drag-handle would just fight the JS-driven
   height. */
.composer textarea { resize: none; min-height: 46px; max-height: 220px; overflow-y: auto; }

/* ---------- Voice input (ADR-15) ---------- */
/* Same small-icon-button treatment as .speak-btn, sized to match the
   composer's 46px-tall textarea rather than the 26px chat-bubble buttons. */
.mic-btn {
  flex-shrink: 0;
  align-self: stretch;
  width: 46px;
  padding: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--bg-inset);
  border: 2px solid var(--cyan);
  box-shadow: none;
}
.mic-btn:hover { background: rgba(0, 255, 249, 0.12); }
.mic-btn:active { transform: none; }
.mic-btn svg { width: 16px; height: 18px; image-rendering: pixelated; }
/* Listening state: a static color/glow change, not a strobe — same
   photosensitivity rule as .speak-btn.speaking (ADR-10). */
.mic-btn.listening { border-color: var(--green); box-shadow: 0 0 6px rgba(57, 255, 20, 0.45); }
.mic-btn[hidden] { display: none; }

/* ---------- Front-page chiptune music toggle (ADR-19) ---------- */
.music-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding: 8px 14px;
  font-size: 11px;
  background: var(--bg-inset);
  color: var(--cyan); /* bug fix: without this the base `button{color:#000}` rule
    (meant for text on the bright magenta primary button) wins instead, rendering
    "Music: On/Off" as near-black text on this button's own dark background —
    same color: var(--cyan) treatment button.secondary already uses for this
    exact dark-bg/cyan-border combination. */
  border: 2px solid var(--cyan);
  box-shadow: none;
}
.music-btn:hover { background: rgba(0, 255, 249, 0.12); }
.music-btn:active { transform: none; }
.music-btn .music-icon { width: 12px; height: 14px; flex-shrink: 0; image-rendering: pixelated; }
/* Playing state: a static color/glow change, not a strobe — same
   photosensitivity rule as .speak-btn.speaking / .mic-btn.listening (ADR-10). */
.music-btn.playing { border-color: var(--green); box-shadow: 0 0 6px rgba(57, 255, 20, 0.45); }

.report .score-grid { display: grid; grid-template-columns: 1fr; gap: 10px; margin-top: 12px; }
.dim { border: 2px solid var(--line); padding: 10px 12px; background: var(--bg-inset); }
.dim .head { display: flex; justify-content: space-between; font-weight: 700; font-size: 13px; }
.pill { font-size: 12px; padding: 2px 9px; color: #0d0221; }
/* Blocky "health bar" segments instead of a smooth gradient bar — a small
   repeating-gradient stripe pattern is enough to read as retro pixel UI. */
.bar {
  height: 10px;
  background: #2a1a4a;
  border: 1px solid var(--line);
  margin: 8px 0 4px;
  overflow: hidden;
}
.bar > i {
  display: block;
  height: 100%;
  background: repeating-linear-gradient(to right, var(--cyan) 0 6px, #0d0221 6px 7px);
}
.band { font-family: "Press Start 2P", monospace; font-size: 16px; font-weight: 400; color: var(--cyan); text-shadow: 0 0 6px currentColor; }
ul.tight { margin: 6px 0; padding-left: 20px; } ul.tight li { margin: 4px 0; font-size: 14px; }
.err { color: var(--err); font-size: 13px; margin-top: 8px; }
.ok-msg { color: var(--green); font-size: 13px; margin-top: 8px; }
.spinner { font-size: 13px; color: var(--yellow); display: flex; align-items: center; gap: 8px; }
.spinner .sprite-accent { width: 20px; height: 14px; image-rendering: pixelated; animation: blink-invader 1s steps(1) infinite; }
@keyframes blink-invader { 50% { opacity: 0.35; } }

.quiz-q { margin-bottom: 14px; }
hr { border: 0; border-top: 2px dashed var(--line); margin: 18px 0; }
.badge { display: inline-block; font-size: 10px; background: var(--bg-inset); border: 1px solid var(--cyan); color: var(--cyan); padding: 3px 8px; margin-left: 6px; text-transform: uppercase; letter-spacing: 0.5px; }

.history-item { border: 2px solid var(--line); padding: 10px 12px; margin-bottom: 8px; cursor: pointer; background: var(--bg-inset); }
.history-item:hover { border-color: var(--magenta); }
.history-item .head { display: flex; justify-content: space-between; font-weight: 700; font-size: 13px; }
.history-detail { display: none; margin-top: 10px; padding-top: 10px; border-top: 1px dashed var(--line); }

#loginGate { max-width: 460px; margin: 70px auto; text-align: center; }
#loginGate .arcade-sprite { width: 64px; height: 64px; image-rendering: pixelated; margin-bottom: 6px; }
#loginGate button { padding: 14px 26px; font-size: 13px; }
#loginGate h2 { text-align: center; font-size: 15px; }

/* ---------- Weekly high-score leaderboard ---------- */
#leaderboardCard .week-label { font-size: 11px; color: var(--yellow); text-align: right; margin: -8px 0 12px; letter-spacing: 0.5px; }
.lb-row { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border: 2px solid var(--line); background: var(--bg-inset); margin-bottom: 6px; }
.lb-rank { font-family: "Press Start 2P", monospace; font-size: 12px; color: var(--muted); width: 34px; flex-shrink: 0; }
.lb-row.lb-top1 { border-color: var(--yellow); box-shadow: 0 0 10px rgba(255, 230, 0, 0.35); }
.lb-row.lb-top1 .lb-rank { color: var(--yellow); }
.lb-row.lb-top2 .lb-rank { color: #c9c9d8; }
.lb-row.lb-top3 .lb-rank { color: #cd8a4a; }
.lb-trophy { width: 22px; height: 18px; flex-shrink: 0; image-rendering: pixelated; }
.lb-who { flex: 1; min-width: 0; }
.lb-name { font-size: 13px; font-weight: 700; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-context { font-size: 11px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.lb-score { font-family: "Press Start 2P", monospace; font-size: 13px; color: var(--green); text-shadow: 0 0 5px rgba(57, 255, 20, 0.5); flex-shrink: 0; }
.lb-optout { display: flex; align-items: center; gap: 8px; font-size: 12px; color: var(--muted); margin-top: 10px; }
.lb-optout input { width: auto; }

/* Respect reduced-motion preferences for the invader blink. */
@media (prefers-reduced-motion: reduce) {
  .spinner .sprite-accent { animation: none; }
}

/* ---------- Utility classes ----------
   IMPORTANT: this app's CSP is `style-src 'self'` with no 'unsafe-inline'
   (server.js), which silently no-ops any `style="..."` attribute written
   into HTML markup OR injected via innerHTML — including ones set from a
   JS template string. It does NOT block `el.style.x = value` assigned via
   the CSSOM after the fact (that's a script action, gated by script-src,
   not style-src). Every one-off layout tweak in index.html/app.js has to be
   a class here for that reason — never a `style="..."` attribute, and never
   an innerHTML template that writes one. See ARCHITECTURE.md's CSP note. */
.sprite-defs-svg { position: absolute; }
#signOutBtn, #loginGate, #report, #quizCard, #chatSpinner { display: none; }
.login-sub { text-align: center; margin-bottom: 14px; }
.row-center { justify-content: center; }
.row-between { justify-content: space-between; }
.row-gap-lg { gap: 14px; }
#loginErr { text-align: center; }
.h2-icon { vertical-align: -4px; margin-right: 6px; }
.actions { margin-top: 14px; }
.quiz-grade-item { margin-bottom: 8px; }
/* Score bar fill — fixed-step width classes (rubric scores are 0-4) instead
   of an inline `style="width:..."`, for the CSP reason above. */
.bar > i.w0 { width: 0%; }
.bar > i.w1 { width: 25%; }
.bar > i.w2 { width: 50%; }
.bar > i.w3 { width: 75%; }
.bar > i.w4 { width: 100%; }
/* Band color — class per band instead of an inline `style="color:..."`. */
.band-strong { color: var(--green); }
.band-solid { color: var(--cyan); }
.band-developing { color: var(--err); }
