/* ============================================================================
   CODE QUEST — components.css
   Every reusable surface and control in the project.

   Interaction contract, applied to all of them:
     rest → hover (lift + glow) → focus-visible (ring) → active (press down)
     → disabled/locked (dashed edge + muted fill + text, never colour alone)
   ========================================================================== */

/* ============================================================================
   1. BUTTONS
   ========================================================================== */

.cq-btn {
  --btn-lift: -2px;
  --btn-scale: 1.03;

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  min-height: 46px;
  padding: var(--sp-3) var(--sp-5);
  border: var(--border-hair) solid var(--glass-edge-hi);
  border-radius: var(--r-md);
  background:
    linear-gradient(180deg, rgba(63, 201, 247, 0.16), rgba(63, 201, 247, 0.05));
  color: var(--text-primary);
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  text-align: center;
  white-space: nowrap;
  box-shadow: var(--elev-1), var(--glass-lip);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  isolation: isolate;
  transition:
    transform var(--dur-fast) var(--ease-out-quint),
    box-shadow var(--dur-mid) var(--ease-out-expo),
    border-color var(--dur-fast) linear,
    background-color var(--dur-fast) linear,
    filter var(--dur-fast) linear;
}

/* A light wash that fades in on hover, under the label. */
.cq-btn::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  border-radius: inherit;
  background: linear-gradient(180deg, rgba(122, 221, 255, 0.24), rgba(63, 201, 247, 0.08));
  opacity: 0;
  transition: opacity var(--dur-mid) var(--ease-out-expo);
}

.cq-btn:hover:not(:disabled):not([aria-disabled='true']) {
  transform: translate3d(0, var(--btn-lift), 0) scale(var(--btn-scale));
  border-color: var(--cyan-300);
  box-shadow: var(--elev-2), var(--glow-cyan-md);
}

.cq-btn:hover:not(:disabled):not([aria-disabled='true'])::before {
  opacity: 1;
}

.cq-btn:focus-visible {
  box-shadow: var(--focus-ring);
  border-color: var(--cyan-200);
}

/* Press: the button goes *down* and the glow tightens — a real click feel. */
.cq-btn:active:not(:disabled):not([aria-disabled='true']) {
  transform: translate3d(0, 1px, 0) scale(0.985);
  box-shadow: var(--elev-1), var(--glow-cyan-sm);
  transition-duration: var(--dur-instant);
}

.cq-btn:disabled,
.cq-btn[aria-disabled='true'] {
  border-style: dashed;
  border-color: var(--locked-edge);
  background: var(--locked-soft);
  color: var(--text-muted);
  box-shadow: none;
  transform: none;
  cursor: not-allowed;
  filter: saturate(0.4);
}

.cq-btn:disabled::before,
.cq-btn[aria-disabled='true']::before {
  opacity: 0;
}

/* ---------- Primary: the gold call to action ---------- */

.cq-btn--primary {
  border-color: var(--gold-300);
  background: linear-gradient(180deg, var(--gold-200) 0%, var(--gold-400) 52%, var(--gold-500) 100%);
  color: var(--text-on-gold);
  box-shadow: var(--elev-2), var(--glow-gold-sm), inset 0 1px 0 rgba(255, 255, 255, 0.45);
}

.cq-btn--primary::before {
  background: linear-gradient(180deg, var(--gold-100), var(--gold-300));
}

.cq-btn--primary:hover:not(:disabled) {
  border-color: var(--gold-100);
  box-shadow: var(--elev-3), var(--glow-gold-md), inset 0 1px 0 rgba(255, 255, 255, 0.55);
}

.cq-btn--primary:active:not(:disabled) {
  box-shadow: var(--elev-1), var(--glow-gold-sm), inset 0 2px 5px rgba(107, 74, 16, 0.4);
}

/* ---------- Hero: the single biggest button on a page ----------
   Floats gently at rest, carries a bloom behind it, and grows on hover. */

.cq-btn--hero {
  --btn-scale: 1.05;

  min-height: 62px;
  padding: var(--sp-4) var(--sp-8);
  font-size: var(--fs-md);
  letter-spacing: var(--ls-wider);
  border-radius: var(--r-lg);
  border-width: var(--border-thin);
}

/* The wrapper floats, the button inside it scales on hover. Splitting them is
   deliberate: both effects are `transform`, and on one element the hover
   scale and the float keyframes would overwrite each other. */
/* A centred row of actions at the end of a flow — the last screen of a test,
   a victory panel, a result page. It used to be spelled `.cq-hero__actions`
   and live with the old cover; it is a layout utility, not part of any one
   screen, so it belongs here with the buttons it arranges. responsive.css
   stacks it (and its siblings) into a full-width column on a phone. */
.cq-actions-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  justify-content: center;
  align-items: center;
}

.cq-btn-hero-wrap {
  position: relative;
  display: inline-block;
  animation: cq-float 4.6s var(--ease-in-out-soft) infinite;
}

/* The float HOLDS STILL the moment the learner reaches for the button.
   A control that keeps drifting under the cursor is harder to hit and reads
   as unfinished, so pointing at it — or focusing it with the keyboard —
   settles it, and the hover scale then lands on a stationary target. */
.cq-btn-hero-wrap:hover,
.cq-btn-hero-wrap:focus-within {
  animation-play-state: paused;
}

.cq-btn-hero-wrap::after {
  content: '';
  position: absolute;
  inset: -60% -35%;
  z-index: 0;
  background: radial-gradient(
    ellipse,
    rgba(239, 189, 87, 0.32) 0%,
    rgba(239, 189, 87, 0.1) 38%,
    transparent 68%
  );
  pointer-events: none;
  animation: cq-bloom-breathe 5s var(--ease-in-out-soft) infinite;
}

.cq-btn-hero-wrap > .cq-btn {
  position: relative;
  z-index: 1;
}

/* ---------- Ghost: secondary, quiet ---------- */

.cq-btn--ghost {
  background: rgba(122, 221, 255, 0.04);
  border-color: rgba(166, 188, 216, 0.28);
  font-weight: var(--fw-semibold);
  box-shadow: none;
}

.cq-btn--ghost:hover:not(:disabled) {
  border-color: var(--cyan-400);
  box-shadow: var(--elev-1), var(--glow-cyan-sm);
}

/* ---------- Danger ---------- */

.cq-btn--danger {
  border-color: var(--danger-edge);
  background: var(--danger-soft);
  color: var(--danger);
}

.cq-btn--danger::before {
  background: rgba(255, 111, 134, 0.2);
}

.cq-btn--danger:hover:not(:disabled) {
  border-color: var(--danger);
  box-shadow: var(--elev-2), var(--glow-danger);
}

/* ---------- Sizes & shapes ---------- */

.cq-btn--sm {
  min-height: 36px;
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-2xs);
  border-radius: var(--r-sm);
}

.cq-btn--lg {
  min-height: 54px;
  padding: var(--sp-4) var(--sp-7);
  font-size: var(--fs-base);
  border-radius: var(--r-lg);
}

.cq-btn--block {
  width: 100%;
}

.cq-btn--icon {
  min-height: 42px;
  width: 42px;
  padding: 0;
  border-radius: var(--r-md);
}

.cq-btn__icon {
  font-size: 1.15em;
  line-height: 1;
}

/* ============================================================================
   2. PANELS
   ========================================================================== */

.cq-panel {
  position: relative;
  padding: var(--gap-panel);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-lg);
  background: var(--glass-fill);
  box-shadow: var(--elev-2), var(--glass-lip);
  backdrop-filter: blur(var(--glass-blur)) saturate(1.22);
  -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(1.22);
}

.cq-panel--strong {
  background: var(--glass-fill-strong);
  border-color: var(--glass-edge-hi);
  box-shadow: var(--elev-3), var(--glass-lip-strong);
}

.cq-panel--soft {
  background: var(--glass-fill-soft);
  box-shadow: var(--elev-1), var(--glass-lip);
}

.cq-panel--tight { padding: var(--sp-4); }
.cq-panel--roomy { padding: clamp(1.25rem, 1rem + 1.6vw, 2.25rem); }
.cq-panel--flush { padding: 0; overflow: hidden; }

/* The accented top seam — the project's signature panel detail. */
.cq-panel--edge::before {
  content: '';
  position: absolute;
  inset-inline: 10%;
  top: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--cyan-400) 26%,
    var(--gold-300) 72%,
    transparent
  );
  opacity: 0.75;
  pointer-events: none;
}

.cq-panel--edge {
  overflow: hidden;
}

.cq-panel--lift {
  transition: transform var(--dur-mid) var(--ease-out-expo),
    box-shadow var(--dur-mid) var(--ease-out-expo),
    border-color var(--dur-fast) linear;
}

