/* ============================================================
   Courses — "Trainer" design language (shared with Exercises).
   Rebuilt to match exercises.css: .exh header, .exstat strip,
   .extool toolbar, .excard grid for the course list, .exedit
   form for the builder meta tab, and a re-skinned curriculum
   builder + quiz editor. Landing + reviews polished to the same
   spacing / typography / hover system.

   Token-only (light + dark via html[data-theme]); RTL-safe via
   logical properties only (never left/right); reduced-motion +
   focus-visible everywhere.

   ── Editor behavioural hooks (course-builder.js reads/toggles these) ──
     .cb-lesson .cb-lesson__* .cb-section .cb-lesson__title
       (curriculum rail, course-builder.js renderList — .active/.dragging state)
     .quiz-q .quiz-q__* .q-options .quiz-opt .quiz-opt__*
     .opt-body .opt-correct .q-body .q-kind  (quiz save/load contract)
     .cb-cover .cb-cover--has #crs-thumb-img
       (cover upload, course-builder.js showThumbPreview)
     #course-tabs .seg  (segmented tabs, JS toggles .active)
   ── HOUSE RULES for this module (this is how the "odd blobs" happened) ──
     • Card footer + lesson-editor actions use the SHARED .btn system only
       (.btn--primary / .btn--ghost / .btn--sm) with VISIBLE labels. Never
       .btn--icon in THOSE two places: components.css turns it into a 34/40px
       --r-full circle, and a row of those under a card is the "blobs on a
       separate bar" look being fixed. (The small delete affordances INSIDE a
       quiz question card are .btn--icon on purpose — they are emitted by
       course-builder.js:550/587, are tooltipped + aria-labelled, and sit inside
       a card rather than in a footer bar. Changing them means changing JS.)
     • The free-lesson toggle is the CANONICAL .switch from forms.css. Never
       clone it: a checkbox that is neither .switch__input nor inside .switch is
       caught by forms.css's `input[type=checkbox]:not(.switch__input)` and
       renders as a stray in-flow 20x20 box next to the track.
   ── Reviews / moderation hooks (course-reviews*.js) ──
     .crs-mod-table .crs-mod-row .crs-mod-row--hidden .crs-mod__*
       (reviews admin, course-reviews-admin.js)
     .crs-outline .crs-outline__* .crs-landing__* .crs-enroll*
     .crs-review .crs-review__* .crs-stars .crs-stars__on/off
     .crs-review-form__stars .crs-review-form__star .is-on
       (landing + member review form, course-reviews.js)
   ============================================================ */

/* =========================================================================
   0. COURSE-LIST CARD — extends .excard (from exercises.css) with course-
      specific bits: status badge, subtitle clamp, split meta footer.
   ========================================================================= */

/* Status pill overlaying the cover (top-inline-end). */
.excard__badge--status{
  inset-block-start:8px;inset-inline-end:8px;gap:5px;
  background:color-mix(in srgb,var(--navy-900) 62%,transparent);
  -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}
.excard__badge--status .dot{
  inline-size:6px;block-size:6px;border-radius:50%;
  background:var(--accent-green);flex-shrink:0;
}

/* Subtitle under the title — clamped to two lines. */
.excard__desc{
  margin:0;color:var(--muted);font-size:var(--fz-sm);line-height:1.5;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;
}

/* Meta footer: lessons · runtime · price, price pushed to the trailing edge. */
.excard__foot--split{gap:var(--s-3);flex-wrap:wrap}
.excard__meta-item{display:inline-flex;align-items:center;gap:5px;color:var(--muted);font-size:var(--fz-xs);font-weight:500}
.excard__meta-item .icon{inline-size:14px;block-size:14px;color:var(--brand-fg);flex-shrink:0}.excard__meta-item--price{margin-inline-start:auto;color:var(--text-2);font-weight:700}

/* Status filter chips carry a status dot before the label. */
#crs-filters .exfilter .dot{inline-size:6px;block-size:6px;border-radius:50%;background:currentColor;opacity:.7;flex-shrink:0}
#crs-filters .exfilter[data-status="draft"] .dot{background:var(--muted)}
#crs-filters .exfilter[data-status="published"] .dot{background:var(--accent-green)}

/* Client-side filter hide (course-builder.js toggles .crs-hidden). */
.crs-hidden{display:none !important}

/* ---- course card FOOTER ACTIONS -----------------------------------------
   Courses deliberately does NOT use exercises.css's `.excard__actions`: that
   class ships its own hairline PLUS a `color-mix(in srgb,var(--text) 4%,…)`
   wash (exercises.css:227-232) which reads as a grey bar bolted under the card,
   and its icon-only children hit `.btn--icon` (components.css:31-32) and render
   as 34px `--r-full` circles with a `--line-strong` ring — the "blobs on a
   separate bar" look. Here the footer is a plain hairline row of THREE LABELLED
   shared buttons: one shape, one radius, one height, hierarchy by SKIN only
   (primary Edit · ghost Preview · ghost Delete that turns danger on hover).
   NEVER add `.btn--icon` in this row — that is what made the circles.

   LAYOUT: a fixed 2-column GRID rather than a wrapping flex row. Measured in
   the real app, a 280px-min grid column leaves ~231px of inner width, and three
   labelled --btn-px:12px buttons need ~261px — so a flex row wrapped and left
   "Delete" stranded alone on a second line (exactly the ragged look being fixed).
   The grid makes the two rows DELIBERATE and identical on every card at every
   width: primary Edit spans the full first row, the two quiet actions split the
   second. Same total height as the accidental wrap, none of the raggedness. */
