/* ==========================================================================
   quiz-hub.css — /quiz/ only.
   ==========================================================================
   The colour system is the whole point of this file, so it is stated once here
   and never re-derived:

     bad  < 40%   red      — below a pass. Must be the loudest thing on screen.
     weak 40–59%  orange   — passing, losing marks.
     ok   60–74%  amber    — fine, not safe.
     good 75%+    green    — done; should recede.

   Red is spent deliberately and only on a real score. A grid where everything
   is coloured is a grid where nothing stands out, which is exactly the problem
   this page had — 36 identical cards with no indication of which three were
   costing the student marks. Bands come from quiz_band() in PHP so the rail,
   the card badge and the bar can never disagree.
   ========================================================================== */

.page-quiz-hub {
  --q-bad:  #ff5c5c;
  --q-weak: #ff9245;
  --q-ok:   #f0c64a;
  --q-good: #58d99a;
  --q-line: rgb(255 255 255 / .1);
  --q-card: rgb(255 255 255 / .04);
  /* NO overflow-x on the body. `overflow: clip` (or hidden) on an ancestor
     CLIPS fixed-position descendants — it broke the PDF modal on every notes
     page, which rendered inline in the flow with its close button off-screen
     instead of as an overlay. The clip belongs on the elements that actually
     overflow (the 3D art stages), not on the page. */
}
.theme-light .page-quiz-hub {
  --q-line: rgb(15 18 26 / .13);
  --q-card: rgb(15 18 26 / .03);
  --q-bad:  #d92d2d;
  --q-weak: #d1691a;
}

/* ── HERO ART ───────────────────────────────────────────────────────────── */
.qArt { position: relative; min-height: clamp(17rem, 30vw, 24rem); perspective: 1400px; display: grid; place-items: center; }
.qArt__stage {
  position: relative; width: 100%; height: 100%; display: grid; place-items: center;
  transform-style: preserve-3d;
  transform: rotateX(var(--ax, 0deg)) rotateY(var(--ay, 0deg));
  transition: transform .5s cubic-bezier(.22,1,.36,1);
}
.qArt__glow {
  position: absolute; width: 70%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgb(240 198 74 / .18), transparent 62%);
  filter: blur(24px);
}
.qArt__dial { position: relative; width: clamp(10rem, 20vw, 14rem); transform: translateZ(40px); }
.qArt__dial svg { width: 100%; display: block; transform: rotate(-90deg); }
.qArt__ring, .qArt__val { fill: none; stroke-width: 8; stroke-linecap: round; }
.qArt__ring { stroke: rgb(255 255 255 / .1); }
.theme-light .qArt__ring { stroke: rgb(15 18 26 / .1); }
.qArt__val {
  stroke: var(--q-good);
  stroke-dasharray: 326.7;                     /* 2πr, r = 52 */
  stroke-dashoffset: calc(326.7 - (326.7 * var(--pct, 0) / 100));
  filter: drop-shadow(0 0 10px currentColor);
  animation: qDraw 1.4s cubic-bezier(.22,1,.36,1) both;
}
@keyframes qDraw { from { stroke-dashoffset: 326.7; } }
.qArt__dial--bad  .qArt__val { stroke: var(--q-bad); }
.qArt__dial--weak .qArt__val { stroke: var(--q-weak); }
.qArt__dial--ok   .qArt__val { stroke: var(--q-ok); }
.qArt__read { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; gap: 2px; }
.qArt__read strong { font-family: var(--font-display); font-size: clamp(1.8rem, 4vw, 2.6rem); line-height: 1; color: var(--text-hi); font-variant-numeric: tabular-nums; }
.qArt__read span { font-family: var(--font-mono); font-size: .64rem; color: var(--text-lo); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }

.qArt__chip {
  position: absolute; display: grid; gap: 1px; justify-items: center;
  padding: var(--s-3) var(--s-4); border-radius: var(--radius);
  border: 1px solid var(--q-line); background: var(--q-card);
  backdrop-filter: blur(10px); box-shadow: 0 16px 40px -18px rgb(0 0 0 / .8);
  animation: qFloat 6s ease-in-out infinite alternate;
}
.qArt__chip b { font-family: var(--font-display); font-size: 1.3rem; color: var(--y-yellow); line-height: 1; font-variant-numeric: tabular-nums; }
.qArt__chip span { font-size: .58rem; color: var(--text-mid); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
.qArt__chip--a { top: 8%;  left: 2%;  transform: translateZ(80px); }
.qArt__chip--b { bottom: 10%; right: 2%; transform: translateZ(60px); animation-delay: -3s; }
@keyframes qFloat { to { translate: 0 -10px; } }

.qArt__orbit { position: absolute; border-radius: 50%; border: 1px solid rgb(240 198 74 / .18); }
.qArt__orbit--1 { inset: 14%; transform: rotateX(74deg); animation: qSpin 20s linear infinite; }
.qArt__orbit--2 { inset: 24%; transform: rotateY(70deg); animation: qSpin 28s linear infinite reverse; }
@keyframes qSpin { to { rotate: 360deg; } }

/* ── NEEDS WORK RAIL ────────────────────────────────────────────────────── */
.qWeak { padding-block: clamp(var(--s-8), 4vw, var(--s-12)); }
.qWeak__head { margin-bottom: var(--s-6); }
.qWeak__flag {
  display: inline-block; padding: .2rem .6rem; border-radius: 999px;
  background: rgb(255 92 92 / .16); border: 1px solid rgb(255 92 92 / .45);
  color: var(--q-bad); font-family: var(--font-mono); font-size: var(--fs-xs);
  letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
}
.qWeak__head h2 { margin: var(--s-3) 0 var(--s-1); font-size: clamp(1.5rem, 1.1rem + 1.6vw, 2.2rem); }
.qWeak__head p { margin: 0; color: var(--text-mid); }

.qWeak__row {
  display: grid; gap: var(--s-4);
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 15rem), 1fr));
}
.qWeak__card {
  position: relative; display: grid; gap: var(--s-2);
  padding: var(--s-5); border-radius: var(--radius-lg);
  border: 1px solid rgb(255 92 92 / .3);
  background: linear-gradient(160deg, rgb(255 92 92 / .1), var(--q-card));
  color: inherit; text-decoration: none;
  transform: rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  transition: transform .35s cubic-bezier(.22,1,.36,1), border-color .3s, box-shadow .35s;
}
.qWeak__card:hover {
  border-color: rgb(255 92 92 / .7);
  box-shadow: 0 0 0 1px rgb(255 92 92 / .35), 0 20px 50px -20px rgb(255 92 92 / .45);
}
.qWeak__card.is-weak { border-color: rgb(255 146 69 / .32); background: linear-gradient(160deg, rgb(255 146 69 / .1), var(--q-card)); }
.qWeak__card.is-ok,
.qWeak__card.is-good { border-color: var(--q-line); background: var(--q-card); }
.qWeak__pct { font-family: var(--font-display); font-size: 2.2rem; line-height: 1; color: var(--q-bad); font-variant-numeric: tabular-nums; }
.qWeak__pct i { font-size: .9rem; font-style: normal; opacity: .7; }
.qWeak__card.is-weak .qWeak__pct { color: var(--q-weak); }
.qWeak__card.is-ok   .qWeak__pct { color: var(--q-ok); }
.qWeak__card.is-good .qWeak__pct { color: var(--q-good); }
.qWeak__name { color: var(--text-hi); font-weight: 600; font-size: var(--fs-sm); line-height: var(--lh-snug); }
.qWeak__decay { font-size: .68rem; color: var(--q-weak); }
.qWeak__bar { display: block; height: 4px; border-radius: 999px; background: rgb(255 255 255 / .1); overflow: hidden; }
.qWeak__bar i { display: block; height: 100%; width: var(--w, 0%); background: currentColor; color: var(--q-bad); }
.qWeak__card.is-weak .qWeak__bar i { color: var(--q-weak); }
.qWeak__go { font-size: var(--fs-sm); color: var(--text-mid); }

