/* ═══════════════════════════════════════════
   LESSON FRAMEWORK — shared across all
   interactive lessons. Depends on tokens.css
═══════════════════════════════════════════ */
*{box-sizing:border-box;margin:0;padding:0}
html{font-size:16px}
body.lesson{background:var(--main-bg);color:var(--ink);font-family:var(--sans);line-height:1.6;transition:background .4s,color .4s;min-height:100vh}
.lesson-wrap{max-width:840px;margin:0 auto;padding:0 24px 96px}

/* ── Top bar ── */
.lesson-top{display:flex;align-items:center;justify-content:space-between;padding:18px 0;border-bottom:1px solid var(--line)}
.back-link{font-family:var(--mono);font-size:11px;color:var(--ink3);text-decoration:none;display:inline-flex;align-items:center;gap:6px}
.back-link:hover{color:var(--gold)}
.theme-btn{background:transparent;border:1px solid var(--line);color:var(--ink3);padding:6px 12px;border-radius:6px;font-family:var(--mono);font-size:10px;cursor:pointer;transition:var(--trans)}
.theme-btn:hover{border-color:var(--gold);color:var(--gold)}

/* ── Hero ── */
.lesson-hero{padding:44px 0 28px}
.lesson-eyebrow{font-family:var(--mono);font-size:10px;color:var(--gold);letter-spacing:.2em;text-transform:uppercase;margin-bottom:12px;display:flex;align-items:center;gap:10px}
.lesson-eyebrow::before{content:'';width:24px;height:1px;background:var(--gold)}
.lesson-title{font-family:var(--serif);font-weight:900;font-size:2.6rem;line-height:1.08;color:var(--ink)}
.lesson-title em{color:var(--gold);font-style:italic}
.lesson-sub{margin-top:14px;font-family:var(--body);font-style:italic;font-size:14px;color:var(--ink3);max-width:600px;line-height:1.8}

/* ── Progress rail ── */
.rail{position:sticky;top:0;z-index:50;background:var(--main-bg);padding:12px 0;border-bottom:1px solid var(--line);display:flex;align-items:center;gap:12px;margin-bottom:36px}
.rail-label{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink3)}
.rail-dots{display:flex;gap:6px;flex:1;flex-wrap:wrap}
.rail-dot{min-width:26px;height:26px;padding:0 9px;border-radius:14px;border:1px solid var(--line);background:var(--section-bg);font-family:var(--mono);font-size:10px;color:var(--ink3);cursor:pointer;transition:var(--trans)}
.rail-dot[disabled]{opacity:.35;cursor:not-allowed}
.rail-dot.done{background:rgba(45,90,61,.12);border-color:var(--emerald);color:var(--emerald)}
.rail-dot.current{border-color:var(--gold);color:var(--gold)}
.rail-pct{font-family:var(--mono);font-size:11px;color:var(--gold)}

/* ── Stage cards ── */
.stage{border:1px solid var(--line);border-radius:14px;background:var(--section-bg);box-shadow:var(--shadow);margin-bottom:28px;overflow:hidden;transition:opacity .3s}
.stage-head{padding:20px 26px;display:flex;align-items:center;gap:14px;border-bottom:1px solid var(--line2)}
.stage-num{font-family:var(--mono);font-size:10px;background:rgba(var(--accent-rgb),.12);color:var(--gold);border:1px solid rgba(var(--accent-rgb),.3);padding:4px 9px;border-radius:5px;flex-shrink:0}
.stage-title{font-family:var(--serif);font-weight:700;font-size:1.15rem;flex:1;color:var(--ink)}
.stage-status{font-family:var(--mono);font-size:10px;color:var(--ink3);flex-shrink:0}
.stage.done .stage-status{color:var(--emerald)}
.stage-body{padding:26px}
.stage.locked{opacity:.5}
.stage.locked .stage-body{display:none}
.stage p{font-size:14px;color:var(--ink2);margin:0 0 14px;font-family:var(--body);line-height:1.85}
.stage p strong{color:var(--teal);font-family:var(--sans)}

.callout{border-left:3px solid var(--gold);background:rgba(var(--accent-rgb),.06);border-radius:8px;padding:13px 16px;font-size:13px;line-height:1.75;margin:16px 0;color:var(--ink2)}
.callout.warn{border-left-color:var(--rust);background:rgba(139,58,42,.07)}
.callout h4{font-family:var(--mono);font-size:10px;letter-spacing:.12em;text-transform:uppercase;color:var(--gold);margin:0 0 6px}
.callout.warn h4{color:var(--rust)}

figure.ladder{margin:18px 0;border:1px solid var(--line);border-radius:10px;background:var(--hero-bg);padding:16px;text-align:center}
figure.ladder svg{max-width:100%;height:auto;color:var(--ink3)}
figure.ladder figcaption{font-family:var(--mono);font-size:10px;color:var(--ink3);margin-top:8px;letter-spacing:.06em}

/* ── Buttons ── */
.btn{background:var(--gold);color:#141210;border:none;padding:10px 22px;border-radius:8px;font-family:var(--mono);font-size:12px;letter-spacing:.05em;cursor:pointer;transition:var(--trans)}
.btn:hover:not(:disabled){background:var(--gold2);transform:translateY(-1px)}
.btn:disabled{opacity:.45;cursor:not-allowed}
.btn.ghost{background:transparent;border:1px solid var(--line);color:var(--ink3)}
.btn.ghost:hover:not(:disabled){border-color:var(--gold);color:var(--gold);background:transparent}
:is(button,a,input,summary):focus-visible{outline:2px solid var(--teal);outline-offset:2px}

/* ── Checkpoint (MCQ / prediction) ── */
.checkpoint{border:1px solid var(--line);border-radius:12px;background:var(--hero-bg);padding:20px;margin:20px 0}
.cp-tag{font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--gold);margin-bottom:10px}
.cp-prompt{font-size:14.5px;font-weight:500;margin-bottom:14px;line-height:1.6;color:var(--ink)}
.cp-opts{display:flex;flex-direction:column;gap:8px}
.cp-opt{display:flex;align-items:center;gap:12px;text-align:left;background:var(--section-bg);border:1px solid var(--line);border-radius:8px;padding:11px 14px;font-size:13px;color:var(--ink2);cursor:pointer;transition:var(--trans);font-family:var(--sans);width:100%}
.cp-opt:hover:not(:disabled){border-color:var(--gold);transform:translateX(3px)}
.cp-opt.selected{border-color:var(--teal);background:rgba(42,107,107,.07)}
.cp-opt.correct{border-color:var(--emerald);background:rgba(45,90,61,.1)}
.cp-opt.wrong{border-color:var(--rust);background:rgba(139,58,42,.08)}
.cp-opt:disabled{cursor:default}
.cp-letter{font-family:var(--mono);font-size:9px;border:1.5px solid var(--line);width:22px;height:22px;border-radius:50%;display:flex;align-items:center;justify-content:center;flex-shrink:0;color:var(--ink3)}
.cp-fb{display:none;margin-top:14px;border-radius:8px;padding:12px 15px;font-size:13px;line-height:1.75;color:var(--ink2)}
.cp-fb.show{display:block;animation:fadeUp .3s ease}
.cp-fb.good{background:rgba(45,90,61,.1);border:1px solid rgba(45,90,61,.3)}
.cp-fb.bad{background:rgba(139,58,42,.08);border:1px solid rgba(139,58,42,.3)}
.cp-actions{margin-top:14px;display:flex;gap:10px;flex-wrap:wrap}
@keyframes fadeUp{from{opacity:0;transform:translateY(5px)}to{opacity:1;transform:none}}