.crs-card__acts{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  align-items:center;gap:var(--s-2);
  padding:var(--s-3) var(--s-4);
  border-block-start:1px solid var(--line);
  background:none;
}
/* compact so a labelled button never outgrows a narrow grid column */
.crs-card__acts .btn{--btn-px:12px;min-inline-size:0}
.crs-card__acts .btn .icon{inline-size:15px;block-size:15px;flex:none}
/* the primary action owns the full first row */
.crs-card__act--wide{grid-column:1 / -1}
/* Quiet until hover; colour/border/background fade only — no movement. The
   transition already comes from .btn (components.css:24) — never re-declare. */
.crs-card__act--danger{color:var(--muted)}
.crs-card__act--danger:hover{
  color:var(--danger-fg);
  border-color:color-mix(in srgb,var(--danger-fg) 42%,var(--line));
  background:color-mix(in srgb,var(--danger-fg) 8%,transparent);
}

/* GUARD — the odd treatment cannot come back to the course grid even if the
   markup ever regresses to the shared `.excard__act*` classes. course.css is
   <link>ed AFTER exercises.css on both course views (index.php / edit.php head
   section), and `#crs-grid …` outranks it regardless. The un-circling resets
   the same PHYSICAL props components.css:31 sets (symmetric, so RTL-neutral). */
#crs-grid .excard__actions{background:none}
#crs-grid .excard__act--primary{flex:0 1 auto;justify-content:center}
#crs-grid .excard__act--danger{margin-inline-start:0}
#crs-grid .btn--icon{width:auto;height:auto;--btn-px:12px}

/* =========================================================================
   1. COURSE EDITOR — RECONSTRUCTED "curriculum workbench" (surface B).
      A slim course bar (.cb-bar) + a centered details form (.cb-meta) +
      a rail/canvas workbench (.cb-work). All-new .cb-* namespace; the old
      .crs-edit__head / .crs-tabs / .builder / .lesson-row / .quiz-* markup
      is gone. Token-only, both themes, RTL logical props.
   ========================================================================= */

/* ---- slim course bar ----------------------------------------------------- */
.cb-bar{
  display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-3) var(--s-4);
  padding:var(--s-3) var(--s-4);margin-block-end:var(--s-6);
  background:var(--glass-bg);border:1px solid var(--glass-border);border-radius:var(--r-lg);
  box-shadow:var(--shadow-xs),var(--glass-hi);backdrop-filter:blur(var(--glass-blur));
  position:sticky;inset-block-start:calc(var(--nav-h) - 1px);z-index:6;
}
.cb-bar__back{
  inline-size:38px;block-size:38px;flex-shrink:0;display:grid;place-items:center;border-radius:var(--r-full);
  border:1px solid var(--line);color:var(--text-2);background:var(--surface);
  transition:color var(--dur) var(--ease),border-color var(--dur) var(--ease),background var(--dur) var(--ease);
}
.cb-bar__back:hover{color:var(--brand-fg);border-color:var(--line-brand);background:var(--tint)}
.cb-bar__id{min-inline-size:0;flex:1 1 240px;display:flex;flex-direction:column;gap:3px}
.cb-bar__title{
  margin:0;font-size:var(--fz-lg);font-weight:800;letter-spacing:-.01em;line-height:1.15;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
.cb-bar__meta{display:flex;align-items:center;gap:var(--s-2);flex-wrap:wrap;font-size:var(--fz-xs)}
.cb-state{display:inline-flex;align-items:center;gap:6px;font-weight:700;color:var(--muted)}
.cb-state__dot{inline-size:7px;block-size:7px;border-radius:50%;background:currentColor;box-shadow:0 0 8px currentColor}
.cb-state--pub{color:var(--success-fg)}
.cb-state--draft{color:var(--muted)}
.cb-bar__sep{inline-size:3px;block-size:3px;border-radius:50%;background:var(--line-strong);flex-shrink:0}
.cb-bar__lessons{display:inline-flex;align-items:center;gap:5px;color:var(--muted);font-weight:600}
.cb-bar__lessons .icon{inline-size:13px;block-size:13px;color:var(--brand-fg)}
.cb-bar__tabs{flex-shrink:0}
.cb-bar__tabs button{display:inline-flex;align-items:center;gap:7px}
.cb-bar__tabs button .icon{inline-size:15px;block-size:15px}
.cb-bar__actions{display:flex;align-items:center;gap:var(--s-2);flex-shrink:0}
.cb-bar__actions .btn .icon{inline-size:15px;block-size:15px}
@media (max-width:900px){
  .cb-bar__actions-lbl{position:absolute;inline-size:1px;block-size:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .cb-bar__actions .btn{--btn-px:11px}
}
@media (max-width:620px){
  .cb-bar{position:static}
  .cb-bar__tabs{order:3;flex:1 1 100%}
  .cb-bar__tabs button{flex:1;justify-content:center}
}

/* =========================================================================
   2. DETAILS TAB — centered, well-grouped panels (.cb-meta).
      Cover banner first, then numbered "Basics" + "Pricing & access".
   ========================================================================= */
.cb-meta{max-inline-size:860px;margin-inline:auto;display:flex;flex-direction:column;gap:var(--s-5)}

.cb-panel{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  padding:var(--s-6);box-shadow:var(--shadow-xs),var(--glass-hi);
}
.cb-panel--cover{padding:var(--s-4)}
.cb-panel__head{display:flex;align-items:flex-start;gap:var(--s-3);margin-block-end:var(--s-5)}
.cb-panel__num{
  inline-size:28px;block-size:28px;flex-shrink:0;display:grid;place-items:center;border-radius:var(--r-sm);
  background:var(--brand-grad);color:var(--on-brand);font-size:var(--fz-sm);font-weight:800;
  font-variant-numeric:tabular-nums;box-shadow:var(--glow);
}
.cb-panel__head-text{min-inline-size:0}
.cb-panel__title{margin:0;font-size:var(--fz-md);font-weight:700;letter-spacing:-.01em}
.cb-panel__sub{margin:2px 0 0;color:var(--muted);font-size:var(--fz-sm);line-height:1.5}
.cb-panel__body{display:flex;flex-direction:column;gap:var(--s-4)}
.cb-panel__body .field{margin-block-end:0}

/* two-up field row that collapses on narrow */
.cb-row2{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-4)}
@media (max-width:560px){.cb-row2{grid-template-columns:1fr}}

/* label + inline "Open builder" trigger */
.cb-label-row{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);margin-block-end:var(--s-2)}
.cb-label-row .label{margin-block-end:0}