.cq-panel--lift:hover {
  transform: translate3d(0, -3px, 0);
  border-color: var(--glass-edge-hi);
  box-shadow: var(--elev-3), var(--glow-cyan-sm);
}

.cq-panel__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  flex-wrap: wrap;
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: var(--border-hair) solid rgba(122, 221, 255, 0.12);
}

.cq-panel__title {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  margin: 0;
}

.cq-panel__sub {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  margin: 0;
}

/* ============================================================================
   3. STAT TILES
   ========================================================================== */

.cq-stat {
  position: relative;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: linear-gradient(160deg, rgba(15, 29, 54, 0.72), rgba(8, 17, 33, 0.55));
  box-shadow: var(--glass-lip);
  overflow: hidden;
  transition: transform var(--dur-mid) var(--ease-out-expo),
    border-color var(--dur-fast) linear, box-shadow var(--dur-mid) var(--ease-out-expo);
}

/* A quiet vertical accent bar on the left edge. */
.cq-stat::before {
  content: '';
  position: absolute;
  left: 0;
  top: 18%;
  bottom: 18%;
  width: 2px;
  border-radius: var(--r-pill);
  background: linear-gradient(180deg, var(--cyan-400), transparent);
}

.cq-stat--gold::before {
  background: linear-gradient(180deg, var(--gold-400), transparent);
}

.cq-stat:hover {
  transform: translate3d(0, -2px, 0);
  border-color: var(--glass-edge-hi);
  box-shadow: var(--glass-lip), var(--glow-cyan-sm);
}

.cq-stat__icon {
  flex: 0 0 auto;
  width: 34px;
  height: 34px;
  object-fit: contain;
}

.cq-stat__body {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.cq-stat__label {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--text-muted);
}

.cq-stat__value {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-black);
  font-variant-numeric: tabular-nums;
  color: var(--text-primary);
  line-height: 1.15;
}

.cq-stat__value--gold { color: var(--gold-200); }
.cq-stat__value--cyan { color: var(--cyan-200); }
.cq-stat__value--jade { color: var(--jade-300); }

.cq-stat__note {
  font-size: var(--fs-3xs);
  color: var(--text-muted);
}

/* ============================================================================
   4. PROGRESS
   ========================================================================== */

.cq-progress {
  position: relative;
  height: 10px;
  width: 100%;
  border-radius: var(--r-pill);
  background: rgba(3, 6, 15, 0.72);
  border: var(--border-hair) solid rgba(122, 221, 255, 0.14);
  overflow: hidden;
  box-shadow: inset 0 1px 3px rgba(0, 0, 0, 0.5);
}

.cq-progress__fill {
  position: relative;
  height: 100%;
  width: 0;
  border-radius: inherit;
  background: linear-gradient(90deg, var(--cyan-600), var(--cyan-300) 70%, var(--cyan-100));
  box-shadow: 0 0 14px rgba(63, 201, 247, 0.62);
  transition: width var(--dur-slower) var(--ease-out-expo);
}

/* A travelling highlight so a filling bar reads as energised. */
.cq-progress__fill::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, 0.34) 50%,
    transparent 100%
  );
  background-size: 90px 100%;
  background-repeat: repeat-x;
  animation: cq-progress-shimmer 1.8s linear infinite;
}

@keyframes cq-progress-shimmer {
  to { background-position: 90px 0; }
}

.cq-progress__fill--gold {
  background: linear-gradient(90deg, var(--gold-600), var(--gold-300) 70%, var(--gold-100));
  box-shadow: 0 0 14px rgba(239, 189, 87, 0.6);
}

.cq-progress__fill--jade {
  background: linear-gradient(90deg, var(--jade-500), var(--jade-300));
  box-shadow: 0 0 14px rgba(69, 227, 180, 0.5);
}

.cq-progress--slim { height: 6px; }
.cq-progress--thick { height: 14px; }

/* Tick marks behind the bar, for a segmented "milestones" look. */
.cq-progress--ticked::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: linear-gradient(90deg, rgba(122, 221, 255, 0.22) 1px, transparent 1px);
  background-size: 12.5% 100%;
  pointer-events: none;
  z-index: 1;
}

/* ============================================================================
   5. CHIPS & BADGES
   ========================================================================== */

.cq-chip {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 5px var(--sp-3);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: rgba(63, 201, 247, 0.1);
  color: var(--cyan-100);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  white-space: nowrap;
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
}

.cq-chip--gold {
  border-color: rgba(239, 189, 87, 0.42);
  background: rgba(239, 189, 87, 0.12);
  color: var(--gold-200);
}

.cq-chip--success {
  border-color: var(--success-edge);
  background: var(--success-soft);
  color: var(--success);
}

.cq-chip--danger {
  border-color: var(--danger-edge);
  background: var(--danger-soft);
  color: var(--danger);
}

.cq-chip--locked {
  border-color: var(--locked-edge);
  border-style: dashed;
  background: var(--locked-soft);
  color: var(--text-muted);
}

.cq-chip--lg {
  padding: var(--sp-2) var(--sp-4);
  font-size: var(--fs-xs);
}

/* An interactive chip (used for topic tags on the cover). */
.cq-chip--tap {
  cursor: default;
  transition: transform var(--dur-fast) var(--ease-out-quint),
    box-shadow var(--dur-fast) var(--ease-out-expo), border-color var(--dur-fast) linear;
}

.cq-chip--tap:hover {
  transform: translate3d(0, -2px, 0);
  border-color: var(--cyan-300);
  box-shadow: var(--glow-cyan-sm);
}

/* ============================================================================
   6. CORE SLOTS — the 0/6 collection
   ========================================================================== */

/* The six Logic Cores are a set — they read as a collection only when they sit
   on one line. A 6-column grid with flexible tracks keeps them together in the
   dashboard's narrow side column instead of leaving one orphan on a second
   row, and the aspect-ratio on .cq-core keeps them circular as they shrink. */
.cq-cores {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: var(--sp-2);
  align-items: center;
}

.cq-core {
  position: relative;
  width: 100%;
  max-width: 46px;
  aspect-ratio: 1 / 1;
  margin-inline: auto;
  border-radius: 50%;
  border: var(--border-thin) dashed var(--locked-edge);
  background: rgba(3, 6, 15, 0.6);
  display: grid;
  place-items: center;
  font-size: var(--fs-sm);
  font-weight: var(--fw-bold);
  color: var(--text-muted);
  transition: transform var(--dur-mid) var(--ease-out-back),
    box-shadow var(--dur-mid) var(--ease-out-expo), border-color var(--dur-fast) linear;
}

.cq-core--earned {
  border-style: solid;
  border-color: var(--cyan-300);
  background:
    radial-gradient(circle at 50% 36%, var(--cyan-100) 0%, var(--cyan-400) 44%, var(--cyan-700) 100%);
  color: var(--bg-abyss);
  box-shadow: var(--glow-cyan-md), inset 0 -3px 8px rgba(5, 59, 82, 0.6);
}

/* An orbiting ring on an earned core. */
.cq-core--earned::after {
  content: '';
  position: absolute;
  inset: -5px;
  border-radius: 50%;
  border: 1px solid rgba(122, 221, 255, 0.45);
  border-top-color: transparent;
  border-left-color: transparent;
  animation: cq-orbit 7s linear infinite;
}

.cq-core:hover {
  transform: scale(1.08);
}

.cq-core--earned:hover {
  box-shadow: var(--glow-cyan-lg);
}

/* ============================================================================
   7. STARS
   ========================================================================== */

.cq-stars {
  display: inline-flex;
  gap: 3px;
  font-size: var(--fs-lg);
  line-height: 1;
}

.cq-star {
  color: var(--locked);
  transition: color var(--dur-mid) linear, transform var(--dur-mid) var(--ease-out-back);
}

.cq-star--on {
  color: var(--gold-300);
}

/* ============================================================================
   8. FORMS
   ========================================================================== */

.cq-field {
  display: block;
}

.cq-field__label {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-2);
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  color: var(--text-secondary);
}

.cq-field__req {
  color: var(--gold-300);
}

.cq-input,
.cq-select {
  width: 100%;
  min-height: 52px;
  padding: var(--sp-3) var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: rgba(3, 6, 15, 0.62);
  color: var(--text-primary);
  font-size: var(--fs-base);
  box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.34);
  transition: border-color var(--dur-fast) linear, box-shadow var(--dur-mid) var(--ease-out-expo),
    background-color var(--dur-fast) linear;
}

