/* Minimal raw CSS — everything else is Tailwind (see base.html).
   Only the things utilities can't express cleanly live here. */

/* Self-hosted UI fonts. Previously loaded from the Google Fonts CDN (fonts.googleapis.com), which
   (a) blocked render on that request, (b) broke typography on CDN-filtering campus networks — the
   same failure we already fixed for Tailwind — and (c) sent every student's IP to Google beneath a
   page that links a privacy notice. Same faces, now served from our own origin (static/fonts/). */
@font-face{font-family:'Inter';font-style:normal;font-weight:400;font-display:swap;src:url('../fonts/inter-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:500;font-display:swap;src:url('../fonts/inter-latin-500-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:600;font-display:swap;src:url('../fonts/inter-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'Inter';font-style:normal;font-weight:700;font-display:swap;src:url('../fonts/inter-latin-700-normal.woff2') format('woff2')}
@font-face{font-family:'Plus Jakarta Sans';font-style:normal;font-weight:600;font-display:swap;src:url('../fonts/plus-jakarta-sans-latin-600-normal.woff2') format('woff2')}
@font-face{font-family:'Plus Jakarta Sans';font-style:normal;font-weight:700;font-display:swap;src:url('../fonts/plus-jakarta-sans-latin-700-normal.woff2') format('woff2')}
@font-face{font-family:'Plus Jakarta Sans';font-style:normal;font-weight:800;font-display:swap;src:url('../fonts/plus-jakarta-sans-latin-800-normal.woff2') format('woff2')}
/* Pixel/retro display faces for HUD accents (labels, XP, badges). Used sparingly; body stays Inter. */
@font-face{font-family:'Press Start 2P';font-style:normal;font-weight:400;font-display:swap;src:url('../fonts/press-start-2p-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Silkscreen';font-style:normal;font-weight:400;font-display:swap;src:url('../fonts/silkscreen-latin-400-normal.woff2') format('woff2')}
@font-face{font-family:'Silkscreen';font-style:normal;font-weight:700;font-display:swap;src:url('../fonts/silkscreen-latin-700-normal.woff2') format('woff2')}

/* Visible keyboard focus for every interactive control that doesn't already draw its own ring.
   :where() holds specificity at 0 so an element's own focus-visible styles still win, and form
   fields (which already ring on focus) are intentionally excluded to avoid a doubled indicator. */
:where(a[href], button, [role="button"], summary, [tabindex]:not([tabindex="-1"])):focus-visible{
  outline: 2px solid #14b8a6;            /* brand-500 */
  outline-offset: 2px;
}

/* We render our own controls; hide the browser's native video chrome. */
video::-webkit-media-controls,
video::-webkit-media-controls-enclosure { display: none !important; }
video::-moz-media-controls { display: none !important; }

/* Refined, unobtrusive scrollbars. */
* { scrollbar-width: thin; scrollbar-color: #cbd5e1 transparent; }
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 999px; border: 3px solid transparent; background-clip: content-box; }
*::-webkit-scrollbar-thumb:hover { background: #94a3b8; background-clip: content-box; }

/* Grab cursors for the drag minigame. */
.cursor-grab { cursor: grab; }
.cursor-grabbing, .dragging { cursor: grabbing; }
.dragging { opacity: .55; transform: rotate(-2deg) scale(1.03); }

/* Tiny celebratory confetti (used sparingly on a correct answer). */
.confetti-piece {
  position: absolute; top: 0; width: 9px; height: 14px; border-radius: 2px;
  will-change: transform, opacity; animation: confetti-fall var(--dur,1.4s) cubic-bezier(.3,.7,.4,1) forwards;
}
@keyframes confetti-fall {
  0%   { transform: translate3d(0,0,0) rotate(0); opacity: 1; }
  100% { transform: translate3d(var(--dx,0), 320px, 0) rotate(var(--rot,540deg)); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}

/* Fullscreen player — fill the screen, letterbox the video, keep controls + checkpoints usable. */
#playerShell:fullscreen, #playerShell:-webkit-full-screen { width: 100vw; height: 100vh; border-radius: 0; display: flex; flex-direction: column; }
#playerShell:fullscreen #stage, #playerShell:-webkit-full-screen #stage { flex: 1 1 auto; aspect-ratio: auto; height: auto; }
#playerShell:fullscreen video, #playerShell:-webkit-full-screen video { object-fit: contain; }

/* Friendly focus-return toast. */
.toast-card { animation: toast-in .3s ease both; }
@keyframes toast-in { from { opacity: 0; transform: translateY(-10px); } to { opacity: 1; transform: translateY(0); } }

/* ============================================================================
   Student design system (.ev-*) — flat "modern retro / pixel-HUD" aesthetic.
   No gradients: flat colour blocks, crisp 2px outlines, hard offset shadows,
   pixel fonts on HUD labels, and segmented XP-style bars. Courses read as
   worlds, modules as levels, progress as XP — deliberately game-y (the retro
   brief earns the hard shadows the craft floor otherwise avoids). Paired with
   the macros in templates/_components.html; per-course colour arrives as the
   --acc CSS variable set in markup. Raw CSS = no Tailwind rebuild.
   ============================================================================ */

.pix{font-family:'Press Start 2P',monospace;text-transform:uppercase;line-height:1.6}
/* Pixel display for large brand text (headings, wordmark) — Silkscreen reads as pixel but stays
   legible at size; Press Start 2P is reserved for the tiny HUD labels. */
.ev-display,.ev-hello,.ev-wordmark{font-family:'Silkscreen','Press Start 2P',sans-serif;font-weight:700}
.ev-wordmark{letter-spacing:.02em;font-size:1.02rem}
/* Header stays in the regular UI font (Inter). Pixel is an ACCENT only — the wordmark (.ev-wordmark)
   and tiny HUD labels — never functional nav links or names. */
.ev-logo{background:#0f766e;border:2px solid #0b1623;border-radius:6px}
.ev-avatar{background:#0f766e;border:2px solid #0b1623;border-radius:6px;font-family:'Press Start 2P',monospace;font-size:.5rem}
/* Page backdrop: a faint pixel dot-grid (replaces the gradient blobs). */
.ev-bg-dots{background-image:radial-gradient(#cbd5e1 1px, transparent 1.2px);background-size:22px 22px;
  background-position:-1px -1px;opacity:.6}

/* ============================================================================
   Retro overrides for the SHARED Tailwind component classes. style.css loads
   after tailwind.css, so these win — EVERY page that uses .card/.chip/.btn/.field
   inherits the flat pixel look with no per-page markup edits (DRY rollout).
   Bespoke surfaces (home hero, dashboard tiles) use .ev-* and are untouched.
   ============================================================================ */
.card{border:2px solid #0b1623;border-radius:10px;box-shadow:4px 4px 0 rgba(11,22,35,.09)}
.chip{border-radius:5px}
.btn-primary{border:2px solid #0b1623;border-radius:7px;box-shadow:3px 3px 0 #042f2e}
.btn-primary:hover{transform:translate(-1px,-1px);box-shadow:4px 4px 0 #042f2e}
.btn-primary:active{transform:translate(1px,1px);box-shadow:2px 2px 0 #042f2e}
.btn-ghost{color:#0b1623;background:#fff;border:2px solid #0b1623;border-radius:7px;box-shadow:3px 3px 0 rgba(11,22,35,.13)}
.btn-ghost:hover{background:#fff;transform:translate(-1px,-1px);box-shadow:4px 4px 0 rgba(15,118,110,.3)}
.field{border:2px solid #0b1623;border-radius:7px;background:#fff}
.field:focus{outline:none;border-color:#14b8a6;box-shadow:0 0 0 3px rgba(20,184,166,.2)}
/* ONE content font. `.font-display` was Plus Jakarta — a third typeface that clashed with Inter on
   the same page. Map it to Inter so every heading matches body + .ev-* content titles (pixel stays
   accent-only). The auth WIP sets its font on its own .lgn-* classes, so it is untouched. */
.font-display{font-family:'Inter',ui-sans-serif,system-ui,sans-serif !important;letter-spacing:-.012em}
/* Flat course-header panel (replaces the teal gradient banner): ink block, per-course --acc hard
   shadow, faint CRT grid. Same language as the home hero. */
.ev-coursehero{position:relative;background:#0b1623;border:2px solid #0b1623;border-radius:12px;
  box-shadow:6px 6px 0 var(--acc,#0f766e);overflow:hidden}
.ev-coursehero::before{content:"";position:absolute;inset:0;opacity:.5;pointer-events:none;
  background-image:linear-gradient(rgba(94,234,212,.05) 1px,transparent 1px),
                  linear-gradient(90deg,rgba(94,234,212,.05) 1px,transparent 1px);background-size:22px 22px}
/* Flat course code badge (replaces the gradient swatch): --acc fill, ink outline, squared. */
.ev-codebadge{display:grid;place-items:center;background:var(--acc,#0f766e);color:#fff;
  border:2px solid #0b1623;border-radius:7px;font-weight:800;flex-shrink:0;line-height:1}
/* Header chrome (retro): tiny pixel HUD tag (beta), flat bordered nav links, flat status badge. */
.ev-tag{display:inline-flex;align-items:center;font-family:'Press Start 2P',monospace;font-size:.44rem;
  letter-spacing:.03em;text-transform:uppercase;color:#0f766e;background:#ccfbf1;border:1.5px solid #0b1623;
  border-radius:5px;padding:.38rem .44rem;line-height:1}
.ev-navlink{display:inline-flex;align-items:center;padding:.42rem .72rem;border-radius:7px;font-weight:600;
  color:#475569;border:2px solid transparent;transition:background .12s,color .12s}
.ev-navlink:hover{background:#f1f5f9;color:#0b1623}
.ev-navlink.is-active{color:#0f766e;background:#f0fdfa;border-color:#0b1623;box-shadow:2px 2px 0 rgba(11,22,35,.12)}
.ev-badge{display:inline-flex;align-items:center;padding:.28rem .55rem;border-radius:6px;font-size:.72rem;
  font-weight:700;color:#78350f;background:#fcd34d;border:2px solid #0b1623;line-height:1.1}

/* -- Hero: a flat "player HUD" panel with a CRT pixel grid. ------------------- */
.ev-hero{position:relative;overflow:hidden;border-radius:10px;color:#fff;padding:1.45rem 1.9rem;
  background:#0b1623;border:2px solid #0b1623;
  box-shadow:7px 7px 0 rgba(15,118,110,.9);animation:ev-rise .45s cubic-bezier(.2,.8,.2,1) both}
@keyframes ev-rise{from{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}
.ev-hero::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.6;
  background-image:linear-gradient(rgba(94,234,212,.05) 1px,transparent 1px),
                  linear-gradient(90deg,rgba(94,234,212,.05) 1px,transparent 1px);background-size:22px 22px}
.ev-hero .ev-hero__contours{position:absolute;z-index:0;right:-3%;bottom:-34%;width:min(46%,440px);aspect-ratio:1;
  color:#134e4a;opacity:.5;pointer-events:none}
.ev-hero .ev-hero__glow{display:none}
.ev-hero>*{position:relative;z-index:1}
.ev-hero__eyebrow{margin:0 0 .55rem;font-family:'Press Start 2P',monospace;font-size:.56rem;letter-spacing:.04em;color:#5eead4}
.ev-hello{margin:0;color:#fff;letter-spacing:.01em;font-size:clamp(1.35rem,2.4vw,1.95rem);line-height:1.3}
.ev-hello em{font-style:normal;color:#5eead4}
.ev-hero__sub{margin:.55rem 0 0;color:#94a3b8;font-size:.98rem}

/* -- Stat rail: HUD stats with pixel labels + segmented XP bars. -------------- */
.ev-statrail{margin-top:1rem;padding-top:.85rem;border-top:2px dashed rgba(94,234,212,.2);
  display:flex;flex-wrap:wrap;gap:1.3rem 2.6rem}
.ev-stat__value{font-family:Inter,sans-serif;font-weight:800;font-size:1.7rem;line-height:1;
  color:#fff;display:flex;align-items:baseline;gap:.28rem}
.ev-stat__value small{font-size:.85rem;font-weight:700;color:#5eead4}
.ev-stat__label{margin-top:.5rem;font-family:'Press Start 2P',monospace;font-size:.5rem;letter-spacing:.03em;
  text-transform:uppercase;color:#5eead4}
.ev-xp,.ev-stat__bar{position:relative;margin-top:.6rem;width:9rem;max-width:100%;height:12px;background:#0f2a2a;
  border:2px solid #042f2e;border-radius:3px;overflow:hidden}
.ev-xp>i,.ev-stat__bar>i{display:block;height:100%;background:#14b8a6}
.ev-xp::after,.ev-stat__bar::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,transparent 0 9px,rgba(4,47,46,.85) 9px 11px)}

/* -- Section label: pixel header with a stepped hairline. --------------------- */
.ev-section{display:flex;align-items:center;gap:.75rem;margin:1.3rem 0 .8rem;
  font-family:'Press Start 2P',monospace;font-size:.62rem;letter-spacing:.02em;text-transform:uppercase;color:#0f766e}
.ev-section::after{content:"";flex:1;height:4px;border-radius:1px;
  background:repeating-linear-gradient(90deg,#cbd5e1 0 6px,transparent 6px 10px)}
.ev-section a{margin-left:auto;font-family:Inter,sans-serif;font-size:.76rem;font-weight:700;letter-spacing:0;
  text-transform:none;color:#0f766e;text-decoration:none;white-space:nowrap}
.ev-section a:hover{text-decoration:underline}

/* -- Resume / continue: the "press start" row. ------------------------------- */
.ev-resume{display:flex;align-items:center;gap:1.05rem;padding:1rem 1.1rem;text-decoration:none;background:#fff;
  border:2px solid #0b1623;border-radius:8px;box-shadow:5px 5px 0 rgba(11,22,35,.12);
  transition:transform .12s,box-shadow .12s}
.ev-resume:hover{transform:translate(-2px,-2px);box-shadow:8px 8px 0 rgba(15,118,110,.32)}
.ev-resume__icon{flex:none;width:52px;height:52px;border-radius:6px;display:grid;place-items:center;color:#fff;
  background:var(--acc,#0f766e);border:2px solid #0b1623}
.ev-resume__eyebrow{font-family:'Press Start 2P',monospace;font-size:.52rem;letter-spacing:.02em;text-transform:uppercase;
  color:var(--acc,#0f766e)}
.ev-resume__title{margin:.35rem 0 0;font-family:Inter,sans-serif;font-weight:700;
  font-size:1.12rem;color:#0b1623;line-height:1.15}
.ev-resume__meta{margin:.16rem 0 0;font-size:.82rem;color:#64748b}
.ev-resume__go{flex:none;display:inline-flex;align-items:center;gap:.45rem;padding:.6rem 1rem;
  font-family:'Press Start 2P',monospace;font-size:.6rem;color:#fff;background:#0f766e;border:2px solid #0b1623;
  border-radius:6px;box-shadow:3px 3px 0 #042f2e;transition:transform .1s,box-shadow .1s;white-space:nowrap}
.ev-resume:hover .ev-resume__go{transform:translate(-1px,-1px);box-shadow:4px 4px 0 #042f2e}

/* Pixel eyebrow accent for page headers (kicker above an Inter title). */
.ev-eyebrow{font-family:'Press Start 2P',monospace;font-size:.56rem;letter-spacing:.04em;
  text-transform:uppercase;color:#0f766e}
/* Retro button: flat, outlined, hard shadow, presses on click. Body text stays Inter. */
.ev-btn{display:inline-flex;align-items:center;gap:.45rem;padding:.5rem .85rem;font-weight:700;font-size:.83rem;
  color:#0b1623;background:#fff;border:2px solid #0b1623;border-radius:7px;box-shadow:3px 3px 0 rgba(11,22,35,.13);
  text-decoration:none;transition:transform .1s,box-shadow .1s;white-space:nowrap}
.ev-btn:hover{transform:translate(-1px,-1px);box-shadow:4px 4px 0 rgba(15,118,110,.32)}
.ev-btn:active{transform:translate(1px,1px);box-shadow:2px 2px 0 rgba(11,22,35,.13)}
.ev-btn svg{width:1rem;height:1rem}
.ev-btn--primary{color:#fff;background:#0f766e;border-color:#0b1623;box-shadow:3px 3px 0 #042f2e}
.ev-btn--primary:hover{box-shadow:4px 4px 0 #042f2e;filter:brightness(1.06)}

/* Generic retro panel (flat, outlined, soft hard-shadow). */
.ev-panel{background:#fff;border:2px solid #0b1623;border-radius:8px;box-shadow:4px 4px 0 rgba(11,22,35,.09)}
/* Selector/filter pills (dashboard). Active fills with --acc (defaults to ink). */
.ev-pill{display:inline-flex;align-items:center;padding:.32rem .65rem;font-size:.8rem;font-weight:600;color:#334155;
  background:#fff;border:2px solid #0b1623;border-radius:6px;text-decoration:none;box-shadow:2px 2px 0 rgba(11,22,35,.1);
  transition:transform .1s,box-shadow .1s;white-space:nowrap}
.ev-pill:hover{transform:translate(-1px,-1px);box-shadow:3px 3px 0 rgba(15,118,110,.25)}
.ev-pill.is-on{color:#fff;background:var(--acc,#0b1623);border-color:#0b1623;box-shadow:2px 2px 0 #042f2e}
.ev-pill--muted{opacity:.55}
.ev-rowlabel{font-family:'Press Start 2P',monospace;font-size:.46rem;letter-spacing:.02em;text-transform:uppercase;
  color:#64748b;width:4.4rem;flex:none}
/* HUD stat tile (dashboard). */
.ev-tile{background:#fff;border:2px solid #0b1623;border-radius:8px;padding:.85rem 1rem;box-shadow:4px 4px 0 rgba(11,22,35,.1)}
.ev-tile__label{font-family:'Press Start 2P',monospace;font-size:.5rem;letter-spacing:.03em;text-transform:uppercase;color:#0f766e}
.ev-tile__value{margin-top:.55rem;font-family:Inter,sans-serif;font-weight:800;font-size:1.8rem;line-height:1;color:#0b1623}
.ev-tile__value small{font-size:.85rem;color:#94a3b8;font-weight:700}

/* -- Course card: a "level select" tile. ------------------------------------- */
.ev-course{position:relative;display:flex;flex-direction:column;text-decoration:none;background:#fff;
  border:2px solid #0b1623;border-radius:8px;overflow:hidden;box-shadow:5px 5px 0 rgba(11,22,35,.1);
  transition:transform .12s,box-shadow .12s}
.ev-course:hover{transform:translate(-3px,-3px);box-shadow:9px 9px 0 var(--acc,#0f766e)}
.ev-course__accent{height:8px;width:100%;background:var(--acc,#0f766e);border-bottom:2px solid #0b1623}
.ev-course__body{display:flex;flex-direction:column;flex:1;padding:1.05rem 1.15rem 1.2rem}
.ev-course__head{display:flex;align-items:center;gap:.7rem}
.ev-course__num{flex:none;width:44px;height:44px;border-radius:6px;display:grid;place-items:center;color:#fff;
  background:var(--acc,#0f766e);border:2px solid #0b1623;font-family:'Press Start 2P',monospace;font-size:.7rem}
.ev-course__code{font-family:'Press Start 2P',monospace;font-size:.56rem;letter-spacing:.02em;color:var(--acc,#0f766e)}
.ev-course__term{font-size:.74rem;color:#94a3b8;margin-top:.25rem}
.ev-course__title{margin:.7rem 0 0;font-family:Inter,sans-serif;font-weight:700;
  font-size:1.05rem;line-height:1.25;color:#0b1623}
.ev-course__blurb{margin:.4rem 0 0;font-size:.85rem;line-height:1.5;color:#64748b;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;min-height:2.55rem}
.ev-course__stats{margin-top:.85rem;display:flex;align-items:center;justify-content:space-between;gap:.5rem;
  font-size:.82rem;color:#334155;font-weight:600}
.ev-course__track{position:relative;margin-top:.5rem;height:11px;background:#eef2f6;border:2px solid #0b1623;
  border-radius:3px;overflow:hidden}
.ev-course__track>i{display:block;height:100%;background:var(--acc,#0f766e)}
.ev-course__track::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:repeating-linear-gradient(90deg,transparent 0 8px,rgba(11,22,35,.16) 8px 10px)}
.ev-course__go{margin-top:.9rem;display:inline-flex;align-items:center;gap:.4rem;color:var(--acc,#0f766e);
  font-family:'Press Start 2P',monospace;font-size:.54rem}
.ev-course:hover .ev-course__go{gap:.65rem}

/* -- Due list: quest-log entries. -------------------------------------------- */
.ev-due{display:flex;gap:.8rem;align-items:flex-start;text-decoration:none;background:#fff;border:2px solid #0b1623;
  border-radius:8px;padding:.85rem 1rem;box-shadow:4px 4px 0 rgba(11,22,35,.09);transition:transform .12s,box-shadow .12s}
.ev-due:hover{transform:translate(-2px,-2px);box-shadow:6px 6px 0 rgba(15,118,110,.26)}
.ev-due--soon:hover{box-shadow:6px 6px 0 rgba(245,158,11,.4)}
.ev-due--closed:hover{box-shadow:6px 6px 0 rgba(225,29,72,.34)}
.ev-due__dot{flex:none;width:12px;height:12px;border:2px solid #0b1623;margin-top:.3rem}
.ev-due__code{font-family:'Press Start 2P',monospace;font-size:.5rem;letter-spacing:.02em;text-transform:uppercase;
  color:var(--acc,#0f766e)}
.ev-due__title{margin:.4rem 0 0;font-weight:700;color:#0b1623;line-height:1.2;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.ev-due__when{margin:.22rem 0 0;font-size:.8rem;color:#64748b}
.ev-due__when.is-soon{color:#b45309;font-weight:700}
.ev-due__when.is-closed{color:#be123c;font-weight:700}

/* -- Empty state. ------------------------------------------------------------ */
.ev-empty{border:2px dashed #94a3b8;border-radius:8px;background:rgba(248,250,252,.7);
  padding:1.6rem;text-align:center;color:#64748b;font-size:.92rem}

@media (max-width:640px){
  .ev-hero{padding:1.5rem 1.3rem;box-shadow:5px 5px 0 rgba(15,118,110,.9)}
  .ev-resume{flex-wrap:wrap}
  .ev-resume__go{margin-left:auto}
}

/* ── Deck list (/slides) ──────────────────────────────────────────────────────
   Semantic classes, not utility soup, for two reasons. The row has to form real
   COLUMNS — the old one was a flex line whose eight children landed at a different
   x on every row, so nothing could be scanned down the list — and a grid is the
   only honest way to say that. And a rule named .deck-row is one selector for the
   retro system to re-skin later, where a row assembled from fourteen utilities
   would have to be rewritten. This file loads after tailwind.css, so it wins with
   no rebuild and no ?v= bump. */

.deck-row{display:grid;align-items:center;gap:.75rem;padding:.5rem .9rem;
  grid-template-columns:18px 34px minmax(0,1fr) auto auto;
  border-bottom:1px solid #f1f5f9}
.deck-row:last-child{border-bottom:0}
.deck-row:hover{background:#f8fafc}
/* Sixty-six saturated buttons in a column is a wall, and a wall is not a hierarchy: the eye
   cannot find the row it wants because every row shouts the same. The action stays present and
   keyboard-reachable on every row, but it only takes the accent on the row you are actually on. */
.deck-row .btn-primary{background:transparent;color:#0f766e;border-color:#94a3b8;box-shadow:none;
  transform:none;transition:background .12s ease,color .12s ease,border-color .12s ease}
.deck-row:hover .btn-primary,.deck-row:focus-within .btn-primary,
.deck-row .btn-primary:focus-visible{background:#0f766e;color:#fff;border-color:#0b1623;box-shadow:2px 2px 0 #042f2e}
/* The menu's Apply and the slot header's promote button are decisions, not row furniture —
   they keep the full solid treatment. */
.deck-menu__panel .btn-primary,.deck-slot__hdr .btn-primary{background:#0f766e;color:#fff}
.deck-row.is-nested{padding-left:1.9rem}

/* The rail is the fixed column the eye rides down the list. Two versions of a week
   now visibly share a number instead of being told apart by a chip 900px away. */
.deck-row__wk{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.72rem;
  color:#64748b;font-variant-numeric:tabular-nums;white-space:nowrap}
.deck-row__wk.is-derived{border-bottom:1px dotted #cbd5e1;cursor:help}

.deck-row__id{min-width:0}
.deck-row__id a{display:block;font-weight:600;color:#0f172a;text-decoration:none;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.deck-row__id a:hover{color:#0f766e}
/* The deck id was visible nowhere on the page — not in any text — so sixteen decks in
   same-title clusters were indistinguishable, and Ctrl-F for "v3" matched nothing. */
.deck-row__slug{font-size:.68rem;color:#5c6673;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;
  display:block;margin-top:.05rem}
.deck-row__file{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;color:#546070}
.deck-row__when{font-variant-numeric:tabular-nums;color:#5c6673}

.deck-row__num{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.7rem;
  color:#64748b;font-variant-numeric:tabular-nums;white-space:nowrap;text-align:right}

.deck-tag{display:inline-flex;align-items:center;gap:.25rem;white-space:nowrap;
  font-size:.66rem;font-weight:600;padding:.1rem .4rem;border-radius:999px;
  background:#f1f5f9;color:#4a5567}
.deck-tag--ai{background:#f5f3ff;color:#6d28d9}
.deck-tag--mic{background:#ecfdf5;color:#047857}
/* Amber is spent on one thing only: a week whose newest deck is not the one students
   get. Roughly three rows in sixty-six. Colouring the other fifty-three "Live" rows
   loudly is what taught the eye to skip the whole column. */
.deck-tag--todo{background:#fffbeb;color:#92400e}
.deck-dot{width:7px;height:7px;border-radius:999px;background:#047857;display:inline-block;flex:none}
.deck-tag--live{background:#ecfdf5;color:#046c50}

.deck-row__meta{display:flex;align-items:center;justify-content:flex-end;gap:.5rem;white-space:nowrap}
.deck-row__act{display:flex;align-items:center;gap:.4rem;white-space:nowrap}

/* ── picking several decks at once ──────────────────────────────────────────────────────────
   The tick column is the narrowest thing that can still be hit, and it stays low-contrast until
   the row is hovered or something is actually selected: sixty-six checkboxes down the left edge
   of a list you are usually only READING is a column of noise. */
.deck-pick{display:grid;place-items:center;height:100%;cursor:pointer}
.deck-pick__box{width:14px;height:14px;margin:0;cursor:pointer;accent-color:#0f766e;
  opacity:.32;transition:opacity .12s ease}
.deck-row:hover .deck-pick__box,.deck-row:focus-within .deck-pick__box,
.deck-pick__box:checked,body.has-bulkbar .deck-pick__box{opacity:1}
.deck-row.is-picked{background:#f0fdfa}
.deck-row.is-picked:hover{background:#ccfbf1}

/* The bar sits over the page rather than in it, so ticking a row never reflows the list you are
   reading — and the body gains matching padding so the last row is still reachable under it. */
.bulkbar{position:fixed;left:50%;transform:translateX(-50%);bottom:1.1rem;z-index:60;
  display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;justify-content:center;
  max-width:min(60rem,calc(100vw - 1.5rem));padding:.55rem .7rem;border:2px solid #0b1623;
  border-radius:11px;background:#fff;box-shadow:5px 5px 0 rgba(11,22,35,.18)}
.bulkbar[hidden]{display:none}
body.has-bulkbar{padding-bottom:5rem}
.bulkbar__n{font-size:.78rem;font-weight:800;color:#0b1623;white-space:nowrap;padding:0 .35rem}
.bulkbar__n.is-warn{color:#9f1239}
.bulkbar__btn{display:inline-flex;align-items:center;gap:.35rem;white-space:nowrap;cursor:pointer;
  font-size:.78rem;font-weight:700;color:#0b1623;background:#fff;border:2px solid #0b1623;
  border-radius:7px;padding:.25rem .6rem}
.bulkbar__btn:hover{background:#0b1623;color:#fff}
.bulkbar__btn svg{flex:none}
.bulkbar__btn[hidden]{display:none}
.bulkbar__btn.is-danger{color:#9f1239;border-color:#9f1239}
.bulkbar__btn.is-danger:hover{background:#9f1239;color:#fff}
.bulkbar__sep{width:1px;height:1.1rem;background:#e2e8f0}
.bulkbar__link{cursor:pointer;background:none;border:0;font-size:.74rem;font-weight:700;
  color:#64748b;white-space:nowrap;padding:.25rem .3rem}
.bulkbar__link:hover{color:#0f766e;text-decoration:underline}
@media (max-width:640px){ .bulkbar{bottom:.5rem;gap:.35rem} .bulkbar__sep{display:none} }
@media (prefers-reduced-motion:reduce){ .deck-pick__box{transition:none} }

/* A week that holds more than one deck. 41 of 48 weeks hold exactly one and render as
   a plain row with none of this. */
.deck-slot{border-bottom:1px solid #f1f5f9}
.deck-slot__hdr{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;
  padding:.35rem .9rem;font-size:.72rem;color:#64748b;background:#f8fafc}
.deck-slot__hdr.is-stale{background:#fffbeb;color:#92400e}
.deck-slot__wk{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-weight:700}
.deck-slot__note{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.66rem}

/* Toolbar */
.deck-tools{display:flex;align-items:center;gap:.5rem;flex-wrap:wrap;margin:1rem 0 .25rem}
.deck-tools__q{flex:1 1 15rem;min-width:9rem}
.deck-facet{font-size:.72rem;font-weight:600;padding:.25rem .6rem;border-radius:999px;
  border:1px solid #e2e8f0;background:#fff;color:#475569;cursor:pointer}
.deck-facet:hover{border-color:#94a3b8}
.deck-facet[aria-pressed="true"]{background:#0f766e;border-color:#0f766e;color:#fff}
.deck-count{font-size:.72rem;color:#64748b;font-variant-numeric:tabular-nums;white-space:nowrap}
.deck-row.is-hidden,.deck-slot.is-hidden{display:none}

@media (max-width:1100px){
  /* Below this the title used to be the first thing sacrificed while the delete glyph kept its
     full width — the least important element crowding out the only identifying one. Now the row
     reflows to two lines: identity and the action on top, the measurements underneath. Grid gives
     way to wrapping flex because the cells have to share a line, which a grid cell cannot do. */
  .deck-row{display:flex;flex-wrap:wrap;align-items:center;gap:.3rem .6rem}
  .deck-row__wk{flex:none;order:0}
  .deck-row__id{flex:1 1 8rem;min-width:0;order:1}
  .deck-row__act{flex:none;order:2}
  .deck-row__meta{order:3;flex:1 0 100%;justify-content:flex-start;padding-left:2.4rem}
  .deck-row.is-nested{padding-left:1.2rem}
}


/* ── the ⋯ menu ───────────────────────────────────────────────────────────────
   Positioned by JS as position:fixed. It has to be: the panel lives inside a row inside
   .cblock.card, which carries overflow-hidden for its rounded corners and its collapse, and an
   absolutely-positioned child cannot escape that — the Apply button was simply unreachable on
   most rows. Fixed takes it out of every clipping ancestor, and the script flips it above the
   button near the bottom of the window. */
.deck-menu{position:relative}
.deck-menu__btn{list-style:none;cursor:pointer;padding:.35rem .5rem;border-radius:6px;
  color:#475569;font-weight:700;line-height:1;min-height:32px;display:grid;place-items:center}
.deck-menu__btn::-webkit-details-marker{display:none}
.deck-menu__btn:hover,.deck-menu[open] .deck-menu__btn{color:#0f766e;background:#f1f5f9}
.deck-menu__panel{position:fixed;z-index:80;width:19rem;background:#fff;border:1px solid #e2e8f0;
  border-radius:12px;box-shadow:0 12px 32px rgba(15,23,42,.16);padding:.35rem;
  display:flex;flex-direction:column;gap:.1rem}
.deck-menu__hd{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:.66rem;color:#546070;
  padding:.35rem .55rem .3rem;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}

/* One row shape for every action, so the icons form a column and the labels start at the same x —
   the old panel mixed full-width buttons with paragraph text and nothing lined up. */
.deck-menu__item{display:flex;align-items:center;gap:.55rem;width:100%;text-align:left;
  padding:.42rem .55rem;border-radius:8px;font-size:.82rem;font-weight:600;color:#334155;
  background:none;border:0;cursor:pointer;line-height:1.25}
.deck-menu__item svg{flex:none;color:#94a3b8}
.deck-menu__item:hover{background:#f1f5f9;color:#0f172a}
.deck-menu__item:hover svg{color:#0f766e}
.deck-menu__item.is-danger{color:#be123c}
.deck-menu__item.is-danger svg{color:#fb7185}
.deck-menu__item.is-danger:hover{background:#fff1f2;color:#9f1239}

.deck-menu__bind{padding:.5rem .55rem;margin:.2rem 0;border-top:1px solid #f1f5f9;border-bottom:1px solid #f1f5f9}
.deck-menu__bind label{display:block;font-size:.62rem;font-weight:700;letter-spacing:.08em;
  text-transform:uppercase;color:#64748b;margin-bottom:.3rem}
/* The select and Apply share a line. Apply used to be a full-width button under a full-width
   select, which is what pushed the panel past the height its container would show. */
.deck-menu__row{display:flex;gap:.35rem}
.deck-menu__row .field{flex:1;min-width:0;padding:.3rem .45rem;font-size:.78rem}
.deck-menu__row .btn-primary{flex:none;padding:.3rem .7rem;font-size:.78rem}
.deck-menu__bind p{margin:.35rem 0 0;font-size:.66rem;line-height:1.35;color:#5c6673}

@media (prefers-reduced-motion:reduce){
  .deck-row .btn-primary,.deck-menu__item,.deck-facet{transition:none}
}