/* cover banner (hooks: .cb-cover / .cb-cover--has / #crs-thumb-img) */
.cb-cover{
  aspect-ratio:3/1;border-radius:var(--r);overflow:hidden;position:relative;
  border:1px dashed var(--line);background:var(--brand-grad-soft);display:grid;place-items:center;
}
.cb-cover--has{border-style:solid;border-color:var(--line)}
.cb-cover img{inline-size:100%;block-size:100%;object-fit:cover}
.cb-cover__ph{color:var(--brand-fg);opacity:.45;display:grid;place-items:center}.cb-cover__ph .icon{inline-size:52px;block-size:52px}
.cb-cover__drop{margin-block-start:var(--s-3);padding:var(--s-4)}
.cb-cover__drop small{margin-block-start:2px}
.cb-cover__status{display:block;margin-block-start:var(--s-2);font-size:var(--fz-xs)}

/* sticky save bar for the details form */
.cb-meta__save{
  position:sticky;inset-block-end:var(--s-4);display:flex;align-items:center;gap:var(--s-3);
  padding:var(--s-3) var(--s-4);border-radius:var(--r-lg);
  background:color-mix(in srgb,var(--surface) 88%,transparent);backdrop-filter:blur(10px);
  border:1px solid var(--line);box-shadow:var(--shadow-sm),var(--glass-hi);
}
.cb-meta__save-hint{margin-inline-end:auto;color:var(--muted);font-size:var(--fz-xs)}

/* =========================================================================
   3. CURRICULUM WORKBENCH — narrow rail + dominant editor canvas (.cb-work).
   ========================================================================= */
.cb-work{display:grid;grid-template-columns:300px minmax(0,1fr);gap:var(--s-5);align-items:start}

/* ---- lesson rail --------------------------------------------------------- */
.cb-rail{
  display:flex;flex-direction:column;
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-xs),var(--glass-hi);overflow:hidden;
  position:sticky;inset-block-start:calc(var(--nav-h) + 64px);
  max-block-size:calc(100vh - var(--nav-h) - var(--s-12));
}
.cb-rail__head{padding:var(--s-4);border-block-end:1px solid var(--line);background:var(--card-head)}
.cb-rail__head-top{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3)}
.cb-rail__label{font-size:var(--fz-md);font-weight:700;letter-spacing:-.01em}
.cb-rail__runtime{
  margin-block-start:var(--s-2);font-size:var(--fz-xs);color:var(--muted);
  display:flex;align-items:center;gap:6px;
}
.cb-rail__runtime #total-duration{
  color:var(--text-2);font-weight:700;font-variant-numeric:tabular-nums;
  padding:2px 8px;border-radius:var(--r-full);background:var(--bg-3);
}
.cb-rail__list{
  display:flex;flex-direction:column;gap:2px;overflow-y:auto;flex:1;min-block-size:0;
  padding:var(--s-3);
}

.cb-section{
  font-size:var(--fz-xs);text-transform:uppercase;letter-spacing:.07em;color:var(--muted);
  font-weight:700;padding:var(--s-4) var(--s-2) var(--s-2);
}
.cb-section:first-child{padding-block-start:var(--s-1)}