.cq-select {
  appearance: none;
  padding-right: var(--sp-7);
  background-image:
    linear-gradient(45deg, transparent 50%, var(--cyan-300) 50%),
    linear-gradient(135deg, var(--cyan-300) 50%, transparent 50%);
  background-position: calc(100% - 21px) 50%, calc(100% - 15px) 50%;
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

.cq-select option {
  background: var(--bg-mid);
  color: var(--text-primary);
}

.cq-input::placeholder {
  color: var(--text-muted);
}

.cq-input:hover:not(:disabled),
.cq-select:hover:not(:disabled) {
  border-color: rgba(122, 221, 255, 0.34);
  background: rgba(3, 6, 15, 0.5);
}

.cq-input:focus-visible,
.cq-select:focus-visible {
  border-color: var(--cyan-300);
  box-shadow: var(--focus-ring), inset 0 2px 6px rgba(0, 0, 0, 0.3);
  background: rgba(8, 17, 33, 0.7);
}

.cq-input[aria-invalid='true'] {
  border-color: var(--danger);
  background: var(--danger-soft);
}

.cq-input:disabled,
.cq-input[readonly] {
  color: var(--text-secondary);
  background: rgba(3, 6, 15, 0.4);
  border-style: dashed;
  cursor: not-allowed;
}

.cq-field__error {
  display: block;
  min-height: 1.25em;
  margin-top: var(--sp-1);
  font-size: var(--fs-2xs);
  color: var(--danger);
}

/* ---------- Range slider (sound panel) ---------- */

.cq-range {
  -webkit-appearance: none;
  appearance: none;
  width: 100%;
  height: 22px;
  background: transparent;
  cursor: pointer;
}

.cq-range::-webkit-slider-runnable-track {
  height: 6px;
  border-radius: var(--r-pill);
  background: linear-gradient(
    90deg,
    var(--cyan-400) 0%,
    var(--cyan-400) var(--val, 50%),
    rgba(3, 6, 15, 0.75) var(--val, 50%),
    rgba(3, 6, 15, 0.75) 100%
  );
  border: var(--border-hair) solid rgba(122, 221, 255, 0.2);
}

.cq-range::-moz-range-track {
  height: 6px;
  border-radius: var(--r-pill);
  background: rgba(3, 6, 15, 0.75);
  border: var(--border-hair) solid rgba(122, 221, 255, 0.2);
}

.cq-range::-moz-range-progress {
  height: 6px;
  border-radius: var(--r-pill);
  background: var(--cyan-400);
}

.cq-range::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 16px;
  height: 16px;
  margin-top: -6px;
  border-radius: 50%;
  background: var(--cyan-100);
  border: 2px solid var(--cyan-500);
  box-shadow: var(--glow-cyan-sm);
  transition: transform var(--dur-fast) var(--ease-out-back);
}

.cq-range::-moz-range-thumb {
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--cyan-100);
  border: 2px solid var(--cyan-500);
  box-shadow: var(--glow-cyan-sm);
}

.cq-range:hover::-webkit-slider-thumb {
  transform: scale(1.22);
}

.cq-range:focus-visible {
  box-shadow: none;
}

.cq-range:focus-visible::-webkit-slider-thumb {
  box-shadow: var(--focus-ring);
}

/* ============================================================================
   9. DIALOGUE BOX
   ========================================================================== */

.cq-dialogue {
  position: relative;
  display: flex;
  align-items: stretch;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge-hi);
  border-radius: var(--r-lg);
  background: linear-gradient(150deg, rgba(10, 22, 42, 0.93), rgba(5, 12, 26, 0.9));
  box-shadow: var(--elev-3), var(--glass-lip);
  backdrop-filter: blur(var(--glass-blur-heavy));
  -webkit-backdrop-filter: blur(var(--glass-blur-heavy));
  overflow: hidden;
}

.cq-dialogue::before {
  content: '';
  position: absolute;
  inset-inline: 8%;
  top: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--cyan-300), transparent);
  opacity: 0.7;
}

.cq-dialogue__portrait {
  flex: 0 0 auto;
  width: 88px;
  height: 88px;
  border-radius: var(--r-md);
  border: var(--border-hair) solid var(--glass-edge-hi);
  background:
    radial-gradient(circle at 50% 30%, rgba(63, 201, 247, 0.16), rgba(3, 6, 15, 0.85));
  object-fit: contain;
  object-position: center bottom;
  box-shadow: var(--glow-cyan-sm);
}

.cq-dialogue--no-portrait .cq-dialogue__portrait {
  display: none;
}

.cq-dialogue__body {
  flex: 1 1 auto;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.cq-dialogue__speaker {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--cyan-200);
  margin: 0;
}

.cq-dialogue__speaker::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--cyan-300);
  box-shadow: 0 0 10px var(--cyan-400);
  flex: 0 0 auto;
}

.cq-dialogue__text {
  min-height: 3.4em;
  font-size: var(--fs-base);
  line-height: var(--lh-thai);
  color: var(--text-primary);
  margin: 0;
}

.cq-dialogue__caret {
  display: inline-block;
  width: 0.5em;
  color: var(--cyan-300);
  animation: cq-blink 900ms steps(1) infinite;
}

.cq-dialogue__controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: var(--sp-1);
}

.cq-dialogue__count {
  font-family: var(--font-body);
  font-size: var(--fs-2xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
}

/* Inside a mission the dialogue is one standing line: no counter, no controls,
   no reserved second row. */
.cq-mission .cq-dialogue {
  padding: var(--sp-3);
}

.cq-mission .cq-dialogue__portrait {
  width: 56px;
  height: 56px;
}

.cq-mission .cq-dialogue__text {
  min-height: 0;
  font-size: var(--fs-sm);
}

.cq-mission .cq-dialogue__controls {
  display: none;
}

/* ============================================================================
   10. HUD — the gameplay top bar
   ========================================================================== */

.cq-hud {
  position: sticky;
  top: 0;
  z-index: var(--z-hud);
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-4);
  min-height: var(--hud-h);
  max-width: 100%;
  padding: var(--sp-2) var(--gutter);
  background: linear-gradient(180deg, rgba(5, 11, 26, 0.96), rgba(5, 11, 26, 0.82));
  border-bottom: var(--border-hair) solid var(--glass-edge);
  box-shadow: 0 1px 0 rgba(122, 221, 255, 0.07), 0 8px 30px rgba(2, 5, 12, 0.5);
  backdrop-filter: blur(16px) saturate(1.25);
  -webkit-backdrop-filter: blur(16px) saturate(1.25);
  overflow: hidden;
}

/* ---- the back control ----
   First thing in the bar, so "the way out" is always in the same place — and
   the arrow is drawn with a border, not an icon file. */
.cq-hud__back {
  flex: 0 0 auto;
  gap: var(--sp-2);
  padding-inline: var(--sp-3) var(--sp-4);
  letter-spacing: var(--ls-normal);
}

.cq-hud__back-mark {
  display: inline-block;
  width: 0.52em;
  height: 0.52em;
  border-left: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform var(--dur-fast) var(--ease-out-quint);
}

.cq-hud__back:hover .cq-hud__back-mark {
  transform: rotate(45deg) translate3d(-1px, 1px, 0);
}

/* On a phone the label steps aside and the arrow alone carries the control —
   its accessible name lives on the button itself, so nothing is lost. */
@media (max-width: 560px) {
  .cq-hud__back-text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .cq-hud__back {
    padding-inline: var(--sp-3);
  }
}

/* A thin energy line along the bottom edge of the bar. */
.cq-hud::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    rgba(63, 201, 247, 0.45) 30%,
    rgba(239, 189, 87, 0.32) 70%,
    transparent
  );
}

.cq-hud__brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex: 0 1 auto;
  min-width: 0;
  font-family: var(--font-display);
  font-size: var(--fs-xs);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-wider);
  color: var(--cyan-100);
  white-space: nowrap;
}

.cq-hud__brand-mark {
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  flex: 0 0 auto;
  color: var(--cyan-300);
  font-size: 0.8em;
  border: var(--border-hair) solid rgba(122, 221, 255, 0.4);
  border-radius: 7px;
  background: rgba(63, 201, 247, 0.1);
  box-shadow: var(--glow-cyan-sm);
}

/* The chapter label — the one variable-width item, so it is the one that
   truncates rather than pushing the bar wider. */
.cq-hud > .cq-chip {
  flex: 0 1 auto;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
}

.cq-hud__items {
  display: flex;
  align-items: center;
  gap: var(--sp-3) var(--sp-4);
  margin-left: auto;
  flex: 0 1 auto;
  min-width: 0;
  flex-wrap: wrap;
  justify-content: flex-end;
}

/* A HUD readout: label above, value below, with a divider before it. */
.cq-hud__item {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0;
  padding-left: var(--sp-4);
  white-space: nowrap;
  line-height: 1.15;
}

.cq-hud__item::before {
  content: '';
  position: absolute;
  left: 0;
  top: 12%;
  bottom: 12%;
  width: 1px;
  background: linear-gradient(180deg, transparent, rgba(122, 221, 255, 0.3), transparent);
}

.cq-hud__item:first-child::before {
  display: none;
}