/* ── Sequence exercise ── */
.seq-answer{display:flex;flex-wrap:wrap;gap:8px;min-height:46px;border:1px dashed var(--line);border-radius:10px;padding:8px;margin-bottom:14px}
.seq-slot{font-family:var(--mono);font-size:12px;background:rgba(45,90,61,.12);border:1px solid var(--emerald);color:var(--emerald);border-radius:6px;padding:6px 12px}
.seq-pool{display:flex;flex-wrap:wrap;gap:8px}
.seq-chip{font-family:var(--mono);font-size:12px;background:var(--section-bg);border:1px solid var(--line);border-radius:6px;padding:8px 14px;cursor:pointer;color:var(--ink2);transition:var(--trans)}
.seq-chip:hover:not(:disabled){border-color:var(--gold);color:var(--gold)}
.seq-chip.placed{opacity:.3;cursor:default}
.shake{animation:shake .35s ease}
@keyframes shake{0%,100%{transform:translateX(0)}25%{transform:translateX(-5px)}75%{transform:translateX(5px)}}

/* ── Orbital builder ── */
.ob{border:1px solid var(--line);border-radius:12px;background:var(--hero-bg);padding:20px;margin:20px 0}
.ob-head{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:12px;margin-bottom:18px}
.ob-el{display:flex;align-items:center;gap:12px}
.ob-symbol{font-family:var(--serif);font-weight:900;font-size:1.5rem;width:52px;height:52px;border:1.5px solid var(--gold);border-radius:10px;display:flex;align-items:center;justify-content:center;color:var(--gold);flex-shrink:0}
.ob-elname{font-size:13px;font-weight:500;color:var(--ink)}
.ob-elz{font-family:var(--mono);font-size:10px;color:var(--ink3)}
.ob-count{font-family:var(--mono);font-size:12px;color:var(--teal)}
.ob-core{font-family:var(--mono);font-size:11px;background:rgba(42,107,107,.1);border:1px solid rgba(42,107,107,.3);color:var(--teal);padding:4px 10px;border-radius:6px}
.ob-groups{display:flex;flex-wrap:wrap;gap:18px;align-items:flex-end;margin-bottom:16px}
.ob-group{display:flex;flex-direction:column;align-items:center;gap:6px}
.ob-orbs{display:flex;gap:5px}
.ob-orb{width:44px;height:44px;border:1.5px solid var(--line);border-radius:7px;background:var(--section-bg);cursor:pointer;font-size:15px;line-height:1;display:flex;align-items:center;justify-content:center;gap:1px;color:var(--teal);transition:var(--trans);font-family:var(--mono)}
.ob-orb:hover{border-color:var(--gold)}
.ob-orb.full{background:rgba(42,107,107,.08);border-color:rgba(42,107,107,.4)}
.ob-label{font-family:var(--mono);font-size:11px;color:var(--ink3)}
.ob-readout{font-family:var(--mono);font-size:14px;background:var(--section-bg);border:1px solid var(--line);border-radius:8px;padding:10px 14px;min-height:40px;color:var(--gold)}
.ob-readout sup{font-size:9px}
.ob-fb{display:none;margin-top:12px;border-radius:8px;padding:12px 15px;font-size:13px;line-height:1.75;color:var(--ink2)}
.ob-fb.show{display:block;animation:fadeUp .25s ease}
.ob-fb.good{background:rgba(45,90,61,.1);border:1px solid rgba(45,90,61,.3)}
.ob-fb.bad{background:rgba(139,58,42,.08);border:1px solid rgba(139,58,42,.3)}
.ob-fb.info{background:rgba(var(--accent-rgb),.08);border:1px solid rgba(var(--accent-rgb),.3)}
.ob-tools{margin-top:12px;display:flex;gap:10px;flex-wrap:wrap}

/* ── Arabic hint (optional clarification) ── */
.ar-hint{margin:14px 0;border:1px solid var(--line);border-radius:8px;background:var(--section-bg)}
.ar-hint summary{cursor:pointer;padding:10px 14px;font-family:var(--mono);font-size:11px;color:var(--ink3);list-style-position:inside}
.ar-hint[open] summary{border-bottom:1px solid var(--line2);color:var(--gold)}
.ar-hint p{padding:12px 16px;font-size:13.5px;line-height:2;margin:0;color:var(--ink2)}

/* ── Mastery summary ── */
.mastery-summary{display:grid;grid-template-columns:repeat(auto-fit,minmax(140px,1fr));gap:12px;margin:18px 0}
.ms-card{border:1px solid var(--line);border-radius:10px;padding:14px;background:var(--section-bg);text-align:center}
.ms-big{font-family:var(--serif);font-weight:900;font-size:1.8rem;color:var(--gold)}
.ms-label{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink3);margin-top:4px}
.complete-card{text-align:center;padding:36px 20px;border:1px solid rgba(var(--accent-rgb),.35);border-radius:14px;background:rgba(var(--accent-rgb),.05);margin-top:8px}
.complete-card h3{font-family:var(--serif);font-weight:900;font-size:1.4rem;color:var(--ink);margin-bottom:8px}

@media(max-width:640px){
  .lesson-title{font-size:2rem}
  .stage-body{padding:20px 16px}
  .stage-head{padding:16px}
  .ob-orb{width:38px;height:38px}
}

/* ── Config Player (watch Aufbau/Hund/Pauli live) ── */
.cfgp{border:1px solid var(--line);border-radius:12px;background:var(--hero-bg);padding:18px;margin:16px 0}
.cfgp-elems{display:flex;flex-wrap:wrap;gap:6px;margin-bottom:14px}
.cfgp-chip{font-family:var(--mono);font-size:11px;padding:6px 12px;border-radius:20px;border:1px solid var(--line);background:var(--section-bg);color:var(--ink2);cursor:pointer;transition:var(--trans)}
.cfgp-chip small{color:var(--ink3);font-size:9px}
.cfgp-chip:hover{border-color:var(--gold)}
/* The active chip keeps its gold border and gold wash; only the LABEL is a
   text-safe token. --gold on a 12% accent wash measures 4.07:1 and thinning the
   wash does not rescue it (4.33:1 even at 5%), so the text had to move. Applies
   to .cfgp-chip, .dc-chip and .vs-chip alike — CLAUDE.md §12.8. */
.cfgp-chip.active{border-color:var(--gold);background:rgba(var(--accent-rgb),.12);color:var(--ink)}
.cfgp-axis{font-family:var(--mono);font-size:9px;color:var(--ink3);letter-spacing:.12em;text-transform:uppercase;margin-bottom:8px}
.cfgp-diagram{display:flex;flex-direction:column-reverse;gap:7px;padding:4px 0 10px}
.cfgp-row{display:flex;align-items:center;gap:10px}
.cfgp-lab{font-family:var(--mono);font-size:11px;color:var(--ink3);min-width:24px;text-align:right}
.cfgp-orb{width:34px;height:34px;border:1.5px solid var(--line);border-radius:6px;background:var(--section-bg);display:inline-flex;align-items:center;justify-content:center;font-family:var(--mono);font-size:13px;color:var(--teal);transition:var(--trans)}
.cfgp-orb.filled{border-color:rgba(42,107,107,.45);background:rgba(42,107,107,.07)}
.cfgp-orb.pop{animation:cfgPop .35s cubic-bezier(0.34,1.4,0.64,1)}
@keyframes cfgPop{from{transform:scale(.5)}to{transform:scale(1)}}
.cfgp-readout{font-family:var(--mono);font-size:13px;color:var(--gold);border:1px solid var(--line);border-radius:8px;background:var(--section-bg);padding:9px 13px;min-height:36px}
.cfgp-readout sup{font-size:9px}
.cfgp-narr{margin-top:10px;font-size:12.5px;line-height:1.7;color:var(--ink2);border-left:3px solid var(--gold);padding:8px 12px;background:rgba(var(--accent-rgb),.05);border-radius:6px;min-height:38px}
.cfgp-controls{display:flex;gap:8px;margin-top:12px;flex-wrap:wrap}
@media(max-width:640px){.cfgp-orb{width:29px;height:29px;font-size:11px}}
@media print{.cfgp,.checkpoint,.vsepr,.decay{display:none!important}}