.cb-lesson{
  display:flex;align-items:center;gap:9px;padding:8px 10px;border-radius:var(--r-sm);
  cursor:pointer;color:var(--text-2);border:1px solid transparent;position:relative;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease),
    color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.cb-lesson::before{
  content:"";position:absolute;inset-inline-start:0;inset-block:6px;inline-size:3px;
  border-radius:var(--r-full);background:var(--brand-grad);opacity:0;
  transition:opacity var(--dur) var(--ease);
}
.cb-lesson:hover{background:var(--tint);color:var(--text);border-color:var(--line)}
.cb-lesson:focus-visible{outline:2px solid var(--focus-line);outline-offset:2px}
.cb-lesson.dragging{opacity:.5;background:var(--bg-3);border-style:dashed;border-color:var(--line-brand)}
.cb-lesson.active{
  background:var(--brand-grad-soft);border-color:var(--line-brand);color:var(--brand-fg);box-shadow:var(--glass-hi);
}
.cb-lesson.active::before{opacity:1}.cb-lesson__handle{color:var(--muted);display:inline-flex;cursor:grab;flex-shrink:0}
.cb-lesson__handle .icon{inline-size:15px;block-size:15px}
.cb-lesson__num{
  inline-size:22px;block-size:22px;flex-shrink:0;display:grid;place-items:center;border-radius:var(--r-xs);
  background:var(--bg-3);color:var(--muted);font-size:11px;font-weight:700;font-variant-numeric:tabular-nums;
  transition:background var(--dur) var(--ease),color var(--dur) var(--ease);
}
.cb-lesson.active .cb-lesson__num{background:var(--brand-grad);color:var(--on-brand);box-shadow:var(--glow)}
.cb-lesson__ico{color:var(--muted);display:inline-flex;flex-shrink:0}
.cb-lesson__ico .icon{inline-size:15px;block-size:15px}
.cb-lesson.active .cb-lesson__ico{color:var(--brand-fg)}.cb-lesson__body{display:flex;flex-direction:column;min-inline-size:0;flex:1;line-height:1.3}
.cb-lesson__title{font-size:var(--fz-sm);font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.cb-lesson__type{font-size:11px;color:var(--muted)}
.cb-lesson__free{
  flex-shrink:0;font-size:10px;padding:2px 7px;border-radius:var(--r-full);font-weight:700;
  background:color-mix(in srgb,var(--accent-green) 12%,transparent);color:var(--success-fg);
  border:1px solid color-mix(in srgb,var(--accent-green) 30%,transparent);
}

.cb-rail__empty{
  text-align:center;padding:var(--s-10) var(--s-4);color:var(--muted);
  display:flex;flex-direction:column;align-items:center;gap:var(--s-3);
}
.cb-rail__empty-ico{
  inline-size:52px;block-size:52px;display:grid;place-items:center;border-radius:var(--r-lg);
  background:var(--brand-grad-soft);color:var(--brand-fg);border:1px solid var(--line-brand);box-shadow:var(--glass-hi);
}.cb-rail__empty-ico .icon{inline-size:26px;block-size:26px}
.cb-rail__empty p{font-size:var(--fz-sm);max-inline-size:30ch;line-height:1.5}

/* ---- editor canvas ------------------------------------------------------
   ONE card, flush: a titled head, numbered steps divided by hairlines, and a
   sticky save bar. NO padding on the card and NO overflow:hidden — an
   overflow:hidden ancestor turns `position:sticky` into a no-op, so the corners
   are clipped with LOGICAL corner radii on the head/foot instead. */
.cb-canvas{min-inline-size:0}
.cb-canvas__editor{
  background:var(--surface);border:1px solid var(--line);border-radius:var(--r-lg);
  box-shadow:var(--shadow-sm),var(--glass-hi);
}
.cb-form{display:flex;flex-direction:column}

/* head — what this panel is, and the ORDER of work. The destructive action is a
   quiet LABELLED shared button (it used to be a hand-rolled 36px circle). */
.cb-ed__head{
  display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-4);
  padding:var(--s-5) var(--s-6);background:var(--card-head);
  border-start-start-radius:var(--r-lg);border-start-end-radius:var(--r-lg);
}
.cb-ed__head-text{min-inline-size:0;display:flex;flex-direction:column;gap:3px}
.cb-ed__eyebrow{
  font-size:var(--fz-xs);font-weight:700;text-transform:uppercase;
  letter-spacing:.08em;color:var(--brand-fg);
}
.cb-ed__title{margin:0;font-size:var(--fz-md);font-weight:700;letter-spacing:-.01em;color:var(--text)}
.cb-ed__sub{margin:0;color:var(--muted);font-size:var(--fz-sm);line-height:1.55;max-inline-size:64ch}
.cb-ed__del{flex:none}

/* ---- numbered steps ------------------------------------------------------
   `.cb-fs` (a bare hairline under a title inside a flat card) is gone. Steps
   REUSE the Details-tab language already in this file (.cb-panel__head / __num /
   __head-text / __title / __sub) so both surfaces read as one system, but
   without a nested card surface. The divider lives on `border-block-start`, so a
   hidden type panel takes its hairline with it — never a stranded rule. */
.cb-step{
  padding:var(--s-6);border-block-start:1px solid var(--line);
  display:flex;flex-direction:column;gap:var(--s-5);
}
.cb-step .field{margin-block-end:0}
.cb-step .cb-panel__head{margin-block-end:0;align-items:flex-start}
.cb-step .cb-panel__head-text{flex:1 1 auto}
.cb-panel__act{flex:none;margin-inline-start:auto}
.cb-step__body{display:flex;flex-direction:column;gap:var(--s-5)}

/* required-field marker — no app-wide class exists; mirrors the existing
   module-local precedents (.exw-req, .req, .sbc-req). */
.cb-req{color:var(--danger-fg);font-weight:800;margin-inline-start:2px}
/* --text-2, not --muted: this note sits on the sticky footer, whose translucent
   color-mix(--surface 92%) fill drops --muted to 4.07:1 in the light theme — under the
   4.5:1 AA floor for ~12px text. --text-2 clears it on that same fill in both themes. */
.cb-reqnote{display:inline-flex;align-items:center;gap:6px;color:var(--text-2);font-size:var(--fz-xs)}
.cb-reqnote .cb-req{margin-inline-start:0}

/* Field-level error MESSAGE only. The danger BORDER for :user-invalid /
   [aria-invalid] / .field--error already ships app-wide from forms-standard.css
   §7 (loaded by layouts/dashboard.php and written `html :is(…)` so it wins) —
   do not duplicate it. `:is()` is forgiving, so an engine without
   :user-invalid drops that one argument instead of the whole rule. */
.cb-field__err{display:none}
.cb-field--req :is(.input:user-invalid,.input[aria-invalid="true"]) ~ .cb-field__err,
.cb-field--req.field--error .cb-field__err{display:block}

/* video: source + duration share a row; the id fields drop below */
.cb-vrow{display:grid;grid-template-columns:minmax(0,1fr) 180px;gap:var(--s-5);align-items:start}
.cb-vrow .field{min-inline-size:0}
@media (max-width:640px){.cb-vrow{grid-template-columns:1fr}}

/* ---- segmented control (video source) ------------------------------------
   Custom, radio-backed, CSP-safe; replaces the old oversized <select>.
   course-builder.js reads the checked radio via #l-vkind (the CONTAINER) and
   FormData still posts name="video_kind".
   Radio-backed (JS needs #l-vkind to stay a radiogroup CONTAINER), but now
   CONTENT WIDTH and start-aligned like .exsrc-toggle (exercises.css:345-352) —
   never a full-width chunky bar. `.cb-seg__btn` is a <span>, which
   motion-standard.css does not cover, so this is the one hand-written
   transition: colour / border / shadow only, no movement. */