.cq-hud__item-label {
  font-size: var(--fs-3xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wider);
  text-transform: uppercase;
  color: var(--text-muted);
}

.cq-hud__item-value {
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  font-weight: var(--fw-black);
  font-variant-numeric: tabular-nums;
  color: var(--cyan-100);
  transition: color var(--dur-mid) linear;
}

.cq-hud__item-value--gold {
  color: var(--gold-200);
}

/* Flashes when the value changes — set briefly by game-hud.js. */
.cq-hud__item-value.is-bumped {
  animation: cq-count-settle 520ms var(--ease-out-back);
}

/* ---- sign out ----
   Present on every screen a learner can walk into, for the same reason the
   back control is: a classroom machine is shared, and the token in this
   browser belongs to whoever used it last. It sits at the far end of the bar,
   after the readouts — reachable, but never next to the thumb that is trying
   to press "next". The mark is a door with an arrow leaving it, drawn in CSS. */
.cq-logout {
  flex: 0 0 auto;
  gap: var(--sp-2);
  letter-spacing: var(--ls-normal);
}

.cq-logout__mark {
  position: relative;
  display: inline-block;
  width: 0.78em;
  height: 0.8em;
  flex: 0 0 auto;
  border: 2px solid currentColor;
  border-right: 0;
  border-radius: 2px 0 0 2px;
}

/* the stem of the arrow, leaving the doorway */
.cq-logout__mark::before {
  content: '';
  position: absolute;
  top: 50%;
  right: -0.46em;
  width: 0.52em;
  height: 2px;
  background: currentColor;
  transform: translateY(-50%);
  transition: transform var(--dur-fast) var(--ease-out-quint);
}

/* and its head */
.cq-logout__mark::after {
  content: '';
  position: absolute;
  top: 50%;
  right: -0.42em;
  width: 0.32em;
  height: 0.32em;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
  transform: translate(0, -50%) rotate(45deg);
  transition: transform var(--dur-fast) var(--ease-out-quint);
}

.cq-logout:hover .cq-logout__mark::before {
  transform: translate(2px, -50%);
}

.cq-logout:hover .cq-logout__mark::after {
  transform: translate(2px, -50%) rotate(45deg);
}

/* On a phone the bar is already two rows, so the label steps aside and the
   mark carries the control — the accessible name lives on the button, exactly
   as it does for the back control, so nothing is lost to a screen reader. */
@media (max-width: 560px) {
  .cq-logout--hud .cq-logout__text {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
  }

  .cq-logout--hud {
    padding-inline: var(--sp-3);
  }
}

/* ============================================================================
   11. SOUND PANEL — mute + per-channel volume, in a popover
   ========================================================================== */

.cq-sound {
  position: relative;
  flex: 0 0 auto;
}

.cq-sound__toggle {
  position: relative; /* anchors the muted slash drawn in ::after */
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: rgba(3, 6, 15, 0.55);
  color: var(--cyan-200);
  transition: transform var(--dur-fast) var(--ease-out-quint),
    border-color var(--dur-fast) linear, box-shadow var(--dur-mid) var(--ease-out-expo),
    color var(--dur-fast) linear;
}

.cq-sound__toggle:hover {
  transform: scale(1.06);
  border-color: var(--cyan-300);
  box-shadow: var(--glow-cyan-sm);
}

.cq-sound__toggle:active {
  transform: scale(0.95);
}

.cq-sound__toggle[aria-expanded='true'] {
  border-color: var(--cyan-300);
  box-shadow: var(--glow-cyan-md);
}

.cq-sound__toggle.is-muted {
  border-color: var(--danger-edge);
  color: var(--danger);
}

/* Three animated bars that show sound is on. */
.cq-sound__bars {
  display: flex;
  align-items: flex-end;
  gap: 2px;
  height: 15px;
}

.cq-sound__bars i {
  display: block;
  width: 3px;
  border-radius: 2px;
  background: currentColor;
  animation: cq-eq 900ms var(--ease-in-out-soft) infinite alternate;
}

.cq-sound__bars i:nth-child(1) { height: 7px;  animation-delay: 0ms; }
.cq-sound__bars i:nth-child(2) { height: 14px; animation-delay: 150ms; }
.cq-sound__bars i:nth-child(3) { height: 10px; animation-delay: 300ms; }

@keyframes cq-eq {
  from { transform: scaleY(0.4); }
  to   { transform: scaleY(1); }
}

/* Muted: the bars stop and flatten, and a slash is drawn over them. */
.cq-sound__toggle.is-muted .cq-sound__bars i {
  animation: none;
  transform: scaleY(0.32);
}

.cq-sound__toggle.is-muted::after {
  content: '';
  position: absolute;
  width: 24px;
  height: 2px;
  border-radius: 2px;
  background: var(--danger);
  transform: rotate(-45deg);
  box-shadow: 0 0 8px rgba(255, 111, 134, 0.7);
}

.cq-sound__panel {
  position: absolute;
  top: calc(100% + var(--sp-2));
  right: 0;
  z-index: var(--z-popover);
  width: 258px;
  padding: var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge-hi);
  border-radius: var(--r-lg);
  background: var(--glass-fill-strong);
  box-shadow: var(--elev-4), var(--glass-lip-strong);
  backdrop-filter: blur(var(--glass-blur-heavy)) saturate(1.3);
  -webkit-backdrop-filter: blur(var(--glass-blur-heavy)) saturate(1.3);
  animation: cq-drop var(--dur-mid) var(--ease-out-expo) both;
}

.cq-sound__panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: var(--border-hair) solid rgba(122, 221, 255, 0.14);
}

.cq-sound__row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: var(--sp-2);
  margin-bottom: var(--sp-3);
}

.cq-sound__row:last-child {
  margin-bottom: 0;
}

.cq-sound__row-label {
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  color: var(--text-secondary);
}

.cq-sound__row-val {
  font-family: var(--font-body);
  font-size: var(--fs-3xs);
  color: var(--text-muted);
  font-variant-numeric: tabular-nums;
  min-width: 3.2em;
  text-align: end;
}

.cq-sound__row .cq-range {
  grid-column: 1 / -1;
}

/* A small switch for the mute row. */
.cq-switch {
  position: relative;
  display: inline-flex;
  align-items: center;
  width: 44px;
  height: 24px;
  flex: 0 0 auto;
  border-radius: var(--r-pill);
  border: var(--border-hair) solid var(--glass-edge);
  background: rgba(3, 6, 15, 0.7);
  transition: background-color var(--dur-mid) linear, border-color var(--dur-fast) linear;
}

.cq-switch::after {
  content: '';
  position: absolute;
  left: 3px;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  background: var(--text-muted);
  transition: transform var(--dur-mid) var(--ease-out-back), background-color var(--dur-mid) linear;
}

.cq-switch[aria-checked='true'] {
  background: rgba(63, 201, 247, 0.26);
  border-color: var(--cyan-300);
}

.cq-switch[aria-checked='true']::after {
  transform: translateX(20px);
  background: var(--cyan-100);
  box-shadow: 0 0 10px var(--cyan-300);
}

.cq-switch:focus-visible {
  box-shadow: var(--focus-ring);
}

/* ============================================================================
   11b. REWARD LIST
   A list of badges / achievements / cores that have been earned. Shared: the
   reward modal shows it on every chapter page, the dashboard shows it in the
   side column, and the result page shows it in the reward summary — so it
   belongs here rather than in any one page's stylesheet.
   ========================================================================== */

.cq-reward-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
}

.cq-reward-list__item {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--glass-edge);
  background: var(--glass-fill-soft);
  transition:
    transform var(--dur-fast) var(--ease-out-expo),
    border-color var(--dur-fast) var(--ease-out),
    box-shadow var(--dur-fast) var(--ease-out);
}

.cq-reward-list__item:hover {
  transform: translate3d(0, -2px, 0);
  border-color: rgba(239, 189, 87, 0.3);
  box-shadow: var(--elev-2);
}

.cq-reward-list__item--empty {
  justify-content: center;
  border-style: dashed;
  border-color: rgba(122, 221, 255, 0.16);
  background: transparent;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.cq-reward-list__item--empty:hover {
  transform: none;
  border-color: rgba(122, 221, 255, 0.16);
  box-shadow: none;
}

.cq-reward-list__icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid rgba(239, 189, 87, 0.4);
  background: radial-gradient(
    circle at 50% 38%,
    rgba(239, 189, 87, 0.26),
    rgba(168, 123, 28, 0.12)
  );
  color: var(--gold-200);
  font-size: var(--fs-md);
  line-height: 1;
  box-shadow: var(--glow-gold-sm);
}

.cq-reward-list__name {
  display: block;
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
}

.cq-reward-list__desc {
  display: block;
  font-size: var(--fs-xs);
  line-height: var(--lh-snug);
  color: var(--text-muted);
}