/* ── BANK CARDS ─────────────────────────────────────────────────────────── */
.qCard {
  position: relative;
  /* NO overflow:hidden. It was clipping the top of the eyebrow's glyphs — the
     "2" of "20 QUESTIONS" rendered as a "∠". The sheen is the only thing that
     needed clipping, so it clips itself via border-radius: inherit instead. */
  transform: rotateX(var(--tx, 0deg)) rotateY(var(--ty, 0deg));
  transition: transform .35s cubic-bezier(.22,1,.36,1), border-color .3s, box-shadow .35s;
}
.qCard__sheen {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  border-radius: inherit; overflow: hidden;
  background: radial-gradient(320px circle at var(--mx,50%) var(--my,50%), rgb(255 255 255 / .1), transparent 62%);
  transition: opacity .3s;
}
.qCard:hover .qCard__sheen { opacity: 1; }

.qCard__score {
  position: absolute; top: var(--s-4); right: var(--s-4);
  display: grid; justify-items: end; gap: 0;
  padding: .2rem .55rem; border-radius: 999px;
  border: 1px solid currentColor; color: var(--q-good);
  font-variant-numeric: tabular-nums;
}
.qCard__score b { font-size: .8rem; }
.qCard__score i { font-style: normal; font-size: .56rem; opacity: .75; }
.qCard.is-bad  .qCard__score { color: var(--q-bad); background: rgb(255 92 92 / .12); }
.qCard.is-weak .qCard__score { color: var(--q-weak); background: rgb(255 146 69 / .12); }
.qCard.is-ok   .qCard__score { color: var(--q-ok); background: rgb(240 198 74 / .12); }
.qCard.is-good .qCard__score { background: rgb(88 217 154 / .12); }

/* A red left edge, so a weak bank is identifiable from the grid's rhythm
   alone — before any number has been read. */
.qCard.is-bad  { border-left: 3px solid var(--q-bad); }
.qCard.is-weak { border-left: 3px solid var(--q-weak); }

.qCard__bar { display: block; height: 4px; border-radius: 999px; background: rgb(255 255 255 / .09); overflow: hidden; margin: var(--s-3) 0 0; }
.qCard__bar i { display: block; height: 100%; width: var(--w, 0%); background: var(--q-good); }
.qCard.is-bad  .qCard__bar i { background: var(--q-bad); }
.qCard.is-weak .qCard__bar i { background: var(--q-weak); }
.qCard.is-ok   .qCard__bar i { background: var(--q-ok); }
.qCard__decay { display: block; margin-top: var(--s-2); font-size: .66rem; color: var(--q-weak); }

/* ── RESPONSIVE ─────────────────────────────────────────────────────────── */
@media (max-width: 64rem) { .qArt { min-height: 14rem; } }
@media (max-width: 40rem) {
  .qArt { min-height: 11rem; order: -1; }
  .qArt__chip { padding: var(--s-2) var(--s-3); }
  .qArt__chip b { font-size: 1rem; }
  .qArt__chip--a { left: 0; } .qArt__chip--b { right: 0; }
  .qWeak__row { grid-template-columns: 1fr; }
  .qCard__score { top: var(--s-3); right: var(--s-3); }
}
@media (prefers-reduced-motion: reduce) {
  .qArt__chip, .qArt__orbit, .qArt__val { animation: none; }
  .qArt__stage, .qCard, .qWeak__card { transition: none; }
}


/* ── WHOLE CARD CLICKABLE ───────────────────────────────────────────────────
   The card looked clickable and was not — only the small "Start →" link was a
   target. Rather than wrap the <article> in an <a> (which would swallow the
   score badge and bar into the link text announced to screen readers), the
   existing link is stretched over the card with a pseudo-element. One link,
   one accessible name, the whole card as the hit area. */
.qCard .card__link { position: static; }
.qCard .card__link::after {
  content: ''; position: absolute; inset: 0; z-index: 2; border-radius: inherit;
}
.qCard { cursor: pointer; }
/* Keep the score badge and any real control above the stretched link. */
.qCard__score { z-index: 3; }
.qCard:focus-within { outline: 2px solid var(--y-yellow); outline-offset: 3px; }

/* Cards in a row must line up: the grid rows are as tall as the tallest card
   and a short description left the "Start" link floating mid-card. */
.qCard { display: flex; flex-direction: column; }
.qCard .card__link { margin-top: auto; }
.qCard__bar, .qCard__decay { flex: none; }