.cb-seg{
  display:inline-flex;align-items:stretch;flex-wrap:wrap;align-self:start;
  inline-size:auto;max-inline-size:100%;gap:3px;padding:3px;
  border-radius:var(--r-full);
  background:var(--bg-3);border:1px solid var(--line);
  box-shadow:inset 0 1px 2px color-mix(in srgb,var(--navy-900) 6%,transparent),var(--inset-sunken);
}
.cb-seg__opt{position:relative;flex:0 0 auto;display:flex;min-inline-size:0}
.cb-seg__input{position:absolute;inset:0;inline-size:100%;block-size:100%;margin:0;opacity:0;cursor:pointer}
.cb-seg__btn{
  display:inline-flex;align-items:center;justify-content:center;gap:6px;
  padding:7px 16px;border-radius:var(--r-full);
  font-size:var(--fz-xs);font-weight:600;color:var(--text-2);
  white-space:nowrap;border:1px solid transparent;
  transition:color var(--dur) var(--ease),background-color var(--dur) var(--ease),
    border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.cb-seg__opt:hover .cb-seg__btn{color:var(--text);background:var(--tint)}
.cb-seg__input:checked ~ .cb-seg__btn{
  background:var(--surface);color:var(--brand-fg);
  border-color:var(--line-brand);box-shadow:var(--shadow-xs),var(--glass-hi);
}
.cb-seg__input:checked:hover ~ .cb-seg__btn{background:var(--surface);color:var(--brand-fg)}
.cb-seg__input:focus-visible ~ .cb-seg__btn{outline:2px solid var(--focus-line);outline-offset:2px}

/* ---- FREE-LESSON TOGGLE --------------------------------------------------
   The canonical `.switch` (forms.css:69-183) is the SINGLE source of truth; the
   module-local `.cb-switch*` clone is GONE. Never re-add one: a checkbox that is
   not `.switch__input` AND is not inside `.switch` is captured by
   `input[type="checkbox"]:not(.switch__input)` (forms.css:42, specificity 0,2,1
   — it beats any single class regardless of load order) and rendered as a 20x20
   IN-FLOW box. That phantom checkbox is what made this control look broken.
   course.css supplies LAYOUT ONLY. */
.cb-free{align-items:flex-start;gap:var(--s-3)}
.cb-free__text{display:flex;flex-direction:column;min-inline-size:0}
.cb-free .switch__track{margin-block-start:2px}
.cb-free__row{
  display:flex;padding:var(--s-4);
  border:1px solid var(--line);border-radius:var(--r);background:var(--bg-2);
}
/* HARD GUARD (scoped to this module's editor so there is no app-wide blast
   radius) — no naked checkbox may ever render as a stray box beside a track
   here, whatever the load order or a stale cached copy of this file does.
   Mirrors forms.css:109-113 with enough weight to always win. */
#lesson-editor .switch input[type="checkbox"],
.cb-free__row input[type="checkbox"],
.cb-switch input[type="checkbox"]{
  position:absolute !important;inline-size:1px !important;block-size:1px !important;
  opacity:0 !important;margin:-1px !important;padding:0 !important;border:0 !important;
  overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;
}

/* article writing canvas — the tall focused surface */
.cb-editor__canvas{min-block-size:320px;line-height:1.75;resize:vertical;font-size:var(--fz-base)}

/* ---- sticky save bar ----------------------------------------------------
   No negative-margin bleed needed now that the card is flush. ONE primary
   action, plus the required-field note stated where the user commits. */
.cb-ed__foot{
  position:sticky;inset-block-end:0;z-index:2;
  display:flex;align-items:center;flex-wrap:wrap;gap:var(--s-3);
  padding:var(--s-4) var(--s-6);
  border-block-start:1px solid var(--line);
  border-end-start-radius:var(--r-lg);border-end-end-radius:var(--r-lg);
  background:color-mix(in srgb,var(--surface) 92%,transparent);
  -webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);
}
.cb-ed__foot .cb-reqnote{margin-inline-end:auto}
.cb-ed__foot .btn--primary{flex:none}

/* idle full-canvas invitation */
.cb-canvas__idle{
  display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;
  gap:var(--s-4);min-block-size:520px;padding:var(--s-10);
  background:var(--surface);border:1px dashed var(--line);border-radius:var(--r-lg);
}
.cb-canvas__idle-ico{
  inline-size:76px;block-size:76px;display:grid;place-items:center;border-radius:var(--r-xl);
  background:var(--brand-grad-soft);color:var(--brand-fg);border:1px solid var(--line-brand);box-shadow:var(--glass-hi);
}.cb-canvas__idle-ico .icon{inline-size:36px;block-size:36px}
.cb-canvas__idle h3{margin:0;font-size:var(--fz-lg);font-weight:700;color:var(--text)}
.cb-canvas__idle p{margin:0;max-inline-size:42ch;color:var(--muted);font-size:var(--fz-sm);line-height:1.6}

/* =========================================================================
   3b. QUIZ BUILDER (inside the quiz panel). JS save/load contract classes
       (.quiz-q/.q-body/.q-kind/.quiz-opt/.opt-body/.opt-correct) kept.
   ========================================================================= */
.cb-quiz__settings{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4)}
.cb-quiz__settings .field{margin-block-end:0}
@media (max-width:640px){.cb-quiz__settings{grid-template-columns:1fr}}

/* Was a bordered box nested inside an already-bordered card (boxes inside
   boxes). Now flush, split off by a dashed hairline. Written as an explicit
   override rather than a deletion, because a browser may still hold the stale
   `@import …modules/course.css?v=10` copy from primunity.css. */