/* ============================================================================
   12. MODAL
   ========================================================================== */

.cq-modal {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);
  display: grid;
  place-items: center;
  padding: var(--sp-4);
  background: var(--overlay-scrim);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  animation: cq-fade-in var(--dur-mid) linear both;
}

.cq-modal__box {
  position: relative;
  width: min(580px, 100%);
  max-height: 88vh;
  overflow-y: auto;
  padding: clamp(1.25rem, 1rem + 1.8vw, 2.25rem);
  border: var(--border-thin) solid var(--glass-edge-hi);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, rgba(14, 29, 54, 0.97), rgba(5, 11, 26, 0.97));
  box-shadow: var(--elev-4), var(--glow-cyan-sm), var(--glass-lip-strong);
  backdrop-filter: blur(var(--glass-blur-heavy));
  -webkit-backdrop-filter: blur(var(--glass-blur-heavy));
}

.cq-modal__box::before {
  content: '';
  position: absolute;
  inset-inline: 14%;
  top: 0;
  height: 2px;
  background: linear-gradient(90deg, transparent, var(--gold-300), var(--cyan-300), transparent);
  border-radius: var(--r-pill);
}

.cq-modal__title {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  font-weight: var(--fw-black);
  margin-bottom: var(--sp-3);
  color: var(--gold-200);
  text-align: center;
}

.cq-modal__body {
  color: var(--text-secondary);
  line-height: var(--lh-thai);
}

.cq-modal__media {
  width: 100%;
  max-height: 34vh;
  object-fit: cover;
  margin-bottom: var(--sp-4);
  border-radius: var(--r-md);
  border: var(--border-hair) solid var(--glass-edge);
}

.cq-modal__actions {
  display: flex;
  gap: var(--sp-3);
  justify-content: center;
  flex-wrap: wrap;
  margin-top: var(--sp-5);
}

/* ---------- Reward variant: the celebratory modal ---------- */

.cq-modal--reward .cq-modal__box {
  border-color: var(--gold-300);
  box-shadow: var(--elev-4), var(--glow-gold-md), var(--glass-lip-strong);
  animation: cq-pop-lg var(--dur-slower) var(--ease-out-back) both;
  text-align: center;
  overflow: hidden;
}

/* Rays behind the reward content. */
.cq-modal--reward .cq-modal__box::after {
  content: '';
  position: absolute;
  inset: -40% -10%;
  z-index: 0;
  background:
    conic-gradient(
      from 0deg,
      transparent 0deg,
      rgba(239, 189, 87, 0.14) 10deg,
      transparent 20deg,
      transparent 40deg,
      rgba(239, 189, 87, 0.1) 50deg,
      transparent 60deg
    );
  animation: cq-orbit 40s linear infinite;
  pointer-events: none;
}

.cq-modal--reward .cq-modal__box > * {
  position: relative;
  z-index: 1;
}

/* ============================================================================
   13. TOAST
   ========================================================================== */

.cq-toasts {
  position: fixed;
  bottom: var(--sp-5);
  left: 50%;
  transform: translateX(-50%);
  z-index: var(--z-toast);
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  width: min(470px, calc(100vw - 2 * var(--sp-4)));
  pointer-events: none;
}

.cq-toast {
  display: flex;
  align-items: flex-start;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge-hi);
  border-left-width: 3px;
  border-radius: var(--r-md);
  background: linear-gradient(150deg, rgba(12, 25, 46, 0.98), rgba(6, 13, 27, 0.98));
  box-shadow: var(--elev-3), var(--glass-lip);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  font-size: var(--fs-sm);
  pointer-events: auto;
}

.cq-toast--success { border-left-color: var(--success); }
.cq-toast--error   { border-left-color: var(--danger); }
.cq-toast--warn    { border-left-color: var(--warning); }
.cq-toast--info    { border-left-color: var(--cyan-400); }

.cq-toast__icon {
  flex: 0 0 auto;
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  font-size: var(--fs-2xs);
  font-weight: var(--fw-black);
  background: rgba(122, 221, 255, 0.14);
  color: var(--cyan-200);
}

.cq-toast--success .cq-toast__icon { background: var(--success-soft); color: var(--success); }
.cq-toast--error .cq-toast__icon   { background: var(--danger-soft);  color: var(--danger); }
.cq-toast--warn .cq-toast__icon    { background: var(--warning-soft); color: var(--warning); }

.cq-toast__body {
  flex: 1 1 auto;
  min-width: 0;
  line-height: var(--lh-relaxed);
}

/* ============================================================================
   14. LOADING SCREEN
   ========================================================================== */

.cq-loader {
  position: fixed;
  inset: 0;
  z-index: var(--z-loader);
  display: grid;
  place-items: center;
  background:
    radial-gradient(ellipse 80% 60% at 50% 40%, var(--bg-mid) 0%, var(--bg-abyss) 72%);
  transition: opacity var(--dur-slower) var(--ease-out-expo);
}

.cq-loader--out {
  opacity: 0;
  pointer-events: none;
}

.cq-loader__inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-4);
  text-align: center;
  padding-inline: var(--sp-4);
}

/* A three-ring energy core, each ring spinning at a different rate. */
.cq-loader__core {
  position: relative;
  width: 86px;
  height: 86px;
}

.cq-loader__core span {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid transparent;
}

.cq-loader__core span:nth-child(1) {
  border-top-color: var(--cyan-300);
  border-right-color: rgba(63, 201, 247, 0.3);
  animation: cq-orbit 1.1s linear infinite;
}

.cq-loader__core span:nth-child(2) {
  inset: 12px;
  border-bottom-color: var(--gold-300);
  border-left-color: rgba(239, 189, 87, 0.28);
  animation: cq-orbit 1.7s linear infinite reverse;
}

.cq-loader__core span:nth-child(3) {
  inset: 26px;
  border-radius: 50%;
  border: 0;
  background: radial-gradient(circle, var(--cyan-100), var(--cyan-500) 62%, transparent 78%);
  box-shadow: var(--glow-cyan-md);
  animation: cq-bloom-breathe 1.8s var(--ease-in-out-soft) infinite;
}

.cq-loader__title {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-black);
  letter-spacing: var(--ls-widest);
  color: var(--cyan-100);
}

.cq-loader__msg {
  font-size: var(--fs-xs);
  color: var(--text-secondary);
  min-height: 1.4em;
}

.cq-loader__bar {
  width: min(280px, 70vw);
  height: 4px;
  border-radius: var(--r-pill);
  background: rgba(63, 201, 247, 0.14);
  overflow: hidden;
}

.cq-loader__bar-fill {
  height: 100%;
  width: 0;
  background: linear-gradient(90deg, var(--cyan-500), var(--cyan-200));
  box-shadow: 0 0 12px rgba(63, 201, 247, 0.6);
  transition: width var(--dur-mid) var(--ease-out-expo);
}

/* Legacy alias kept so loading-screen.js needs no change. */
.cq-loader__ring {
  width: 74px;
  height: 74px;
  border-radius: 50%;
  border: 3px solid rgba(63, 201, 247, 0.18);
  border-top-color: var(--cyan-300);
  animation: cq-orbit 900ms linear infinite;
}

/* ============================================================================
   15. FATAL ERROR PANEL
   ========================================================================== */

.cq-fatal {
  max-width: 640px;
  margin: 8vh auto;
  padding: var(--sp-6);
  border: var(--border-thin) solid var(--danger-edge);
  border-radius: var(--r-xl);
  background: linear-gradient(160deg, rgba(38, 10, 18, 0.9), rgba(14, 6, 12, 0.92));
  box-shadow: var(--elev-3);
}

.cq-fatal h1 {
  font-size: var(--fs-xl);
  color: var(--danger);
  margin-bottom: var(--sp-3);
}

.cq-fatal p {
  color: var(--text-secondary);
}

.cq-fatal code {
  color: var(--gold-200);
  word-break: break-all;
}

/* ============================================================================
   17. SAVE STATUS
   A small chip that says whether the learner's progress reached the server.
   Fixed to the corner so it never moves the layout, and above the HUD so it is
   visible on every page.
   ========================================================================== */

.cq-sync {
  position: fixed;
  right: var(--gutter);
  bottom: var(--gutter);
  z-index: var(--z-toast);
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-4);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-pill);
  background: var(--glass-fill-strong);
  box-shadow: var(--elev-3), var(--glass-lip);
  backdrop-filter: blur(var(--glass-blur));
  -webkit-backdrop-filter: blur(var(--glass-blur));
  font-size: var(--fs-2xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-wide);
  color: var(--text-secondary);
  pointer-events: none;
  animation: cq-rise-sm var(--dur-mid) var(--ease-out-expo) both;
}

.cq-sync__dot {
  width: 8px;
  height: 8px;
  flex: 0 0 auto;
  border-radius: 50%;
  background: var(--text-muted);
}