/* ── Decay lab ──
   Colour tokens are explicit so protons/neutrons/particles stay legible on
   both the light plate and the dark plate. */
:root{
  --dc-proton:#b8903a;
  --dc-neutron:#2a6b6b;
  --dc-beta:#a8462f;
  --dc-plate:#fbf9f5;
}
[data-theme="dark"]{
  --dc-proton:#d8a955;
  --dc-neutron:#6fc4c4;
  --dc-beta:#e08a70;
  --dc-plate:#16130f;
}

.decay{border:1px solid var(--line);border-radius:10px;background:var(--section-bg);margin:18px 0;overflow:hidden}

/* Nuclide picker */
.dc-picker{display:flex;flex-wrap:wrap;gap:6px;padding:14px 16px;background:var(--hero-bg);border-bottom:1px solid var(--line)}
.dc-chip{
  display:flex;align-items:center;gap:8px;padding:7px 13px;
  border:1px solid var(--line);border-radius:4px;background:var(--section-bg);
  cursor:pointer;transition:var(--trans);
}
.dc-chip:hover{border-color:var(--gold-ui);transform:translateY(-1px)}
.dc-chip.active{border-color:var(--gold-ui);background:rgba(var(--accent-rgb),.12);box-shadow:inset 0 0 0 1px var(--gold-ui)}
.dc-chip-n{font-family:var(--mono);font-size:13px;color:var(--ink)}
.dc-chip.active .dc-chip-n{color:var(--ink)}
.dc-chip-m{font-family:var(--mono);font-size:11px;color:var(--ink3);border-left:1px solid var(--line);padding-left:8px}

.dc-predict{padding:0 16px}
.dc-predict:not(:empty){padding:16px}

/* Stage + panel, same split as the VSEPR viewer */
.dc-lab{display:flex;flex-direction:column}
.dc-main{display:grid;grid-template-columns:minmax(0,1.4fr) minmax(240px,1fr)}
.dc-stagewrap{position:relative;background:var(--dc-plate);border-right:1px solid var(--line);display:flex;flex-direction:column;justify-content:center}
.dc-stage{display:block;width:100%}

/* Progress of the emission, so the phase is always readable */
.dc-phase{position:absolute;left:0;right:0;bottom:0;height:2px;background:var(--line2)}
.dc-phase-fill{display:block;height:100%;width:0;background:var(--gold-ui);transition:width .08s linear}

.dc-legend{
  position:absolute;left:0;right:0;bottom:10px;display:flex;justify-content:center;gap:16px;
  font-family:var(--mono);font-size:9.5px;color:var(--ink3);pointer-events:none;
}
.dc-legend span{display:inline-flex;align-items:center;gap:5px}
.dc-k{width:9px;height:9px;border-radius:50%;display:inline-block}
.dc-k.p{background:var(--dc-proton)}
.dc-k.n{background:var(--dc-neutron)}
.dc-scale{opacity:.75}

/* Particles */
.dc-nuc{stroke:var(--dc-plate);stroke-width:1.2}
.dc-nuc.p{fill:var(--dc-proton)}
.dc-nuc.n{fill:var(--dc-neutron)}
.dc-nuc.flip{stroke:var(--gold);stroke-width:2.4}
.dc-beta{fill:var(--dc-beta)}
.dc-trail{fill:var(--ink3)}
.dc-halo{stroke:var(--gold-ui)}
.dc-gamma{stroke:var(--gold-ui);stroke-width:2}
.dc-glyph{font-family:var(--mono);font-size:14px;font-weight:600;fill:var(--dc-beta);
  paint-order:stroke;stroke:var(--dc-plate);stroke-width:3.5}

/* Panel */
.dc-panel{padding:18px 20px;background:var(--card-bg);display:flex;flex-direction:column;min-width:0}
.dc-id{padding-bottom:13px;border-bottom:1px solid var(--line)}
.dc-mode{
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--gold);border:1px solid var(--gold-ui);border-radius:3px;padding:2px 7px;
}
.dc-nuclide{font-family:var(--serif);font-size:1.6rem;font-weight:700;color:var(--ink);margin:8px 0 2px;line-height:1.1}
.dc-nuclide sup,.dc-nuclide sub{font-size:.5em;font-family:var(--mono)}
.dc-use{font-family:var(--sans);font-size:12px;color:var(--ink3);margin:0}

.dc-counts{display:grid;grid-template-columns:repeat(3,1fr);gap:8px;padding:14px 0;border-bottom:1px solid var(--line2)}
.dc-ct{display:flex;flex-direction:column;align-items:center;gap:1px;padding:8px 4px;
  border:1px solid var(--line);border-radius:4px;background:var(--hero-bg)}
.dc-ct-k{font-family:var(--mono);font-size:9px;letter-spacing:.1em;color:var(--ink3)}
.dc-ct-v{font-family:var(--serif);font-size:1.5rem;font-weight:700;color:var(--ink);line-height:1;font-variant-numeric:tabular-nums}
.dc-ct-v.tick{animation:dcTick .45s var(--ease-out)}
@keyframes dcTick{
  0%{transform:scale(1);color:var(--ink)}
  35%{transform:scale(1.25);color:var(--gold)}
  100%{transform:scale(1);color:var(--ink)}
}
.dc-ct-l{font-family:var(--mono);font-size:8.5px;color:var(--ink3);text-align:center}

.dc-sec{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink3);display:block;margin-bottom:7px}
.dc-eq{padding:13px 0;border-bottom:1px solid var(--line2)}
.dc-eq-body{
  display:block;font-family:var(--mono);font-size:14px;color:var(--ink);line-height:1.9;
  background:rgba(var(--accent-rgb),.06);border:1px solid rgba(var(--accent-rgb),.22);border-radius:4px;padding:9px 12px;
}
.dc-eq-body sup,.dc-eq-body sub{font-size:.68em}
.dc-arrow{color:var(--gold);margin:0 3px}
.dc-plus{color:var(--ink3);margin:0 2px}
.dc-emit{color:var(--dc-beta);font-weight:600}

.dc-facts{display:grid;grid-template-columns:1fr;gap:0;margin:0;padding:11px 0 0}
.dc-fact{display:flex;align-items:baseline;justify-content:space-between;gap:12px;padding:7px 0;border-bottom:1px solid var(--line2)}
.dc-fact dt{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink3);margin:0;white-space:nowrap}
.dc-fact dd{font-family:var(--mono);font-size:12px;color:var(--ink2);margin:0;text-align:right}

/* Narration + tools */
.dc-narr{
  font-family:var(--body);font-size:13px;line-height:1.7;color:var(--ink2);
  padding:12px 18px;border-top:1px solid var(--line);
  border-left:2px solid var(--gold-ui);background:rgba(var(--accent-rgb),.05);
}
.dc-live{font-family:var(--mono);font-size:12px;color:var(--gold);letter-spacing:.03em}