.cb-quiz{
  border:0;border-radius:0;background:none;
  border-block-start:1px dashed var(--line);
  padding:var(--s-5) 0 0;
}
.cb-quiz__head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);margin-block-end:var(--s-2)}
.cb-quiz__title{font-size:var(--fz-sm);font-weight:700;color:var(--text)}
.cb-quiz__status{font-size:var(--fz-xs);color:var(--success-fg);font-weight:600}
.cb-quiz__hint{margin:0 0 var(--s-4);color:var(--muted);font-size:var(--fz-xs);line-height:1.5}
.cb-quiz__actions{display:flex;flex-wrap:wrap;gap:var(--s-3);align-items:center;margin-block-start:var(--s-4)}

.quiz-q{
  border:1px solid var(--line);border-radius:var(--r-lg);padding:var(--s-5);margin-block-end:var(--s-4);
  background:var(--surface);box-shadow:var(--shadow-sm),var(--glass-hi);
  transition:border-color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.quiz-q:hover{border-color:var(--line-strong)}
.quiz-q:focus-within{border-color:var(--line-brand);box-shadow:var(--shadow),var(--glass-hi)}
.quiz-q__head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);margin-block-end:var(--s-3)}
/* .quiz-q__num is the ONLY selector this sheet shares with modules/player.css, and
   it is emitted from BOTH sides of the course feature: course-builder.js:549 puts it
   in .quiz-q__head (a flex row, above) and course-player.js:631 puts it in
   .quiz-q__body (player.css's flex row). It is a fixed 26px circle, so `flex-shrink:0`
   is load-bearing in both rows — without it the badge is squashed by a long sibling.
   player.css declares it; this sheet did NOT, which was invisible while player.css
   arrived via the primunity.css manifest on every page and became a real defect the
   moment player.css became page-linked: the builder (/dashboard/courses/{id}) links
   course.css WITHOUT player.css, so the badge computed flex-shrink:1 there.
   Declared HERE rather than by linking a 30 KB player sheet into the builder: the
   two sheets' selector intersection is this one rule, so player.css contributes
   nothing else the builder could use. */
.quiz-q__num{
  flex-shrink:0;
  inline-size:26px;block-size:26px;display:grid;place-items:center;border-radius:var(--r-full);
  background:var(--brand-grad);color:var(--on-brand);font-size:var(--fz-xs);font-weight:800;box-shadow:var(--glow);
}
.quiz-q__addopt{margin-block-start:var(--s-2)}
.q-options{display:flex;flex-direction:column;gap:var(--s-2);margin-block-start:var(--s-3)}