/* Saving — the dot pulses, so a slow connection still looks alive. */
.cq-sync.is-saving {
  border-color: rgba(122, 221, 255, 0.3);
}

.cq-sync.is-saving .cq-sync__dot {
  background: var(--cyan-300);
  box-shadow: 0 0 8px var(--cyan-400);
  animation: cq-breathe-opacity 1.1s var(--ease-in-out-soft) infinite;
}

.cq-sync.is-saved {
  border-color: var(--success-edge);
  color: var(--success);
}

.cq-sync.is-saved .cq-sync__dot {
  background: var(--success);
  box-shadow: var(--glow-success);
}

/* Failed — red, and it does not fade away on its own. */
.cq-sync.is-error {
  border-color: var(--danger-edge);
  background: var(--danger-soft);
  color: var(--danger);
}

.cq-sync.is-error .cq-sync__dot {
  background: var(--danger);
  box-shadow: var(--glow-danger);
}

@media (max-width: 520px) {
  .cq-sync {
    left: var(--page-gutter);
    right: var(--page-gutter);
    justify-content: center;
  }
}

@media (prefers-reduced-motion: reduce) {
  .cq-sync,
  .cq-sync.is-saving .cq-sync__dot {
    animation: none;
  }
}

html[data-reduced-motion='true'] .cq-sync,
html[data-reduced-motion='true'] .cq-sync.is-saving .cq-sync__dot {
  animation: none;
}

@media print {
  .cq-sync { display: none !important; }
}

/* ============================================================================
   CSS GLYPHS — drawn, not loaded

   Each glyph is a 1.15rem box. The base element carries the outline, and the
   ::before / ::after carry the inner marks, so one span is enough for any of
   them. `currentColor` everywhere means a glyph always matches the text it
   sits beside, including in a locked or completed tile.
   ========================================================================== */

.cq-glyph {
  position: relative;
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  flex: 0 0 auto;
  color: inherit;
  vertical-align: -0.18em;
}

.cq-glyph::before,
.cq-glyph::after {
  content: '';
  position: absolute;
  display: block;
}

/* ---- play: a solid triangle ---- */
.cq-glyph--play::before {
  inset: 8% 12% 8% 20%;
  background: currentColor;
  clip-path: polygon(0 0, 100% 50%, 0 100%);
}

/* ---- map: a folded sheet with a marked point ---- */
.cq-glyph--map::before {
  inset: 10% 4%;
  border: var(--border-thin) solid currentColor;
  border-radius: 3px;
  clip-path: polygon(0 8%, 33% 0, 66% 12%, 100% 0, 100% 92%, 66% 100%, 33% 88%, 0 100%);
  opacity: 0.85;
}

.cq-glyph--map::after {
  left: 46%;
  top: 30%;
  width: 22%;
  height: 22%;
  border-radius: 50%;
  background: currentColor;
}

/* ---- test: a sheet with two written lines ---- */
.cq-glyph--test::before {
  inset: 6% 16%;
  border: var(--border-thin) solid currentColor;
  border-radius: 3px;
  opacity: 0.85;
}

.cq-glyph--test::after {
  left: 30%;
  right: 30%;
  top: 34%;
  height: 2px;
  background: currentColor;
  box-shadow: 0 5px 0 currentColor;
}

/* ---- boss: a diamond core ---- */
.cq-glyph--boss::before {
  inset: 4%;
  border: var(--border-thin) solid currentColor;
  transform: rotate(45deg);
  border-radius: 3px;
  opacity: 0.9;
}

.cq-glyph--boss::after {
  inset: 36%;
  background: currentColor;
  transform: rotate(45deg);
}

/* ---- chart: three rising bars ---- */
.cq-glyph--chart::before {
  left: 8%;
  right: 8%;
  bottom: 12%;
  height: 60%;
  background:
    linear-gradient(currentColor, currentColor) 0 100% / 22% 46% no-repeat,
    linear-gradient(currentColor, currentColor) 50% 100% / 22% 78% no-repeat,
    linear-gradient(currentColor, currentColor) 100% 100% / 22% 100% no-repeat;
}

.cq-glyph--chart::after {
  left: 6%;
  right: 6%;
  bottom: 6%;
  height: 2px;
  background: currentColor;
  opacity: 0.6;
}

/* ---- seal: a ringed medal ---- */
.cq-glyph--seal::before {
  inset: 6% 14% 26%;
  border: var(--border-thin) solid currentColor;
  border-radius: 50%;
}

.cq-glyph--seal::after {
  left: 30%;
  right: 30%;
  bottom: 2%;
  height: 34%;
  background: currentColor;
  opacity: 0.75;
  clip-path: polygon(0 0, 100% 0, 100% 100%, 50% 66%, 0 100%);
}

/* ---- story: a speech plate ---- */
.cq-glyph--story::before {
  inset: 12% 6% 26%;
  border: var(--border-thin) solid currentColor;
  border-radius: 4px;
  opacity: 0.9;
}

.cq-glyph--story::after {
  left: 26%;
  bottom: 8%;
  width: 26%;
  height: 22%;
  background: currentColor;
  clip-path: polygon(0 0, 100% 0, 18% 100%);
  opacity: 0.9;
}

/* ---- user: head and shoulders ---- */
.cq-glyph--user::before {
  left: 32%;
  top: 8%;
  width: 36%;
  height: 36%;
  border: var(--border-thin) solid currentColor;
  border-radius: 50%;
}

.cq-glyph--user::after {
  left: 14%;
  right: 14%;
  bottom: 10%;
  height: 40%;
  border: var(--border-thin) solid currentColor;
  border-bottom: 0;
  border-radius: 50% 50% 0 0;
}

/* ---- lock: shackle and body ---- */
.cq-glyph--lock::before {
  left: 26%;
  right: 26%;
  top: 6%;
  height: 42%;
  border: var(--border-thin) solid currentColor;
  border-bottom: 0;
  border-radius: 50% 50% 0 0;
  opacity: 0.85;
}

.cq-glyph--lock::after {
  left: 12%;
  right: 12%;
  bottom: 8%;
  height: 52%;
  border: var(--border-thin) solid currentColor;
  border-radius: 3px;
  background: color-mix(in srgb, currentColor 16%, transparent);
}

/* ---- hint: a lamp ---- */
.cq-glyph--hint::before {
  left: 24%;
  right: 24%;
  top: 6%;
  height: 58%;
  border: var(--border-thin) solid currentColor;
  border-radius: 50% 50% 40% 40%;
}

.cq-glyph--hint::after {
  left: 34%;
  right: 34%;
  bottom: 10%;
  height: 26%;
  background: currentColor;
  border-radius: 1px;
  opacity: 0.85;
}

/* A glyph shown at text size inside a sentence, rather than in its own tile. */
.cq-glyph--inline {
  width: 1em;
  height: 1em;
  vertical-align: -0.12em;
}


/* ==========================================================================
   CINEMATIC — เนื้อเรื่องแบบเต็มหน้าจอ
   ==========================================================================

   บทสนทนาที่อยู่ในกล่องกลางหน้าเว็บอ่านแล้วเหมือน "เนื้อหาในเว็บ" แต่ข้อความชุดเดียวกัน
   บนฉากเต็มจอที่ไม่มีอย่างอื่นมารบกวน อ่านแล้วเหมือน "ฉากในเกม" — ตัวหนังสือไม่เปลี่ยน
   เปลี่ยนแค่สิ่งที่อยู่รอบ ๆ ซึ่งเป็นตัวตัดสินว่าผู้เรียนจะมองสื่อนี้เป็นบทเรียนหรือเป็นเกม
   ในนาทีแรกที่เปิดเจอ

   กล่องข้อความวางชิดล่างแบบ Visual Novel เพราะสายตาผู้เล่นอยู่ที่ฉากก่อน แล้วค่อยลงมา
   อ่านข้อความ ไม่ใช่กลับกัน
   ========================================================================== */

.cq-cinematic {
  position: fixed;
  inset: 0;
  z-index: 900;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
  background: var(--bg-abyss, #03060f);
  animation: cq-cine-in 320ms ease-out both;
}

.cq-cinematic__scene {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* ฉากเคลื่อนช้า ๆ ทำให้ภาพนิ่งดูมีชีวิตโดยไม่ดึงสายตาออกจากข้อความ */
  animation: cq-cine-pan 24s ease-in-out infinite alternate;
}

/* ไล่เฉดจากล่างขึ้นบน ให้ตัวอักษรอ่านออกบนฉากสว่างโดยไม่ต้องใส่เงารอบตัวอักษร */
.cq-cinematic__veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to top, rgba(3, 6, 15, 0.96) 0%, rgba(3, 6, 15, 0.72) 28%,
                    rgba(3, 6, 15, 0.18) 58%, rgba(3, 6, 15, 0.34) 100%);
}