.dc-tools{display:flex;flex-wrap:wrap;align-items:center;gap:8px;padding:12px 16px;background:var(--hero-bg);border-top:1px solid var(--line)}
.dc-btn{
  display:inline-flex;align-items:center;gap:7px;
  font-family:var(--mono);font-size:11px;letter-spacing:.05em;padding:8px 15px;border-radius:3px;
  border:1px solid var(--line);background:var(--section-bg);color:var(--ink2);cursor:pointer;transition:var(--trans);
}
.dc-btn:hover{border-color:var(--gold-ui);color:var(--gold)}
.dc-btn.primary{border-color:var(--gold-ui);color:var(--gold);background:rgba(var(--accent-rgb),.1)}
.dc-btn.primary:hover{background:var(--gold-ui);color:var(--paper)}
.dc-btn svg{width:13px;height:13px}
.dc-btn:disabled{opacity:.45;cursor:default}

.dc-speeds{display:inline-flex;border:1px solid var(--line);border-radius:3px;overflow:hidden;margin-left:auto}
.dc-speed{
  font-family:var(--mono);font-size:10.5px;padding:7px 11px;border:none;
  background:var(--section-bg);color:var(--ink3);cursor:pointer;transition:var(--trans);
  border-right:1px solid var(--line);
}
.dc-speed:last-child{border-right:none}
.dc-speed:hover{color:var(--ink)}
.dc-speed.on{background:rgba(var(--accent-rgb),.14);color:var(--gold)}

.dc-series{padding:0 16px}
.dc-series:not(:empty){padding:16px}
.dc-series-head{margin-bottom:10px}

@media(max-width:860px){
  .dc-main{grid-template-columns:1fr}
  .dc-stagewrap{border-right:none;border-bottom:1px solid var(--line)}
}
@media(max-width:560px){
  .dc-panel{padding:16px}
  .dc-nuclide{font-size:1.4rem}
  .dc-counts{gap:6px}
  .dc-ct-v{font-size:1.25rem}
  .dc-speeds{margin-left:0}
}

/* ── VSEPR viewer ── */
/* Bond colour is an explicit token so it can never fall back to something
   invisible on a dark surface. */
:root{
  --vs-bond:#5d554a;
  --vs-bond-core:#8b8375;
  --vs-lone:#a8462f;
  --vs-domain:#2a6b6b;
  --vs-stage:#fbf9f5;
}
[data-theme="dark"]{
  --vs-bond:#b3aa9a;
  --vs-bond-core:#ded5c4;
  --vs-lone:#e08a70;
  --vs-domain:#6fc4c4;
  --vs-stage:#16130f;
}

.vsepr{border:1px solid var(--line);border-radius:10px;background:var(--section-bg);margin:18px 0;overflow:hidden}

/* Picker — grouping by steric number is the lesson, so it leads. */
.vs-picker{padding:14px 16px 6px;background:var(--hero-bg);border-bottom:1px solid var(--line)}
.vs-grow{display:flex;align-items:flex-start;gap:14px;padding:7px 0;border-bottom:1px solid var(--line2)}
.vs-grow:last-child{border-bottom:none}
.vs-glabel{display:flex;flex-direction:column;gap:1px;min-width:116px;flex-shrink:0;padding-top:3px}
.vs-glabel b{font-family:var(--mono);font-size:10px;letter-spacing:.12em;color:var(--gold);font-weight:600}
.vs-glabel i{font-family:var(--mono);font-size:9.5px;color:var(--ink3);font-style:normal;letter-spacing:.02em}
.vs-gchips{display:flex;flex-wrap:wrap;gap:5px;flex:1}
.vs-chip{
  display:flex;flex-direction:column;align-items:center;gap:1px;
  padding:5px 10px;border:1px solid var(--line);border-radius:4px;
  background:var(--section-bg);cursor:pointer;transition:var(--trans);min-width:58px;
}
.vs-chip:hover{border-color:var(--gold-ui);transform:translateY(-1px)}
.vs-chip.active{border-color:var(--gold-ui);background:rgba(var(--accent-rgb),.12);box-shadow:inset 0 0 0 1px var(--gold-ui)}
.vs-chip-f{font-family:var(--mono);font-size:12px;color:var(--ink);font-weight:500}
/* The active chip and toggle keep their gold border, gold wash and inset ring —
   only the LABEL moves to a text-safe token. --gold on a 12% accent wash caps at
   4.07:1 and cannot be rescued by thinning the wash (4.33:1 even at 5%), so the
   text is what had to change, not the background. Same fix as .btn-next and
   .flow-arrow in CLAUDE.md §12.8: keep the accent, move the text. */
.vs-chip.active .vs-chip-f{color:var(--ink)}
.vs-chip-x{font-family:var(--mono);font-size:8.5px;color:var(--ink3);letter-spacing:.04em}

/* Stage + panel */
.vs-main{display:grid;grid-template-columns:minmax(0,1.34fr) minmax(238px,1fr)}
.vs-stage{
  position:relative;background:var(--vs-stage);cursor:grab;touch-action:none;overflow:hidden;
  border-right:1px solid var(--line);min-height:320px;display:flex;align-items:center;
}
.vs-stage.grabbing{cursor:grabbing}
.vs-stage.over-domain{cursor:grab}
.vs-stage.dragging-domain{cursor:grabbing}
.vs-stage:focus-visible{outline:2px solid var(--gold-ui);outline-offset:-2px}
.vs-stage svg{display:block;width:100%}

.vs-hint{
  position:absolute;left:0;right:0;bottom:10px;text-align:center;
  font-family:var(--mono);font-size:9.5px;letter-spacing:.06em;color:var(--ink3);
  /* opacity was .85, which composited --ink3 down to 3.88:1. At full strength it
     is 5.30:1; the quietness comes from the 9.5px size and the letter-spacing.
     The property stays because .vs-stage.dragging-domain sets it to 0. */
  pointer-events:none;opacity:1;transition:opacity .3s var(--ease);
}
.vs-stage.dragging-domain .vs-hint,.vs-stage.grabbing .vs-hint{opacity:0}

.vs-cam{position:absolute;right:10px;top:10px;display:flex;flex-direction:column;gap:4px}
.vs-cambtn{
  width:28px;height:28px;display:flex;align-items:center;justify-content:center;
  border:1px solid var(--line);border-radius:3px;background:var(--section-bg);
  color:var(--ink2);cursor:pointer;font-family:var(--mono);font-size:13px;line-height:1;
  transition:var(--trans);
}
.vs-cambtn:hover{border-color:var(--gold-ui);color:var(--gold)}
.vs-cambtn svg{width:13px;height:13px}

/* Molecule graphics */
.vs-bond{stroke:var(--vs-bond);stroke-linecap:round}
.vs-bond-core{stroke:var(--vs-bond-core);stroke-linecap:round}
.vs-halo{fill:none;stroke:var(--gold-ui);stroke-width:2}
.vs-e{fill:var(--vs-lone)}
.vs-atom,.vs-lone{transition:none}
.vs-arc{fill:none;stroke:var(--gold-ui);stroke-width:1.7;stroke-dasharray:4 3}
.vs-arc-label{
  font-family:var(--mono);font-size:13px;font-weight:600;fill:var(--gold);
  paint-order:stroke;stroke:var(--vs-stage);stroke-width:3.5;
}
.vs-dip{stroke:var(--gold);stroke-width:2.6}
.vs-muzero{font-family:var(--mono);font-size:12.5px;fill:var(--ink3)}

/* ── Panel: one answer first, supporting data after ── */
.vs-panel{padding:18px 20px;display:flex;flex-direction:column;gap:0;min-width:0;background:var(--card-bg)}