/* One answer row: [correct toggle] [flexible input] [delete]. */
.quiz-opt{
  display:grid;grid-template-columns:auto 1fr auto;align-items:center;
  gap:var(--s-3);padding:var(--s-2);border:1px solid transparent;border-radius:var(--r-sm);
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.quiz-opt:hover{background:var(--bg-2);border-color:var(--line)}
.quiz-opt--edit .opt-body{flex:1;min-inline-size:0}

/* ---- DE-BLEED: player.css must not style the BUILDER's answer rows ---------
   player.css is @imported by the primunity.css bundle, so it loads on EVERY
   page — including this editor — and two of its player rules are UNSCOPED:
     .quiz-opt label{display:flex;padding:13px 16px;border:1px solid …;width:100%}
     .quiz-opt input{width:18px;height:18px}                    (player.css:245-249)
   Both are (0,1,1) — a class PLUS a type — so they OUT-SPECIFY this module's
   single-class `.quiz-opt__correct` / `.opt-body` rules no matter which file
   loads last. Measured live before this fix: the correct-answer toggle rendered
   as an 89.6px padded rounded rect instead of a 32px round check, and the answer
   TEXT input collapsed to 30px wide inside its 621px grid column — i.e. the same
   "controls look broken" defect, in the same editor.
   The cure is specificity, not order: every rule below is scoped to
   `.quiz-opt--edit` (0,2,0+), the class course-builder.js always stamps on
   builder rows (`row.className = 'quiz-opt quiz-opt--edit'`) and that the player
   never emits — so the player's own quiz is untouched. */
.quiz-opt--edit .quiz-opt__correct{
  display:inline-grid;place-items:center;inline-size:32px;block-size:32px;
  padding:0;border:0;background:none;border-radius:var(--r-full);gap:0;
}
.quiz-opt--edit .quiz-opt__correct:hover{background:none;border-color:transparent}
/* Full-size invisible hit target. This needs THREE classes (0,3,0) to win:
   forms.css:42 `input[type="checkbox"]:not(.switch__input)` is (0,2,1) — a type
   selector plus two class-level parts — so it beat the two-class
   `.quiz-opt__correct .opt-correct` rule below and forced the real checkbox back
   to `position:relative; display:inline-grid; 20x20`. Because the label is a
   2-child grid, that in-flow checkbox stole a grid ROW and squashed the visible
   check dot to ~12px. Absolutely positioning it again restores a single centred
   dot AND makes the whole 32px label the click target. */
.quiz-opt--edit .quiz-opt__correct .opt-correct{
  position:absolute;inset:0;margin:0;
  inline-size:100%;block-size:100%;
  border:0;border-radius:inherit;background:none;appearance:none;
  accent-color:auto;
}
/* let the answer field fill its 1fr column again */
.quiz-opt--edit .opt-body{inline-size:auto;block-size:auto}

/* Correct-answer affordance: pill toggle with a check. Checked = brand + glow. */
.quiz-opt__correct{position:relative;display:inline-grid;place-items:center;inline-size:32px;block-size:32px;flex-shrink:0;cursor:pointer}
.quiz-opt__correct .opt-correct{position:absolute;inset:0;margin:0;opacity:0;cursor:pointer}
.quiz-opt__correct-dot{
  display:grid;place-items:center;inline-size:26px;block-size:26px;
  border-radius:var(--r-full);border:1.5px solid var(--line);background:var(--surface);color:transparent;
  transition:border-color var(--dur) var(--ease),background var(--dur) var(--ease),
    color var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.quiz-opt__correct-dot .icon{inline-size:15px;block-size:15px}
.quiz-opt__correct:hover .quiz-opt__correct-dot{border-color:var(--line-brand);color:var(--brand-fg)}
.quiz-opt__correct .opt-correct:checked ~ .quiz-opt__correct-dot{
  background:var(--brand-grad);border-color:transparent;color:var(--on-brand);box-shadow:var(--glow);
}
.quiz-opt__correct .opt-correct:focus-visible ~ .quiz-opt__correct-dot{outline:2px solid var(--line-brand);outline-offset:2px}
.quiz-opt__del{flex-shrink:0;color:var(--muted);transition:color var(--dur) var(--ease)}
.quiz-opt__del:hover{color:var(--danger-fg)}

/* =========================================================================
   4. PUBLIC LANDING — aurora hero preserved; spacing/hover polished to match.
   ========================================================================= */
.crs-landing{max-inline-size:var(--container);margin-inline:auto;padding:calc(var(--nav-h) + var(--s-10)) var(--s-6) var(--s-16)}

.crs-landing__hero{display:grid;grid-template-columns:1.1fr .9fr;gap:var(--s-10);align-items:center;margin-block-end:var(--s-12)}
.crs-landing__hero-copy .section__eyebrow{display:inline-flex;align-items:center;gap:6px}
.crs-landing__title{
  font-size:var(--fz-2xl);margin-block-end:var(--s-4);line-height:1.08;
  letter-spacing:var(--tracking-display);font-weight:800;
}
.crs-landing__sub{font-size:var(--fz-md);color:var(--text-2);max-inline-size:52ch;margin-block-end:var(--s-6)}
.crs-landing__facts{display:flex;flex-wrap:wrap;gap:var(--s-3) var(--s-5);margin-block-end:var(--s-8);list-style:none;padding:0}
.crs-landing__facts li{display:inline-flex;align-items:center;gap:7px;font-size:var(--fz-sm);color:var(--text-2);font-weight:500}
.crs-landing__facts li a{display:inline-flex;align-items:center;gap:7px;color:inherit;text-decoration:none;transition:color var(--dur) var(--ease)}
.crs-landing__facts li a:hover{color:var(--brand-fg)}.crs-landing__facts .icon{color:var(--brand-fg)}.crs-landing__cta{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-3)}
.crs-landing__price{font-size:var(--fz-lg);font-weight:800;color:var(--text)}
.crs-landing__free-note{
  display:inline-flex;align-items:center;gap:7px;margin-block-start:var(--s-5);
  font-size:var(--fz-sm);color:var(--success-fg);font-weight:600;
}

/* hero poster / preview mock */
.crs-landing__hero-media{position:relative}
.crs-landing__poster{
  position:relative;aspect-ratio:16/9;border-radius:var(--r-2xl);overflow:hidden;
  border:1px solid var(--line);box-shadow:var(--shadow-xl);background:var(--brand-grad-soft);
}
.crs-landing__poster img{inline-size:100%;block-size:100%;object-fit:cover}
.crs-landing__poster-fallback{position:absolute;inset:0;display:grid;place-items:center;color:var(--brand-fg);opacity:.5}.crs-landing__poster-fallback .icon{inline-size:72px;block-size:72px}
.crs-landing__play{
  position:absolute;inset:0;margin:auto;inline-size:74px;block-size:74px;border-radius:var(--r-full);
  display:grid;place-items:center;background:var(--surface-solid);color:var(--brand-fg);
  box-shadow:var(--shadow-lg);
  transition:background var(--dur) var(--ease),box-shadow var(--dur) var(--ease);
}
.crs-landing__play .icon{inline-size:28px;block-size:28px;margin-inline-start:3px}
[dir="ltr"] .crs-landing__play .icon{margin-inline-start:0;margin-inline-end:-3px}
.crs-landing__play:hover{background:var(--surface);box-shadow:var(--shadow-xl)}
.crs-landing__poster-card{
  position:absolute;inset-block-end:-22px;inset-inline-end:-14px;
  display:flex;gap:var(--s-5);padding:var(--s-4) var(--s-5);border-radius:var(--r-lg);
  background:var(--surface-solid);border:1px solid var(--line);box-shadow:var(--shadow-lg);
}
.crs-landing__poster-card>div{display:flex;flex-direction:column;line-height:1.3}
.crs-landing__poster-card span{font-size:11px}
.crs-landing__poster-card strong{font-size:var(--fz-md);color:var(--text)}

/* landing body grid + outline + sticky enroll */
.crs-landing__grid{display:grid;grid-template-columns:1fr 340px;gap:var(--s-8);align-items:start}
.crs-landing__main{min-inline-size:0}

.crs-outline__head{
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);
  padding:var(--s-5) var(--s-6);border-block-end:1px solid var(--line);
}
.crs-outline__head h2{font-size:var(--fz-lg);margin:0}
.crs-outline{padding:var(--s-3) var(--s-4);list-style:none;margin:0}
.crs-outline__chapter{
  display:flex;align-items:center;gap:6px;font-size:var(--fz-xs);font-weight:700;
  text-transform:uppercase;letter-spacing:.06em;color:var(--muted);padding:var(--s-4) var(--s-2) var(--s-2);
}
.crs-outline__chapter:first-child{padding-block-start:var(--s-2)}
.crs-outline__chapter .icon{color:var(--brand-fg)}.crs-outline__item{
  display:flex;align-items:center;gap:12px;padding:12px var(--s-2);border-radius:var(--r-sm);
  border:1px solid transparent;
  transition:background var(--dur) var(--ease),border-color var(--dur) var(--ease);
}
.crs-outline__item:hover{background:var(--tint);border-color:var(--line-brand)}
.crs-outline__ico{
  inline-size:34px;block-size:34px;flex-shrink:0;display:grid;place-items:center;border-radius:var(--r-sm);
  background:var(--brand-grad-soft);color:var(--brand-fg);border:1px solid var(--line-brand);box-shadow:var(--glass-hi);
}.crs-outline__title{flex:1;min-inline-size:0;display:flex;flex-direction:column;line-height:1.35;font-size:var(--fz-sm);font-weight:600;color:var(--text)}
.crs-outline__title small{font-weight:400}
.crs-outline__free{flex-shrink:0}
.crs-outline__lock{color:var(--muted);flex-shrink:0}
.crs-outline__dur{flex-shrink:0;font-size:var(--fz-xs);font-variant-numeric:tabular-nums}