.cq-cinematic__box {
  position: relative;
  z-index: 3;
  grid-row: 2;
  width: min(1080px, 100%);
  margin: 0 auto;
  padding: 0 clamp(1rem, 4vw, 2.5rem) clamp(1.25rem, 4vh, 2.5rem);
  animation: cq-cine-rise 420ms 120ms ease-out both;
}

/* กล่องบทสนทนาเดิมถูกนำมาใช้ซ้ำทั้งดุ้น เปลี่ยนแค่เปลือกนอกให้เข้ากับฉาก */
.cq-cinematic .cq-dialogue {
  background: rgba(5, 11, 26, 0.86);
  backdrop-filter: blur(10px);
  border-color: rgba(122, 221, 255, 0.34);
  box-shadow: 0 -8px 40px rgba(3, 6, 15, 0.6);
}

.cq-cinematic .cq-dialogue__text {
  font-size: clamp(1.05rem, 2.1vw, 1.3rem);
  line-height: 1.85;
}

.cq-cinematic .cq-dialogue__portrait {
  width: clamp(72px, 12vw, 132px);
  height: clamp(72px, 12vw, 132px);
}

@keyframes cq-cine-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

@keyframes cq-cine-rise {
  from { opacity: 0; transform: translateY(24px); }
  to   { opacity: 1; transform: none; }
}

@keyframes cq-cine-pan {
  from { transform: scale(1.06) translate3d(-1.2%, 0, 0); }
  to   { transform: scale(1.06) translate3d(1.2%, -1%, 0); }
}

/* จอเตี้ย (โน้ตบุ๊ก 768px หรือมือถือแนวนอน): ลดช่องว่างไม่ให้กล่องดันฉากจนหาย */
@media (max-height: 560px) {
  .cq-cinematic__box { padding-bottom: 0.75rem; }
  .cq-cinematic .cq-dialogue__text { font-size: 1rem; line-height: 1.6; }
  .cq-cinematic .cq-dialogue__portrait { width: 64px; height: 64px; }
}

@media (prefers-reduced-motion: reduce) {
  .cq-cinematic,
  .cq-cinematic__box,
  .cq-cinematic__scene {
    animation: none;
  }
}

/* ==========================================================================
   CINEMATIC — ชั้นเพิ่มเติมสำหรับบทนำเต็มจอ
   ==========================================================================

   บทนำของเกม (js/pages/start.js) ใช้ฉากเต็มจอตัวเดียวกับบทเรียน แต่มีของเพิ่ม
   สามอย่าง: วิดีโอ cinematic ทับภาพนิ่ง, ปุ่ม "ข้ามบทนำ" ที่มุมจอ และแถบบอก
   จังหวะฉากใต้กล่องข้อความ ทั้งสามอย่างวางบนโครงเดิม ไม่แตะกล่องบทสนทนาเลย
   ========================================================================== */

/* กล่องข้อความอยู่แถวที่ 2 แถวที่ 3 เว้นไว้ให้แถบจังหวะฉาก */
.cq-cinematic--intro {
  grid-template-rows: 1fr auto auto;
}

.cq-cinematic__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ภาพนิ่งของบทนำค่อย ๆ ดันเข้า ทำให้จังหวะที่ไม่มีวิดีโอก็ยังเหมือนภาพเคลื่อนไหว */
.cq-cinematic--intro .cq-cinematic__scene {
  animation: cq-intro-push 16s var(--ease-in-out-soft) infinite alternate;
}

@keyframes cq-intro-push {
  from { transform: scale(1.02); }
  to   { transform: scale(1.11); }
}

.cq-cinematic__corner {
  position: absolute;
  z-index: 4;
  top: max(var(--sp-4), env(safe-area-inset-top));
  right: max(var(--sp-4), env(safe-area-inset-right));
  z-index: 3;
}

.cq-cinematic__footer {
  position: relative;
  grid-row: 3;
  z-index: 3;
  /* ต้องพ้นแถบดำล่าง (4.5% ของความสูงจอ) ไม่เช่นนั้นบรรทัดบอกวิธีไปต่อจะจมหายไปกับมัน */
  padding: 0 clamp(1rem, 4vw, 2.5rem) calc(4.5% + clamp(0.75rem, 2vh, 1.25rem));
  text-align: center;
}

/* แถบดำบน–ล่างแบบภาพยนตร์: สัญญาณว่า "นี่คือฉาก ไม่ใช่หน้าเว็บ" ที่อ่านออกทันที */
.cq-cinematic--intro::before,
.cq-cinematic--intro::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  height: 4.5%;
  background: var(--bg-abyss);
  z-index: 2;
  pointer-events: none;
}

.cq-cinematic--intro::before { top: 0; }
.cq-cinematic--intro::after { bottom: 0; }

@media (prefers-reduced-motion: reduce) {
  .cq-cinematic--intro .cq-cinematic__scene {
    animation: none;
  }
}

/* ==========================================================================
   FULLSCREEN TOGGLE — ปุ่มเข้า/ออกโหมดเต็มจอ
   ==========================================================================

   เกมพาเข้าเต็มจอเองตั้งแต่ผู้เรียนแตะหน้าจอครั้งแรก (js/core/fullscreen.js)
   ปุ่มนี้คือทางออกที่มองเห็นได้ จึงต้องอยู่ที่เดิมทุกหน้า — ข้างปุ่มเสียง
   เครื่องหมายบนปุ่มวาดด้วย CSS ล้วน: สี่มุมของกรอบ ซึ่งกางออกเมื่อยังไม่เต็มจอ
   และหุบเข้าเมื่อเต็มจออยู่ อ่านได้โดยไม่ต้องมีคำอธิบาย
   ========================================================================== */

.cq-fsbtn {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: var(--glass-fill-soft);
  color: var(--cyan-200);
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease-out-expo),
    background-color var(--dur-fast) var(--ease-out-expo),
    box-shadow var(--dur-fast) var(--ease-out-expo);
}

.cq-fsbtn:hover,
.cq-fsbtn:focus-visible {
  border-color: var(--glass-edge-hi);
  background: var(--cyan-soft);
  box-shadow: var(--glow-cyan-sm);
}

.cq-fsbtn__mark {
  position: relative;
  display: block;
  width: 16px;
  height: 16px;
}

/* สองมุมทแยง (บนซ้าย / ล่างขวา) เขียนด้วย ::before และ ::after ของ mark เดียว */
.cq-fsbtn__mark::before,
.cq-fsbtn__mark::after {
  content: '';
  position: absolute;
  width: 6px;
  height: 6px;
  border: 2px solid currentColor;
  transition: inset var(--dur-fast) var(--ease-out-expo);
}

.cq-fsbtn__mark::before {
  top: 0;
  left: 0;
  border-right: 0;
  border-bottom: 0;
}

.cq-fsbtn__mark::after {
  right: 0;
  bottom: 0;
  border-left: 0;
  border-top: 0;
}

/* เต็มจออยู่แล้ว — มุมหุบเข้าหากัน สื่อว่ากดแล้วจะ "ย่อ" กลับ */
.cq-fsbtn--on {
  border-color: var(--glass-edge-hi);
  color: var(--gold-200);
}

.cq-fsbtn--on .cq-fsbtn__mark::before {
  top: 3px;
  left: 3px;
}

.cq-fsbtn--on .cq-fsbtn__mark::after {
  right: 3px;
  bottom: 3px;
}

/* ==========================================================================
   Story player — วิดีโอเนื้อเรื่องรายบท (js/game/story-player.js)
   ช็อตสั้นหลายช็อตเล่นต่อกันเต็มจอ แถบความคืบหน้าแบบ "สตอรี่" ด้านบน
   คำบรรยายไทยด้านล่าง แถบดำบน–ล่างแบบภาพยนตร์เหมือนฉากบทนำ
   ========================================================================== */

.cq-story {
  position: fixed;
  inset: 0;
  z-index: 1200;
  background: #000;
  overflow: hidden;
  cursor: pointer;
  animation: cq-story-in 0.4s ease-out both;
}

.cq-story.is-leaving {
  animation: cq-story-out 0.38s ease-in both;
}

@keyframes cq-story-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes cq-story-out { from { opacity: 1; } to { opacity: 0; } }

.cq-story__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 0.35s ease;
}

.cq-story__video.is-on {
  opacity: 1;
}

/* เงาไล่บน–ล่าง ให้ตัวหนังสือกับปุ่มอ่านออกบนทุกฉาก */
.cq-story__shade {
  position: absolute;
  inset: 0;
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(0, 0, 0, 0.72), transparent 22%),
    linear-gradient(to top, rgba(0, 0, 0, 0.82), transparent 34%);
}