.vs-id{display:flex;flex-direction:column;align-items:flex-start;gap:2px;padding-bottom:14px;border-bottom:1px solid var(--line)}
.vs-axe{
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;color:var(--gold);
  border:1px solid var(--gold-ui);border-radius:3px;padding:2px 7px;
}
.vs-formula{font-family:var(--serif);font-size:1.65rem;font-weight:700;color:var(--ink);line-height:1.1;margin:6px 0 0}
.vs-name{font-family:var(--sans);font-size:12.5px;color:var(--ink3);margin:0}

.vs-headline{display:flex;flex-direction:column;gap:3px;padding:14px 0;border-bottom:1px solid var(--line2)}
.vs-hl-label{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink3)}
.vs-hl-value{font-family:var(--serif);font-size:1.3rem;font-weight:700;color:var(--gold);line-height:1.15}

/* Domain census as marks, not a crowded sentence. */
.vs-domains{padding:13px 0;border-bottom:1px solid var(--line2)}
.vs-sec-label{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink3);display:block;margin-bottom:8px;
}
.vs-drow{display:flex;flex-wrap:wrap;gap:14px}
.vs-dgroup{display:flex;align-items:center;gap:7px}
.vs-dchips{display:flex;gap:3px}
.vs-dc{width:10px;height:10px;border-radius:50%;display:block}
.vs-dc.bond{background:var(--vs-domain);border:1px solid var(--vs-domain)}
.vs-dc.lone{background:hsl(0 0% 0% / 0);border:1.5px solid var(--vs-lone);position:relative}
.vs-dlabel{font-family:var(--mono);font-size:10.5px;color:var(--ink2)}

.vs-facts{display:grid;grid-template-columns:1fr 1fr;gap:0 18px;margin:0;padding:12px 0 4px}
.vs-fact{display:flex;flex-direction:column;gap:2px;padding:7px 0;border-bottom:1px solid var(--line2)}
.vs-fact dt{font-family:var(--mono);font-size:9px;letter-spacing:.1em;text-transform:uppercase;color:var(--ink3);margin:0}
.vs-fact dd{font-family:var(--mono);font-size:12.5px;color:var(--ink2);margin:0}

.vs-measure{display:flex;align-items:baseline;justify-content:space-between;gap:10px;padding:12px 0}
.vs-measure .vs-sec-label{margin:0}
.vs-measure-val{
  font-family:var(--mono);font-size:1.15rem;font-weight:600;color:var(--ink);
  font-variant-numeric:tabular-nums;transition:color .2s var(--ease);
}
.vs-measure-val.off-ideal{color:var(--rust)}

.vs-note{
  font-family:var(--body);font-size:12.5px;line-height:1.7;color:var(--ink2);
  border-left:2px solid var(--gold-ui);padding:9px 13px;background:rgba(var(--accent-rgb),.05);
  border-radius:0 4px 4px 0;margin:auto 0 0;
}

.vs-toggles{display:flex;flex-wrap:wrap;gap:5px;padding:12px 16px;background:var(--hero-bg);border-top:1px solid var(--line)}
.vs-tog{
  font-family:var(--mono);font-size:10px;letter-spacing:.06em;padding:6px 12px;border-radius:3px;
  border:1px solid var(--line);background:var(--section-bg);color:var(--ink3);cursor:pointer;transition:var(--trans);
}
.vs-tog:hover{border-color:var(--gold-ui);color:var(--ink2)}
.vs-tog.on{border-color:var(--gold-ui);background:rgba(var(--accent-rgb),.12);color:var(--ink2)}

@media(max-width:860px){
  .vs-main{grid-template-columns:1fr}
  .vs-stage{border-right:none;border-bottom:1px solid var(--line);min-height:300px}
  .vs-glabel{min-width:100px}
}
@media(max-width:560px){
  .vs-grow{flex-direction:column;gap:5px}
  .vs-glabel{flex-direction:row;align-items:baseline;gap:7px;min-width:0}
  .vs-panel{padding:16px}
  .vs-formula{font-size:1.45rem}
  .vs-facts{grid-template-columns:1fr}
}

/* Exception marker on element chips — a typographic asterisk, not a pictogram. */
.cfgp-flag{color:var(--gold);font-weight:600;margin-left:2px;vertical-align:super;font-size:.8em}

/* Long geometry names ("Trigonal Bipyramidal") must wrap rather than run past
   the panel edge on narrow screens. */
.vs-fact{flex-wrap:wrap}
.vs-fact dd{flex:1 1 auto;min-width:0;word-break:break-word}
@media(max-width:560px){
  .vs-fact{flex-direction:column;align-items:flex-start;gap:2px}
  .vs-fact dd{text-align:left}
}

/* ── VSEPR reference table ──
   Grouped by steric number so each block reads as one parent geometry
   losing bonds to lone pairs, rather than 13 unrelated rows. */
.vsepr-table{width:100%;border-collapse:collapse}
.vsepr-table caption{
  caption-side:top;text-align:left;padding:0 0 10px;
  font-family:var(--body);font-size:12.5px;font-style:italic;color:var(--ink3);line-height:1.6;
}
.vsepr-table th[scope="col"]{
  font-family:var(--mono);font-size:9px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--ink3);text-align:left;padding:9px 12px;background:var(--cream2);
  border-bottom:1px solid var(--line);font-weight:400;white-space:nowrap;
}
.vsepr-table td{padding:9px 12px;border-bottom:1px solid var(--line2);vertical-align:middle}

/* Steric-number spine */
.vsr-sn{
  vertical-align:top;padding:11px 14px 11px 12px;text-align:left;
  border-bottom:1px solid var(--line);border-right:1px solid var(--line);
  background:var(--hero-bg);white-space:nowrap;
}
.vsr-n{
  display:block;font-family:var(--serif);font-size:1.35rem;font-weight:700;
  color:var(--gold);line-height:1;
}
.vsr-g{
  display:block;font-family:var(--mono);font-size:9px;letter-spacing:.06em;
  color:var(--ink3);margin-top:3px;
}
.vsr-first td{border-top:1px solid var(--line)}

.vsr-count{font-family:var(--mono);font-size:13px;color:var(--ink2);font-variant-numeric:tabular-nums;width:1%}
.vsr-count.has-lone{color:var(--rust);font-weight:600}
.vsr-shape{font-family:var(--sans);font-size:var(--fs-sm);color:var(--ink);font-weight:500}
.vsr-angle{font-family:var(--mono);font-size:12.5px;color:var(--ink2);white-space:nowrap}
.vsr-eg{font-family:var(--mono);font-size:13px;color:var(--gold)}
.vsepr-table tbody tr:hover td{background:rgba(var(--accent-rgb),.05)}

@media(max-width:620px){
  .vsepr-table th[scope="col"],.vsepr-table td{padding:8px 9px}
  .vsr-g{display:none}
  .vsr-shape{font-size:13px}
}

/* ═══ Range controls — hit area ═══════════════════════════════════════════
   Every engine that has a slider drew it 16 px tall, which is what the
   browser gives a bare `input[type=range]`. WCAG 2.2 Target Size (Minimum)
   asks for 24 CSS px, and a 16 px grab handle on a phone is genuinely hard
   to catch even where the rule allows it.

   Setting a height grows the INPUT, not the track: with `accent-color` in
   play the browser still paints its thin native track centred in the box, so
   the control looks identical and the area you can actually hit is 28 px.
   Measured before and after: 16 → 28, accent unchanged. */
.gl input[type=range],
.sl input[type=range],
.dl input[type=range],
.pl input[type=range] {
  height: 28px;
}