.crs-landing__aside{position:sticky;inset-block-start:calc(var(--nav-h) + var(--s-6))}
.crs-enroll__price{
  display:flex;flex-direction:column;gap:2px;margin-block-end:var(--s-5);
  padding-block-end:var(--s-5);border-block-end:1px solid var(--line);
}
.crs-enroll__price .price{font-size:38px;font-weight:800;font-variant-numeric:tabular-nums;letter-spacing:var(--tracking-display)}
.crs-enroll__feats{margin-block-start:var(--s-5);display:flex;flex-direction:column;gap:var(--s-1);list-style:none;padding:0}

/* =========================================================================
   5. RESPONSIVE
   ========================================================================= */
@media (max-width:1040px){
  .cb-work{grid-template-columns:1fr}
  .cb-rail{position:static;max-block-size:none}
  .cb-rail__list{max-block-size:420px}
  .cb-canvas__idle{min-block-size:360px}
}
/* narrow: tighten the step rhythm rather than letting padding eat the fields */
@media (max-width:560px){
  .cb-step{padding:var(--s-5) var(--s-4)}
  .cb-ed__head,.cb-ed__foot{padding-inline:var(--s-4)}
  .cb-ed__head{flex-wrap:wrap}
}
@media (max-width:1024px){
  .crs-landing__hero{grid-template-columns:1fr;gap:var(--s-8)}
  .crs-landing__grid{grid-template-columns:1fr}
  .crs-landing__aside{position:static}
  .crs-landing__poster-card{inset-inline-end:var(--s-4)}
}
@media (max-width:640px){
  .crs-landing__poster-card{position:static;margin-block-start:var(--s-4)}
}

/* =========================================================================
   6. COURSE REVIEWS & RATINGS — star display, review list, member form,
      dashboard moderation table. Hooks kept for course-reviews*.js.
   ========================================================================= */

/* star rating (display) */
.crs-stars{display:inline-flex;align-items:center;gap:2px;line-height:1}
.crs-stars .icon{inline-size:18px;block-size:18px}
.crs-stars__on{color:var(--warn-fg)}
.crs-stars__off{color:var(--line-strong)}
.crs-stars--lg .icon{inline-size:22px;block-size:22px}

.crs-rating-head{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;margin-block-end:var(--s-4)}
.crs-rating-head__num{
  font-size:32px;font-weight:800;line-height:1;font-variant-numeric:tabular-nums;
  letter-spacing:var(--tracking-display);
}
.crs-rating-head__meta{display:flex;flex-direction:column;gap:2px}

/* landing review block */
.crs-reviews{margin-block-start:var(--s-2)}
.crs-reviews__list{display:flex;flex-direction:column;gap:var(--s-4);margin-block-start:var(--s-5)}
.crs-review{padding-block-end:var(--s-4);border-block-end:1px solid var(--line)}
.crs-review:last-child{border-block-end:0;padding-block-end:0}
.crs-review__head{display:flex;align-items:center;justify-content:space-between;gap:var(--s-3);flex-wrap:wrap}
.crs-review__who{display:flex;align-items:center;gap:var(--s-2)}
.crs-review__avatar{
  inline-size:36px;block-size:36px;border-radius:50%;display:grid;place-items:center;font-weight:700;
  background:var(--brand-grad-soft);color:var(--brand-fg);border:1px solid var(--line-brand);box-shadow:var(--glass-hi);
}.crs-review__author{font-weight:600;color:var(--text)}
.crs-review__date{color:var(--muted);font-size:var(--fz-sm)}
.crs-review__title{font-weight:700;margin-block-start:var(--s-2)}
.crs-review__body{color:var(--text-2);margin-block-start:var(--s-1);white-space:pre-wrap;word-break:break-word}

/* member review form */
.crs-review-form__stars{display:inline-flex;gap:4px;margin-block-end:var(--s-2)}
.crs-review-form__star{
  background:none;border:0;padding:2px;cursor:pointer;color:var(--line-strong);line-height:0;border-radius:var(--r-xs);
  transition:color var(--dur) var(--ease);
}
.crs-review-form__star .icon{inline-size:28px;block-size:28px}
.crs-review-form__star:hover,
.crs-review-form__star.is-on{color:var(--warn-fg)}
.crs-review-form__star:focus-visible{outline:2px solid var(--focus-line);outline-offset:2px}

/* dashboard moderation table (.extable base + course-specific cells) */
.crs-mod__rating{color:var(--warn-fg);white-space:nowrap}
.crs-mod__body{color:var(--text-2);max-inline-size:520px}
.crs-mod-row{transition:opacity var(--dur) var(--ease)}
.crs-mod-row--hidden{opacity:.55}
.extable-name{color:var(--text);font-weight:700}