.cq-story__top {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  display: grid;
  gap: var(--sp-3);
  padding: max(var(--sp-4), env(safe-area-inset-top)) clamp(1rem, 3vw, 2rem) 0;
}

.cq-story__bars {
  display: flex;
  gap: 6px;
}

.cq-story__bar {
  flex: 1;
  height: 4px;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.25);
  overflow: hidden;
}

.cq-story__bar i {
  display: block;
  width: 0;
  height: 100%;
  background: var(--cyan-200, #7addff);
}

.cq-story__bar.is-done i {
  width: 100% !important;
}

.cq-story__bar:not(.is-active):not(.is-done) i {
  width: 0 !important;
}

.cq-story__actions {
  display: flex;
  justify-content: flex-end;
  gap: var(--sp-2);
}

.cq-story__bottom {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  padding: 0 clamp(1rem, 6vw, 5rem) max(clamp(1rem, 5vh, 2.5rem), env(safe-area-inset-bottom));
  text-align: center;
  pointer-events: none;
}

.cq-story__caption {
  margin: 0 auto var(--sp-2);
  max-width: 48ch;
  font-size: clamp(1.15rem, 2.6vw, 1.9rem);
  line-height: 1.5;
  color: #fff;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.9), 0 0 2px #000;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.5s ease 0.15s, transform 0.5s ease 0.15s;
}

.cq-story__caption.is-on {
  opacity: 1;
  transform: none;
}

.cq-story__hint {
  margin: 0;
  font-size: var(--fs-sm, 0.85rem);
  color: rgba(228, 248, 255, 0.6);
}

@media (prefers-reduced-motion: reduce) {
  .cq-story,
  .cq-story.is-leaving,
  .cq-story__caption {
    animation: none;
    transition: none;
  }
}

/* จอแนวตั้ง (มือถือ/แท็บเล็ตตั้ง): ครอปแบบ cover จะตัดฉากไปเกือบหมด ใช้ contain แทน */
@media (max-aspect-ratio: 1/1) {
  .cq-story__video {
    object-fit: contain;
  }
}

/* ==========================================================================
   ภาพจากชุด UI ใหม่: Core, ตราผ่าน, กุญแจ (ตัดพื้นเขียวด้วย keyed-image.js)
   ========================================================================== */

.cq-mission-item__art {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 0 6px rgba(239, 189, 87, 0.45));
}

.cq-modal__art {
  display: grid;
  place-items: center;
  padding: var(--sp-3) 0 0;
}

.cq-modal__art img {
  width: min(180px, 42vw);
  height: auto;
  filter: drop-shadow(0 0 22px rgba(122, 221, 255, 0.55));
  animation: cq-core-rise 0.9s var(--ease-out-expo, ease-out) both;
}

@keyframes cq-core-rise {
  from { opacity: 0; transform: translateY(24px) scale(0.6); }
  to { opacity: 1; transform: none; }
}

.cq-map__cores {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  margin: var(--sp-2) 0 0;
  padding: 0;
  list-style: none;
}

.cq-map__core {
  width: 44px;
  height: 44px;
}

.cq-map__core img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  filter: grayscale(1) brightness(0.45);
  opacity: 0.7;
}

.cq-map__core.is-earned img {
  filter: drop-shadow(0 0 8px rgba(122, 221, 255, 0.6));
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .cq-modal__art img {
    animation: none;
  }
}

/* ==========================================================================
   ปุ่มปิด/เปิดเพลงประกอบ (js/components/music-toggle.js)
   ขนาดและกรอบเดียวกับปุ่มเต็มจอ ปิดอยู่ = ตัวโน้ตจางมีขีดทับ
   ========================================================================== */

.cq-musicbtn--hud,
.cq-musicbtn--cover {
  position: relative;
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: var(--glass-fill-soft);
  color: var(--cyan-200);
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
}

.cq-musicbtn--hud:hover,
.cq-musicbtn--cover:hover,
.cq-musicbtn--hud:focus-visible,
.cq-musicbtn--cover:focus-visible {
  border-color: var(--glass-edge-hi);
  background: var(--cyan-soft);
  box-shadow: var(--glow-cyan-sm);
}

.cq-musicbtn.is-off {
  color: rgba(198, 217, 240, 0.5);
}

.cq-musicbtn--hud.is-off::after,
.cq-musicbtn--cover.is-off::after {
  content: '';
  position: absolute;
  width: 22px;
  height: 2px;
  background: var(--danger, #ff7d92);
  transform: rotate(-45deg);
  border-radius: 1px;
}

.cq-musicbtn--game {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.cq-musicbtn--game.is-off .cq-musicbtn__icon {
  text-decoration: line-through;
}

/* แผงตั้งค่าเสียงที่ย้ายไปลอยใต้ <body> (ดู sound-panel.js → place()) — ตำแหน่งมาจาก JS */
.cq-sound__panel.cq-sound__panel--floating {
  position: fixed;
  right: auto;
  z-index: 1300;
  max-height: calc(100vh - 80px);
  overflow-y: auto;
}

/* กล่องข้อความเปิดระหว่างเกมเต็มจอ (z 800) ต้องอยู่เหนือเวที ไม่งั้นผู้เรียนมองไม่เห็นปุ่มและค้าง */
body.cq-mg-open .cq-modal {
  z-index: 900;
}

/* ทางเข้าของครู (หน้าปก + หน้าลงทะเบียน) — ปุ่มเล็ก ไม่แย่งความสนใจจากปุ่มเริ่มเกม */
.cq-teacher-link {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  min-height: 34px;
  padding: 0 0.85em;
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: var(--glass-fill-soft);
  color: var(--cyan-200);
  font-size: var(--fs-xs, 0.85rem);
  font-weight: 600;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color var(--dur-fast) var(--ease-out-expo), background-color var(--dur-fast) var(--ease-out-expo);
}
.cq-teacher-link:hover,
.cq-teacher-link:focus-visible {
  border-color: var(--cyan-300, #7addff);
  background: rgba(63, 201, 247, 0.14);
  color: #fff;
}
.cq-profile__teacher {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  margin-top: 1rem;
  padding-top: 1rem;
  border-top: 1px solid rgba(122, 221, 255, 0.15);
}
/* ---------- กระดานคะแนน ---------- */
.cq-board {
  display: grid;
  gap: var(--sp-4);
  max-width: 900px;
  margin: 0 auto;
  padding: var(--sp-5);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-lg);
  background: var(--glass-fill);
}
.cq-board__head {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-4);
  align-items: flex-end;
  justify-content: space-between;
}
.cq-board__filter {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
}
.cq-board__filter-label {
  color: #dcecff;
  font-weight: 600;
}
.cq-select {
  min-height: 40px;
  padding: 0 var(--sp-3);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: rgba(3, 6, 15, 0.7);
  color: #fff;
  font: inherit;
}
.cq-board__me {
  margin: 0;
  padding: var(--sp-3);
  border-radius: var(--r-md);
  background: rgba(63, 201, 247, 0.12);
  color: #fff;
  text-align: center;
}
.cq-board__list {
  display: grid;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}
.cq-board__row {
  display: grid;
  grid-template-columns: 52px 1fr auto auto;
  gap: var(--sp-3);
  align-items: center;
  padding: var(--sp-3);
  border: var(--border-hair) solid var(--glass-edge);
  border-radius: var(--r-md);
  background: rgba(3, 6, 15, 0.45);
  color: #eaf4ff;
}
.cq-board__row.is-me {
  border-color: var(--gold-300, #efbd57);
  background: rgba(239, 189, 87, 0.14);
}
.cq-board__rank {
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--gold-300, #efbd57);
  text-align: center;
}
.cq-board__class,
.cq-board__missions {
  color: #c6d9f0;
  font-size: 0.9rem;
}
.cq-board__points {
  min-width: 68px;
  font-size: 1.2rem;
  font-weight: 700;
  color: #fff;
  text-align: right;
}
@media (max-width: 560px) {
  .cq-board__row {
    grid-template-columns: 42px 1fr auto;
  }
  .cq-board__missions {
    display: none;
  }
}
/* ---------- คำช่วยอ่านศัพท์อังกฤษในข้อสอบ ---------- */
.cq-question__gloss {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  align-items: flex-start;
  margin: var(--sp-3) 0;
  padding: var(--sp-3);
  border-left: 3px solid var(--cyan-300, #7addff);
  border-radius: var(--r-sm, 8px);
  background: rgba(63, 201, 247, 0.1);
}
.cq-question__gloss-tag {
  flex: none;
  padding: 2px 10px;
  border-radius: 999px;
  background: var(--cyan-300, #7addff);
  color: #06121f;
  font-size: 0.8rem;
  font-weight: 700;
}
.cq-question__gloss-list {
  display: grid;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
  color: #eaf4ff;
  font-size: 0.95rem;
}
.cq-question__gloss-list b {
  color: #fff;
}