/* ═══════════════════════════════════════════════════════════════════════
   STRUCTURE LAB — ChemLab.StructureLab

   Component tokens, local on purpose: delete the engine and its palette goes
   with it, the arrangement the periodic table already uses.

   The three hybridization colours are CATEGORICAL — they name a kind, not a
   quantity — so they are chosen for distinguishability rather than taken from
   the module accent, and each holds its own value per theme. The figure sits
   on the CREAM page, not on a dark panel, so these are measured against
   --paper, unlike the sidebar, formula-box and mind-map tokens which are not
   (bug #26, §12.7).

   WHAT MAKES IT READ AS A PLATE RATHER THAN A BOX

   The same three moves that turned the mind map from a file tree into a map
   (§12.7), because they are the ones that actually do the work:

     · a hairline of light along the top edge, so the surface has a thickness
     · an inner frame inset a few pixels, so the panel has an edge of its own
       rather than only the border of its container
     · TWO washes rather than one flat ground — the accent pooling at the
       bottom, a cool lift from the top-left. A single flat fill reads as a
       container; two read as a surface with light falling on it.

   Colour only below the drawing: RDKit returns a finished SVG with its own
   geometry, and restyling its internals from here would fight the renderer
   and lose. That was the lesson of the three hand-rolled versions it replaced.
   ═══════════════════════════════════════════════════════════════════════ */
.sl{
  --sl-sp3:#9a6636;  --sl-sp2:#1d6a63;  --sl-sp:#7a4a86;
  --sl-el-o:#b0442c; --sl-el-n:#2b5fa8; --sl-el-s:#8a6a12; --sl-el-x:#6b7280;
  --sl-plate:color-mix(in srgb, var(--paper) 92%, var(--ink) 8%);
  --sl-edge:color-mix(in srgb, var(--paper) 55%, #fff 45%);
  position:relative;margin:30px 0;padding:0;border:1px solid var(--line);
  border-radius:18px;background:var(--paper);overflow:hidden;box-shadow:var(--shadow);
}
/* the hairline of light along the top edge */
.sl::before{content:'';position:absolute;inset:0 0 auto 0;height:1px;
  background:linear-gradient(90deg,transparent,var(--sl-edge) 18%,var(--sl-edge) 82%,transparent);
  opacity:.85;pointer-events:none;z-index:2}
/* two washes: the accent pooling low, a cool lift from the top-left */
.sl::after{content:'';position:absolute;inset:0;pointer-events:none;z-index:0;
  background:
    radial-gradient(120% 68% at 50% 118%, color-mix(in srgb,var(--gold-ui) 13%,transparent), transparent 70%),
    radial-gradient(90% 60% at 6% -8%, color-mix(in srgb,var(--paper) 60%,#fff 40%), transparent 62%)}
.sl > *{position:relative;z-index:1}

[data-theme="dark"] .sl{
  /* Not an inversion — a light-on-dark accent needs RAISING to stay legible
     (§6.8), so these are lifted rather than uniformly lightened. */
  --sl-sp3:#e0a86a; --sl-sp2:#6fc9bf; --sl-sp:#c79bd4;
  --sl-el-o:#f0806a; --sl-el-n:#8ab4f0; --sl-el-s:#e0c060; --sl-el-x:#a8b0bb;
  --sl-edge:color-mix(in srgb, var(--paper) 72%, #fff 28%);
}

/* ── header ── */
.sl-head{display:flex;align-items:baseline;gap:13px;flex-wrap:wrap;
  padding:19px 24px 15px;border-bottom:1px solid var(--line)}
.sl-kicker{font-family:var(--mono);font-size:9px;letter-spacing:.26em;
  text-transform:uppercase;color:var(--ink3)}
.sl-kicker::after{content:'';display:inline-block;width:16px;height:1px;
  background:var(--gold-ui);vertical-align:middle;margin-left:9px;opacity:.7}
/* The display face, at a size that reads as a title. A molecule's name in
   12px mono is a filename; in the serif it is the subject of the panel. */
.sl-name{font-family:var(--serif);font-size:1.34rem;font-weight:700;
  letter-spacing:-.012em;color:var(--ink)}
.sl-formula{font-family:var(--mono);font-size:12.5px;color:var(--gold);
  margin-left:auto;letter-spacing:.02em}

/* ── picker ── */
.sl-picker{display:flex;flex-wrap:wrap;align-items:center;gap:6px;
  padding:15px 24px;border-bottom:1px solid var(--line)}
.sl-group{font-family:var(--mono);font-size:8.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--ink3);margin:0 5px 0 12px;flex-shrink:0;display:flex;align-items:center;gap:7px}
.sl-group::after{content:'';width:12px;height:1px;background:var(--line);display:block}
.sl-group:first-child{margin-left:0}
.sl-pick{font-family:var(--sans);font-size:11.5px;padding:6px 12px;min-height:31px;
  border-radius:999px;cursor:pointer;border:1px solid var(--line);
  background:transparent;color:var(--ink2);
  transition:transform .16s cubic-bezier(.2,.7,.3,1),border-color .16s,color .16s,background .16s}
.sl-pick:hover{border-color:var(--gold);color:var(--gold);transform:translateY(-1px)}
/* --gold, never --gold-ui. The decorative half is a mid tone in BOTH themes,
   so nothing about it flips to rescue text on it — measured at 3.45:1 when
   that mistake was made in the module 3 labs. */
.sl-pick.is-on{background:var(--gold);border-color:var(--gold);color:var(--paper);
  font-weight:600;transform:none}

/* ── the two columns ── */
.sl-main{display:grid;grid-template-columns:1fr 300px;align-items:stretch}
.sl-stage{position:relative;padding:14px;background:var(--sl-plate);min-width:0;
  display:flex;align-items:center;justify-content:center;min-height:250px}
/* the inner frame — an edge of its own, not just the container's border */
.sl-stage::before{content:'';position:absolute;inset:9px;border-radius:10px;
  border:1px solid color-mix(in srgb,var(--line) 60%,transparent);pointer-events:none}
.sl-side{border-left:1px solid var(--line);padding:18px 18px 20px;min-width:0}

/* ── the figure ──
   Drawn by RDKit, which returns a complete SVG with its geometry and colours
   already resolved from the palette we handed it. Only the box is styled here.
   The fade is on the FIGURE, not the stage, so switching molecules reads as
   one thing replacing another rather than the panel blinking. */
.sl-rdkit{width:100%;height:auto;display:block;max-height:280px;margin:0 auto;
  animation:sl-fig .34s cubic-bezier(.2,.7,.3,1) both}
@keyframes sl-fig{from{opacity:0;transform:scale(.965)}to{opacity:1;transform:none}}
/* RDKit marks every element atom-N / bond-N, which is what the click handler
   matches on. The cursor is the only hint that they are targets. */
.sl-rdkit [class*="atom-"],.sl-rdkit [class*="bond-"]{cursor:pointer}
.sl-wait{font-family:var(--mono);font-size:10.5px;line-height:1.9;color:var(--ink3);
  text-align:center;padding:40px 16px}
.sl-wait::after{content:'';display:block;width:26px;height:1px;margin:14px auto 0;
  background:var(--gold-ui);animation:sl-wait 1.3s ease-in-out infinite}
@keyframes sl-wait{0%,100%{opacity:.25;transform:scaleX(.4)}50%{opacity:1;transform:scaleX(1)}}

/* ── side panel ── */
.sl-panel{display:flex;flex-direction:column;gap:15px}
.sl-sec{display:flex;flex-direction:column;gap:7px}
.sl-h5{font-family:var(--mono);font-size:8.5px;letter-spacing:.22em;text-transform:uppercase;
  color:var(--ink3);display:flex;align-items:center;gap:8px;margin:0}
.sl-h5::after{content:'';flex:1;height:1px;
  background:linear-gradient(90deg,var(--line),transparent)}

/* Each row arrives a beat after the one above. --d is set per row in the
   markup; the global prefers-reduced-motion guard in tokens.css turns the
   whole thing into an instant state, which is right for a 6px move. */
.sl-grp,.sl-row{animation:sl-in .32s cubic-bezier(.2,.7,.3,1) both;animation-delay:var(--d,0ms)}
@keyframes sl-in{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}

.sl-grp{display:flex;flex-direction:column;gap:2px;padding:8px 11px;border-radius:9px;
  background:var(--sl-plate);border-left:2px solid var(--gold-ui)}
.sl-grp-name{font-family:var(--sans);font-size:12.5px;font-weight:700;color:var(--ink)}
.sl-grp-note{font-family:var(--sans);font-size:10.5px;line-height:1.55;color:var(--ink3)}

.sl-row{display:flex;align-items:center;gap:8px;flex-wrap:wrap;
  font-family:var(--mono);font-size:10.5px;color:var(--ink2)}
.sl-row b{font-family:var(--sans);font-size:12.5px;color:var(--ink);min-width:24px}
.sl-chip{width:9px;height:9px;border-radius:2px;flex-shrink:0}
.sl-chip.sl-hyb-sp3{background:var(--sl-sp3)}
.sl-chip.sl-hyb-sp2{background:var(--sl-sp2)}
.sl-chip.sl-hyb-sp{background:var(--sl-sp)}
.sl-n{min-width:34px}
.sl-ang{color:var(--gold)}
.sl-shape{color:var(--ink3);width:100%;padding-left:17px;font-size:9.5px}

/* Set numerals — a figure in the display face reads as a value; the same
   idiom the section markers and the mind map's branch numbers use. */
.sl-stats{display:grid;grid-template-columns:repeat(2,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:10px;overflow:hidden}
.sl-stat{background:var(--paper);padding:9px 11px;display:flex;flex-direction:column;gap:1px}
.sl-stat b{font-family:var(--serif);font-size:1.08rem;font-weight:700;color:var(--ink);
  line-height:1.15;font-variant-numeric:lining-nums tabular-nums}
.sl-stat span{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink3)}

/* The degree of unsaturation gets the largest number on the panel, because
   it is the one a reader is asked to compute and then go looking for. */
.sl-dou{display:flex;align-items:center;gap:12px;padding:11px 13px;border-radius:11px;
  background:var(--sl-plate);border:1px solid var(--line)}
.sl-dou-v{font-family:var(--serif);font-size:1.86rem;font-weight:900;line-height:1;
  color:var(--gold);font-variant-numeric:lining-nums tabular-nums;flex-shrink:0}
.sl-dou-b{display:flex;flex-direction:column;gap:2px;min-width:0}
.sl-dou-t{font-family:var(--sans);font-size:11.5px;font-weight:700;color:var(--ink)}
.sl-dou-w{font-family:var(--mono);font-size:9px;line-height:1.6;color:var(--ink3)}
.sl-dou-w b{color:var(--gold)}
/* If the two routes ever disagree, the parser or the valence model is wrong,
   and the panel says so rather than printing a number nobody can trust. */
.sl-dou.is-off{border-color:var(--sl-el-o)}
.sl-dou.is-off .sl-dou-v{color:var(--sl-el-o)}

.sl-back{align-self:flex-start;font-family:var(--mono);font-size:9px;letter-spacing:.1em;
  padding:6px 10px;min-height:28px;border-radius:7px;cursor:pointer;
  border:1px solid var(--line);background:transparent;color:var(--ink3);transition:var(--trans)}
.sl-back:hover{border-color:var(--gold);color:var(--gold)}
.sl-sub{font-family:var(--serif);font-size:1.06rem;font-weight:700;color:var(--ink);
  display:flex;align-items:center;gap:8px;margin:2px 0}
.sl-kv{display:flex;justify-content:space-between;gap:10px;
  font-family:var(--mono);font-size:10px;color:var(--ink3);
  padding:5px 0;border-bottom:1px solid var(--line2,var(--line))}
.sl-kv b{color:var(--ink);font-family:var(--sans);font-size:11.5px}

/* ── torsion view ── */
.sl-tor{position:relative;background:var(--sl-plate);border:1px solid var(--line);
  border-radius:11px;padding:7px;margin:5px 0}
.sl-tor-svg{width:100%;height:auto;display:block}
/* No opacity. At .5 the axis measured 2.09:1 — under the 3:1 floor for a
   graphic that carries meaning, and this one draws the line between the front
   atom and the back one. --ink3 is calibrated to pass at full strength. */
.sl-tor-axis{fill:none;stroke:var(--ink3);stroke-width:1.7}
.sl-tor-hub{fill:var(--ink)}
/* Newman convention, and it is doing real work here: the FRONT atom's bonds
   meet at the hub and read as nearer, the BACK atom's emerge from the circle
   and read as further. Weight carries the same message as position. */
.sl-tor-stub{stroke:var(--ink);stroke-width:2.4;stroke-linecap:round}
.sl-tor-back-s .sl-tor-stub{stroke:var(--ink3);stroke-width:1.9}

/* BOTH orbitals are the same colour and the same alpha, because they are the
   same kind of orbital. Where they cross, the alpha stacks and the region
   darkens on its own — that dark patch IS the overlap, and it shrinks to
   nothing as the angle opens. A separate swatch would be a second thing to
   believe; this one cannot disagree with the geometry because it is it. */
/* A TRANSLUCENT FILL WITH A SOLID OUTLINE, and both halves are load-bearing.

   The fill has to stay translucent — the overlap darkening depends on the
   alpha stacking, and that darkening is the whole point of the figure. But a
   translucent fill alone measured 1.61:1 against the plate, far under the 3:1
   floor for a graphic that carries meaning, and these lobes ARE the meaning.

   So the outline carries the contrast at full strength and the fill carries
   the overlap. Same split that rescued the hybridization marker, arrived at
   the same way: by measuring rather than by looking. */
.sl-tor-lobe{fill:var(--sl-sp2);stroke:var(--sl-sp2);stroke-width:1.4}
.sl-tor-orb .sl-tor-lobe{fill-opacity:.3}
/* The back orbital is dashed — position already says which is which in a
   Newman projection, and a second cue costs nothing and helps at a glance. */
.sl-tor-orb.is-back .sl-tor-lobe{stroke-dasharray:5 3.5}
/* Transform only — a transition on a geometry attribute is not composited, so
   it would jank on the very drag it exists to smooth. */
.sl-tor-orb,.sl-tor-back-s{transition:transform .12s linear}

.sl-tor-arc{fill:none;stroke:var(--gold);stroke-width:1.6;stroke-linecap:round;opacity:.9}
.sl-tor-lab{font-family:var(--mono);font-size:10px;fill:var(--gold);letter-spacing:.04em}

.sl-slider{display:flex;align-items:center;gap:10px;font-family:var(--mono);font-size:9px;
  color:var(--ink3);letter-spacing:.12em;text-transform:uppercase}
.sl-slider input{flex:1;min-width:0;accent-color:var(--gold);min-height:24px;cursor:pointer}
.sl-readout{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;
  background:var(--line);border:1px solid var(--line);border-radius:9px;overflow:hidden}
.sl-readout span{background:var(--paper);padding:7px 9px;display:flex;flex-direction:column;gap:1px;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.12em;text-transform:uppercase;color:var(--ink3)}
.sl-readout b{font-family:var(--serif);font-size:1rem;color:var(--ink);
  font-variant-numeric:lining-nums tabular-nums;letter-spacing:0;text-transform:none}

.sl-note{font-family:var(--sans);font-size:.8rem;line-height:1.62;
  padding:10px 12px;border-radius:9px;border-left:2px solid var(--ink3);
  background:var(--sl-plate);color:var(--ink2)}
.sl-note b{color:var(--ink)}
.sl-note.ok{border-left-color:var(--sl-sp2)}
.sl-note.warn{border-left-color:var(--sl-el-o)}
/* NO opacity on either of these, and that was a measured fix.

   --ink3 is calibrated to pass on this ground at FULL strength — 6.43:1 light,
   5.92:1 dark. Fading it to .8 and .6 dropped the hint to 4.04 and the credit
   to 2.67, both under the 4.5 floor, and the hint is an instruction rather
   than decoration. Quietness comes from size, letter-spacing and case here;
   an opacity that lands text under the floor is not quiet, it is unreadable.
   Contrast has to be measured with the opacity composited in — reading the
   colour alone reports a pass that the eye does not get. */
.sl-hint{font-family:var(--mono);font-size:9px;line-height:1.7;color:var(--ink3)}

/* ── toggles ── */
.sl-toggles{display:flex;gap:7px;flex-wrap:wrap;align-items:center;
  padding:14px 24px;border-top:1px solid var(--line)}
.sl-tog{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;
  padding:8px 13px;min-height:32px;border-radius:8px;cursor:pointer;
  border:1px solid var(--line);background:transparent;color:var(--ink3);
  transition:transform .16s cubic-bezier(.2,.7,.3,1),border-color .16s,color .16s,background .16s}
.sl-tog:hover{border-color:var(--gold);color:var(--gold);transform:translateY(-1px)}
.sl-tog.is-on{background:var(--gold);border-color:var(--gold);color:var(--paper);transform:none}
/* The credit is the quietest thing in the component on purpose — the same
   treatment the builder's mark gets in the platform footer (§16). */
.sl-credit{font-family:var(--mono);font-size:8.5px;letter-spacing:.18em;text-transform:uppercase;
  color:var(--ink3);margin-left:auto}

/* The side panel goes below the figure rather than beside it — a 300px column
   in a phone-width page is not a column, it is a crush. */
@media (max-width:760px){
  .sl-main{grid-template-columns:1fr}
  .sl-side{border-left:0;border-top:1px solid var(--line)}
  .sl-formula{margin-left:0}
  .sl-stage{min-height:200px}
}
@media (max-width:480px){
  .sl-head,.sl-picker,.sl-toggles{padding-left:15px;padding-right:15px}
  .sl-group{margin-left:0}
  .sl-name{font-size:1.18rem}
  .sl-credit{margin-left:0;width:100%}
}

/* ── Position lab (Module 1, Lecture 2 §04) ──────────────────────────────
   Every colour is a token. The panel sits on the PAGE surface, not on a dark
   plate, so page tokens are the correct ones here — the trap recorded against
   the sidebar, the formula box and the mind map does not apply, and this
   comment exists so nobody "fixes" it toward --*-on-dark by reflex. */
.pl-lab{border:1px solid var(--line);border-radius:12px;background:var(--card-bg);overflow:hidden;margin-top:6px}
.pl-head{display:flex;flex-wrap:wrap;align-items:center;gap:10px;padding:14px 16px;border-bottom:1px solid var(--line);background:var(--section-bg)}
.pl-tag{font-family:var(--mono);font-size:9px;letter-spacing:.16em;text-transform:uppercase;color:var(--gold);flex-shrink:0}
.pl-chips{display:flex;flex-wrap:wrap;gap:5px;flex:1 1 auto}
.pl-chip{font-family:var(--mono);font-size:11.5px;min-width:34px;padding:5px 8px;border:1px solid var(--line);border-radius:6px;background:var(--paper);color:var(--ink2);cursor:pointer;transition:var(--trans)}
.pl-chip:hover{border-color:var(--gold);color:var(--gold)}
.pl-step{display:flex;align-items:center;gap:8px;flex-shrink:0}
.pl-arrow{width:26px;height:26px;border:1px solid var(--line);border-radius:50%;background:var(--paper);color:var(--ink2);cursor:pointer;font-size:14px;line-height:1;transition:var(--trans)}
.pl-arrow:hover{border-color:var(--gold);color:var(--gold)}
.pl-zlabel{font-family:var(--mono);font-size:11px;color:var(--ink3);letter-spacing:.05em}
.pl-body{display:flex;flex-wrap:wrap;gap:16px;padding:16px;align-items:stretch}
.pl-card{flex:0 0 108px;border:1px solid var(--line2);border-radius:10px;padding:12px;text-align:center;background:var(--section-bg);display:flex;flex-direction:column;justify-content:center}
.pl-sym{font-family:var(--serif);font-size:2.6rem;line-height:1;color:var(--gold)}
.pl-name{font-family:var(--sans);font-size:11px;color:var(--ink3);margin-top:6px;letter-spacing:.04em}
.pl-cfg{flex:1 1 220px;min-width:0;display:flex;flex-direction:column;justify-content:center}
.pl-cfg-label{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink3);margin-bottom:7px}
.pl-cfg-text{font-family:var(--mono);font-size:13.5px;line-height:1.85;color:var(--ink);word-break:break-word}
.pl-flag:not(:empty){margin-top:9px;font-size:11.5px;line-height:1.6;color:var(--rust);border-left:2px solid var(--rust);padding-left:9px}
.pl-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:1px;background:var(--line);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.pl-cell{background:var(--card-bg);padding:13px 15px}
.pl-cell-k{font-family:var(--mono);font-size:9px;letter-spacing:.14em;text-transform:uppercase;color:var(--ink3)}
.pl-cell-v{font-family:var(--serif);font-size:1.5rem;line-height:1.2;color:var(--ink);margin:4px 0 5px}
.pl-cell-w{font-size:11.5px;line-height:1.55;color:var(--ink3)}
.pl-levels{padding:15px 16px}
.pl-lvl{display:flex;flex-wrap:wrap;align-items:baseline;gap:10px;padding:8px 11px;border:1px solid var(--line);border-left-width:3px;border-left-color:var(--rust);border-radius:7px;margin-bottom:6px;background:var(--section-bg)}
.pl-lvl.is-full{border-left-color:var(--emerald)}
.pl-lvl-n{font-family:var(--mono);font-size:12px;color:var(--ink2);flex-shrink:0}
.pl-lvl-s{font-size:11.5px;font-weight:600;color:var(--rust);flex-shrink:0}
.pl-lvl.is-full .pl-lvl-s{color:var(--emerald)}
.pl-lvl-w{font-size:11.5px;color:var(--ink3);line-height:1.5}
.pl-valence{margin-top:10px;font-size:12.5px;color:var(--ink2);line-height:1.6}
.pl-valence strong{font-family:var(--mono);color:var(--gold);font-size:14px}
.pl-valence span{color:var(--ink3)}
.pl-note:not(:empty){margin:0 16px 16px;padding:12px 14px;border:1px solid var(--line2);border-radius:9px;background:var(--section-bg);font-size:12.5px;line-height:1.72;color:var(--ink2)}
@media (max-width:560px){
  .pl-head{gap:8px}
  .pl-body{padding:13px}
  .pl-card{flex:0 0 100%}
  .pl-sym{font-size:2.2rem}
}
