/* ============================================================
   ChemLab — Experimental Chemistry interactive suite
   Shared stylesheet for hub, concepts page and all sims.
   ============================================================ */

:root {
  --cream: #f5f2ea;
  --paper: #fdfcf8;
  --ink: #2b3947;
  --ink-soft: #5b6b7c;
  --navy: #33506d;
  --navy-deep: #2a4058;
  --blue: #4a9fe3;
  --blue-soft: #dcecfa;
  --amber: #e8a13c;
  --green: #4caf7d;
  --red: #e05a4e;
  --purple: #7a4fb0;
  --card-shadow: 0 6px 24px rgba(43, 57, 71, 0.10), 0 2px 6px rgba(43, 57, 71, 0.08);
  --radius: 16px;
  font-size: 16px;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--cream);
  color: var(--ink);
  font-family: "Segoe UI", system-ui, -apple-system, "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { font-weight: 700; letter-spacing: -0.01em; }

a { color: var(--navy); }

button {
  font: inherit;
  border: none;
  cursor: pointer;
  border-radius: 10px;
  padding: 8px 14px;
  background: #e8e4d8;
  color: var(--ink);
  transition: transform .12s ease, box-shadow .12s ease, background .12s ease;
}
button:hover { transform: translateY(-1px); box-shadow: 0 3px 10px rgba(43,57,71,.15); }
button:active { transform: translateY(0); }
button.primary { background: var(--navy); color: #fff; }
button.primary:hover { background: var(--navy-deep); }

/* ---------------- Top bar (sim pages) ---------------- */

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 10px 20px;
  background: var(--paper);
  border-bottom: 1px solid #e6e1d3;
  position: sticky;
  top: 0;
  z-index: 30;
}
/* the title yields to the controls: it truncates rather than pushing them onto a
   second and third row (the full title is in the browser tab anyway) */
.topbar h1 {
  font-size: 1.05rem; margin: 0;
  flex: 1 1 120px; min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* The mode badge (Version A / B) used to be the FIRST thing dropped when space got
   tight, so two tabs of the same year became indistinguishable and the heading
   ellipsised mid-word ("auto-…"). Shorten the descriptive part instead and keep
   the year and the mode — those are what tell you where you are. */
@media (max-width: 1500px) {
  .topbar h1 { flex: 1 1 240px; }
  .topbar h1 span { font-size: .62em; }
  .topbar h1 .h1-sub { display: none; }
}
.topbar .back {
  text-decoration: none;
  font-weight: 600;
  color: var(--ink-soft);
  white-space: nowrap;
}
.topbar .back:hover { color: var(--navy); }
/* The bar carries a lot of controls (pause, speed, timer, paper, notes, demo…), so
   they are deliberately compact — otherwise they wrap and push the title onto
   three lines. Smaller type + tighter padding keeps the whole bar one row. */
/* flex:none so the controls keep their natural width and the TITLE gives way
   (it truncates) — otherwise the title grows and pushes buttons onto a second row */
.topbar .actions { display: flex; align-items: center; gap: 5px; flex: none; flex-wrap: wrap; justify-content: flex-end; }
.topbar .actions button {
  padding: 5px 9px;
  font-size: .8rem;
  border-radius: 8px;
  white-space: nowrap;
}
@media (max-width: 1100px) {
  .topbar .actions button { padding: 4px 7px; font-size: .75rem; }
  .topbar h1 { font-size: .95rem; }
}

/* auto-demo speed slider (shown only while a demo is running) */
.demo-speed { display: inline-flex; align-items: center; gap: 6px; font-size: .8rem; color: var(--ink-soft); }
.demo-speed[hidden] { display: none; }
.demo-speed input[type="range"] { width: 78px; accent-color: var(--navy); cursor: pointer; }
.demo-speed-val { min-width: 2.6em; text-align: right; font-variant-numeric: tabular-nums; }

/* ---------------- Sim layout ---------------- */

.layout {
  display: flex;
  gap: 18px;
  padding: 18px;
  /* Was capped at 1500px while the notebook below sat in its own 1560px container,
     so on a large monitor the bench + STEPS row floated in the middle of the screen
     with the notebook visibly wider underneath. Both rows now span the window with
     the same 18px side padding, so their edges line up at every size. */
  max-width: none;
  margin: 0 auto;
  align-items: flex-start;
}

#stage-wrap {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  overflow: hidden;
  /* reserved caption strip below the canvas so the instruction banner sits
     under the scene instead of overlapping the drawn lab bench */
  padding-bottom: 80px;
}
#stage {
  display: block;
  width: 100%;
  height: auto;
  /* _resize() may size the canvas narrower than the wrap (it never scales the scene
     above natural size, and it fits the viewport height) — keep it centred. */
  margin-inline: auto;
  /* Was `none`, which handed EVERY touch to the canvas — a swipe over empty bench
     space never scrolled the page down to the notebook, and the lab felt like a trap
     on a phone. `pan-y pinch-zoom` leaves vertical scrolling and zooming with the
     browser; dragging apparatus still works because pointerdown only calls
     preventDefault() once the touch has actually landed on something draggable. */
  touch-action: pan-y pinch-zoom;
  user-select: none;
  -webkit-user-select: none;
}

/* Full-screen mode (⛶ button): let the whole lab fill the screen — drop the
   layout's max-width so the stage grows, and give it a plain backdrop. */
:fullscreen .layout { max-width: none; width: 100%; height: 100%; padding: 12px; }
:fullscreen { background: var(--cream); }
#btn-fullscreen { white-space: nowrap; }

.sidebar {
  flex: 0 0 300px;
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 16px 18px;
  position: sticky;
  top: 72px;
}
.sidebar h2 { font-size: 1rem; margin: 0 0 10px; color: var(--ink-soft); text-transform: uppercase; letter-spacing: .06em; display: flex; align-items: center; justify-content: space-between; }
.step-nav { display: inline-flex; gap: 5px; }
.step-nav-btn {
  padding: 0;
  width: 26px; height: 26px;
  line-height: 1;
  font-size: 1.05rem;
  border-radius: 8px;
  background: #e8e4d8;
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.step-nav-btn:hover { background: var(--navy); color: #fff; }
ol#steps li.navable { cursor: pointer; }
ol#steps li.navable:hover { outline: 2px solid var(--blue); outline-offset: -2px; }

ol#steps { list-style: none; margin: 0 0 14px; padding: 0; }
ol#steps li {
  position: relative;
  padding: 8px 8px 8px 36px;
  margin-bottom: 6px;
  border-radius: 10px;
  background: #f2efe6;
  color: var(--ink-soft);
  font-size: 0.92rem;
  line-height: 1.35;
  transition: background .3s, color .3s;
}
ol#steps li::before {
  content: "";
  position: absolute;
  left: 10px; top: 50%;
  translate: 0 -50%;
  width: 17px; height: 17px;
  border-radius: 50%;
  border: 2px solid #c9c2b0;
  background: #fff;
}
ol#steps li.current {
  background: var(--blue-soft);
  color: var(--ink);
  font-weight: 600;
}
ol#steps li.current::before { border-color: var(--blue); }
ol#steps li.done { background: #e3f3ea; color: #2c6e4d; }
ol#steps li.done::before {
  border-color: var(--green);
  background: var(--green);
  content: "";
}
ol#steps li.done::after {
  content: "✓";
  position: absolute;
  left: 13px; top: 50%;
  translate: 0 -50%;
  color: #fff;
  font-size: 12px;
  font-weight: 800;
}

/* each step is a label + a ▾/▴ chevron that opens its full instructions */
ol#steps .step-row { display: flex; align-items: flex-start; gap: 8px; }
/* .step-label is a real <button> so it can be reached from the keyboard — strip the
   button chrome so it still reads as the plain step text it has always looked like */
ol#steps .step-label {
  flex: 1; min-width: 0;
  appearance: none; background: none; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: default;
}
ol#steps li.navable .step-label { cursor: pointer; }
ol#steps .step-toggle {
  flex: none;
  width: 22px; height: 22px;
  padding: 0;
  line-height: 1;
  font-size: .74rem;
  border: 1px solid #cfc9b8;
  border-radius: 6px;
  background: #fffdf7;
  color: var(--ink-soft);
  cursor: pointer;
}
ol#steps .step-toggle:hover { background: var(--blue-soft); border-color: var(--blue); color: var(--navy); }
ol#steps li.done .step-toggle { border-color: #b6d9c4; background: #f2fbf6; }

.key-idea {
  background: #fff8e8;
  border-left: 4px solid var(--amber);
  border-radius: 8px;
  padding: 10px 12px;
  font-size: .9rem;
  line-height: 1.45;
}
.key-idea b { color: #9a6a12; }

/* ---------------- Engine overlay elements (created by engine.js) ---------------- */

.cl-instruction {
  position: absolute;
  left: 50%;
  bottom: 14px;               /* sits within the reserved strip, clear of the bench */
  transform: translateX(-50%);
  max-width: min(640px, 92%);
  background: rgba(42, 64, 88, 0.94);
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 0.95rem;
  text-align: center;
  box-shadow: 0 6px 18px rgba(0,0,0,.25);
  pointer-events: none;
  transition: opacity .3s;
  z-index: 10;
  line-height: 1.35;
}

.cl-toast {
  position: absolute;
  left: 50%;
  /* Top-centre put every toast squarely over the reagent shelf — the exact bottles
     the message was usually talking about. The bottom band (bench slab + captions)
     is the least information-dense part of the scene, and the toast can never block
     a click anyway: it is click-through. */
  bottom: 106px;
  translate: -50% 0;
  pointer-events: none;
  padding: 10px 18px;
  border-radius: 12px;
  font-weight: 600;
  font-size: .95rem;
  color: #fff;
  background: var(--navy);
  box-shadow: 0 8px 22px rgba(0,0,0,.25);
  opacity: 0;
  pointer-events: none;
  transition: opacity .25s, translate .25s;
  z-index: 20;
  max-width: 88%;
  text-align: center;
  line-height: 1.35;
}
.cl-toast.show { opacity: 1; translate: -50% -6px; }
/* On a page with a component tab bar the toast landed on top of the tabs, hiding
   the name of the half of the practical you had just switched to. */
/* (the old top-anchored toast needed nudging below the component tab bar; it is
   bottom-anchored now, so the tab bar can never collide with it) */
.cl-toast.good { background: var(--green); }
.cl-toast.bad  { background: var(--red); }
.cl-toast.info { background: var(--navy); }
.cl-toast.warn { background: var(--amber); color: #3a2a06; }

/* Completion card — compact panel in the top-right corner. The stage is
   NOT dimmed and stays fully interactive, so students can read the theory
   while looking at (and still playing with) the finished set-up. */
.cl-win {
  position: absolute;
  inset: 0;
  z-index: 25;
  opacity: 0;
  pointer-events: none;
  transition: opacity .4s;
}
.cl-win.show { opacity: 1; }
/* The wrapper is pointer-events:none while hidden, but the CARD used to be
   pointer-events:auto unconditionally — so an invisible 410px-wide panel sat over
   the top-right of every bench from the moment the page loaded and swallowed every
   click there. That is exactly where the reagent shelf lives, so in several years
   the bottles simply could not be picked up. Only accept input once it is shown,
   and keep its two buttons out of the tab order until then. */
.cl-win .cl-win-card {
  pointer-events: none;
  visibility: hidden;
  position: absolute;
  top: 14px;
  right: 14px;
  width: min(410px, 46%);
  max-height: calc(100% - 28px);
  overflow: auto;
  background: var(--paper);
  border: 1px solid #e2dccb;
  border-radius: 16px;
  padding: 18px 22px;
  box-shadow: 0 14px 44px rgba(0,0,0,.26);
  text-align: left;
  animation: cl-slide .45s cubic-bezier(.2,1.4,.4,1);
}
.cl-win.show .cl-win-card { pointer-events: auto; visibility: visible; }
@keyframes cl-slide { from { transform: translateX(36px); opacity: 0; } to { transform: none; opacity: 1; } }
.cl-win h2 { margin: 0 0 8px; font-size: 1.25rem; }
.cl-win .cl-win-body { text-align: left; font-size: .9rem; line-height: 1.5; color: var(--ink); }
.cl-win .cl-win-body ul { padding-left: 18px; margin: 8px 0; }
.cl-win .cl-win-body table { border-collapse: collapse; width: 100%; font-size: .82rem; }
.cl-win .cl-win-body th, .cl-win .cl-win-body td { border: 1px solid #e0dccd; padding: 4px 6px; text-align: left; }
.cl-win .cl-win-body th { background: #f0ecdf; }
.cl-win .cl-win-actions { margin-top: 14px; display: flex; gap: 10px; justify-content: flex-start; }

/* landscape variant — wider & shorter, so a tall set-up (e.g. the drying rack
   in chromatography) stays visible below the card. Opt in with body.win-landscape */
body.win-landscape .cl-win .cl-win-card { width: min(720px, 74%); }
body.win-landscape .cl-win .cl-win-body { font-size: .88rem; }

/* ---------------- paused overlay ----------------
   Shown while sim.paused — i.e. the bench scrolled out of view, or the student
   pressed "Pause lab". It dims the frozen bench and, being on top of the canvas,
   swallows pointer events so nothing can be dragged while the clock is stopped. */
.cl-paused {
  position: absolute;
  inset: 0;
  z-index: 26;                       /* over the bench + instruction, under the win card */
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(38, 44, 56, .42);
  backdrop-filter: blur(1.5px);
  opacity: 0;
  pointer-events: none;
  /* opacity alone leaves the "▶ Resume experiment" button FOCUSABLE while the overlay
     is invisible, so a keyboard user tabbed to a control they could not see (and
     which, if activated, resumed a lab that was never paused). visibility:hidden
     takes it out of the tab order; .show puts it back. Same fix as .cl-win-card. */
  visibility: hidden;
  transition: opacity .2s, visibility 0s linear .2s;
  cursor: pointer;
}
.cl-paused.show {
  opacity: 1;
  pointer-events: auto;
  visibility: visible;
  transition: opacity .2s, visibility 0s;
}
.cl-paused-card {
  background: var(--paper);
  border: 1px solid #e2dccb;
  border-radius: 16px;
  padding: 16px 22px;
  width: min(430px, 84%);
  text-align: center;
  box-shadow: 0 14px 44px rgba(0,0,0,.3);
  animation: cl-pop .22s cubic-bezier(.2,1.4,.4,1);
}
@keyframes cl-pop { from { transform: scale(.94); opacity: 0; } to { transform: none; opacity: 1; } }
.cl-paused-card b { display: block; font-size: 1.05rem; margin-bottom: 6px; }
.cl-paused-card span { display: block; font-size: .84rem; line-height: 1.45; color: var(--ink-soft); margin-bottom: 12px; }
.cl-paused-card button { font-size: .95rem; padding: 8px 18px; }

/* ⏩ fast-forward toggle — lit while ×2 is engaged */
#btn-ff.on { background: #2f6f4f; border-color: #2f6f4f; color: #fff; }
#btn-pause, #btn-ff { white-space: nowrap; }

/* ---------------- Notes drawer ---------------- */

.notes-drawer {
  position: fixed;
  top: 0; right: 0;
  height: 100vh;
  width: min(460px, 92vw);
  background: var(--paper);
  box-shadow: -12px 0 40px rgba(0,0,0,.18);
  z-index: 50;
  padding: 22px 26px;
  overflow-y: auto;
  transform: translateX(105%);
  transition: transform .3s ease;
}
.notes-drawer.open { transform: translateX(0); }
.notes-drawer h2 { margin-top: 0; }
.notes-drawer h3 { margin: 18px 0 6px; color: var(--navy); }
.notes-drawer p, .notes-drawer li { font-size: .93rem; line-height: 1.55; }
.notes-drawer .close-notes { position: absolute; top: 14px; right: 14px; }
.notes-drawer .term { background: var(--blue-soft); border-radius: 6px; padding: 0 5px; font-weight: 600; }
.notes-drawer table { border-collapse: collapse; width: 100%; font-size: .88rem; }
.notes-drawer th, .notes-drawer td { border: 1px solid #e0dccd; padding: 6px 8px; text-align: left; vertical-align: top; }
.notes-drawer th { background: #f0ecdf; }

/* ---------------- Hub (index) ---------------- */

.hub {
  max-width: 1180px;
  margin: 0 auto;
  padding: 34px 22px 60px;
}
.hub-hero { text-align: center; margin-bottom: 30px; }
.hub-hero h1 { font-size: 2.1rem; margin: 0 0 8px; color: var(--navy-deep); }
.hub-hero p { color: var(--ink-soft); max-width: 640px; margin: 0 auto; line-height: 1.5; }

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(310px, 1fr));
  gap: 22px;
}
.sim-card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  overflow: hidden;
  text-decoration: none;
  color: var(--ink);
  transition: transform .18s ease, box-shadow .18s ease;
}
.sim-card:hover { transform: translateY(-4px); box-shadow: 0 14px 34px rgba(43,57,71,.18); }
.sim-card img {
  width: 100%;
  aspect-ratio: 1;          /* square tile: square renders fit exactly; the two
                               portrait tiles only lose their outer margins */
  object-fit: cover;
  background: #fcfcfc;
}
.sim-card .card-body { padding: 14px 18px 18px; }
.sim-card h3 { margin: 0 0 6px; font-size: 1.12rem; }
.sim-card p { margin: 0; color: var(--ink-soft); font-size: .9rem; line-height: 1.45; }
.sim-card .tag {
  display: inline-block;
  font-size: .72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .05em;
  padding: 2px 9px;
  border-radius: 999px;
  margin-bottom: 8px;
  background: var(--blue-soft);
  color: var(--navy);
}

/* ---------------- Hub: revision-notes button ---------------- */

.hub-notes-btn {
  position: fixed;
  top: 18px;
  right: 22px;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--navy);
  color: #fff;
  padding: 10px 18px;
  border-radius: 999px;
  text-decoration: none;
  font-weight: 600;
  font-size: .95rem;
  box-shadow: var(--card-shadow);
  transition: transform .15s ease, background .15s ease;
}
.hub-notes-btn:hover { background: var(--navy-deep); transform: translateY(-2px); }
.hub-notes-btn .book { font-size: 1.15rem; line-height: 1; }

/* ---------------- Concepts page ---------------- */

.doc {
  max-width: 900px;
  margin: 0 auto;
  padding: 30px 22px 80px;
}
.doc .panel {
  background: var(--paper);
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  padding: 24px 30px;
  margin-bottom: 24px;
}
.doc h1 { color: var(--navy-deep); }
.doc h2 { color: var(--navy); border-bottom: 2px solid #eee8d8; padding-bottom: 6px; }
.doc p, .doc li { line-height: 1.6; }
.doc table { border-collapse: collapse; width: 100%; font-size: .92rem; }
.doc th, .doc td { border: 1px solid #e0dccd; padding: 8px 10px; text-align: left; vertical-align: top; }
.doc th { background: #f0ecdf; }
.doc img.inline-fig { max-width: 300px; border-radius: 12px; float: right; margin: 0 0 12px 16px; }
/* the set-up renders sit on near-white — brightness clips the background to
   pure white, then multiply blends it invisibly into the page */
.doc img { mix-blend-mode: multiply; filter: brightness(1.05); }
.doc .defbox {
  background: var(--blue-soft);
  border-left: 4px solid var(--blue);
  border-radius: 8px;
  padding: 10px 14px;
  margin: 12px 0;
}

/* ============================================================
   Quiz component (shared/quiz.js) — used in the per-sim quiz
   modal and on the question-bank page.
   ============================================================ */

.quiz { display: flex; flex-direction: column; gap: 20px; }

/* one question: main column + reserved smiley column (never overlaps) */
.quiz-q {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  background: var(--paper);
  border: 1px solid #e7e1d1;
  border-radius: 14px;
  padding: 18px 20px;
  box-shadow: 0 2px 8px rgba(43,57,71,.06);
}
.quiz-main { flex: 1 1 auto; min-width: 0; }

/* stem */
.quiz-stem { display: flex; gap: 12px; align-items: flex-start; margin-bottom: 14px; }
.quiz-n {
  flex: 0 0 auto;
  width: 28px; height: 28px;
  border-radius: 50%;
  background: var(--navy);
  color: #fff;
  font-weight: 700;
  font-size: .9rem;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.quiz-stem-text { flex: 1 1 auto; min-width: 0; }
.quiz-ask { line-height: 1.5; font-size: .98rem; }
.quiz-ask b { color: var(--navy-deep); }
.quiz-fig { margin: 12px 0 4px; }
.quiz-fig img {
  max-width: 100%;
  max-height: 280px;
  border-radius: 10px;
  border: 1px solid #ece7d8;
  background: #fff;
  /* scans sit on near-white — blend the paper edge away */
  mix-blend-mode: multiply;
}
.quiz-table { margin: 12px 0 4px; overflow-x: auto; }
.quiz-table table { border-collapse: collapse; font-size: .9rem; }
.quiz-table th, .quiz-table td { border: 1px solid #e0dccd; padding: 5px 10px; text-align: left; }
.quiz-table th { background: #f0ecdf; }

/* options — each a full-width row with a clickable circle */
.quiz-opts { display: flex; flex-direction: column; gap: 8px; }
.quiz-opt {
  display: flex;
  align-items: center;
  gap: 12px;
  width: 100%;
  text-align: left;
  background: #f7f4ec;
  border: 1.5px solid #e5dfce;
  border-radius: 12px;
  padding: 10px 14px;
  color: var(--ink);
  transition: background .15s, border-color .15s, box-shadow .15s;
}
.quiz-opt:hover:not(:disabled) { background: #eef4fb; border-color: var(--blue); transform: none; box-shadow: none; }
.quiz-opt:disabled { cursor: default; opacity: 1; }
.quiz-dot {
  flex: 0 0 auto;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 2px solid #b9c2cc;
  background: #fff;
  position: relative;
  transition: border-color .15s, background .15s;
}
.quiz-ltr {
  flex: 0 0 auto;
  font-weight: 700;
  color: var(--navy);
  width: 1ch;
}
.quiz-txt { flex: 1 1 auto; line-height: 1.4; }
.quiz-txt sub { font-size: .75em; }

/* chosen (before confirm) */
.quiz-opt.chosen { background: var(--blue-soft); border-color: var(--blue); }
.quiz-opt.chosen .quiz-dot { border-color: var(--blue); }
.quiz-opt.chosen .quiz-dot::after {
  content: "";
  position: absolute; inset: 3px;
  border-radius: 50%;
  background: var(--blue);
}

/* after confirm */
.quiz-opt.correct { background: #e3f3ea; border-color: var(--green); }
.quiz-opt.correct .quiz-dot { border-color: var(--green); background: var(--green); }
.quiz-opt.correct .quiz-dot::after {
  content: "✓"; position: absolute; inset: 0;
  color: #fff; font-size: 13px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.quiz-opt.correct .quiz-ltr { color: #2c6e4d; }
.quiz-opt.wrong { background: #fbe7e4; border-color: var(--red); }
.quiz-opt.wrong .quiz-dot { border-color: var(--red); background: var(--red); }
.quiz-opt.wrong .quiz-dot::after {
  content: "✕"; position: absolute; inset: 0;
  color: #fff; font-size: 12px; font-weight: 800;
  display: flex; align-items: center; justify-content: center;
}
.quiz-opt.wrong .quiz-ltr { color: #b23b30; }

/* confirm + result (kept to the left, under the options) */
.quiz-actions { display: flex; align-items: center; gap: 12px; margin-top: 14px; flex-wrap: wrap; }
.quiz-confirm {
  background: var(--amber);
  color: #402c05;
  font-weight: 700;
  padding: 9px 22px;
  border-radius: 999px;
  box-shadow: 0 3px 12px rgba(232,161,60,.4);
  animation: quiz-pop .28s cubic-bezier(.2,1.5,.4,1);
}
.quiz-confirm:hover { background: #d9932f; }
@keyframes quiz-pop { from { transform: scale(.8); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.quiz-result { font-size: .92rem; line-height: 1.45; }
.quiz-result.good { color: #2c6e4d; font-weight: 600; }
.quiz-result.bad { color: #b23b30; font-weight: 600; }
.quiz-result b { color: inherit; }

/* smiley column — appears (content-sized) only when a correct answer is shown,
   in its own flex column so it can never overlap the question */
.quiz-side {
  flex: 0 0 auto;
  display: none;
  align-items: center;
  justify-content: center;
  align-self: center;
  margin-left: 6px;
}
.quiz-side.show { display: flex; }
.quiz-smiley {
  width: 132px;
  max-width: 100%;
  animation: quiz-smiley-in .5s cubic-bezier(.2,1.4,.4,1);
}
@keyframes quiz-smiley-in { from { transform: scale(.4) rotate(-12deg); opacity: 0; } to { transform: none; opacity: 1; } }

/* ---------------- Per-sim quiz modal (opened from the win card) ---------------- */

.quiz-launch {
  background: var(--green);
  color: #fff;
  font-weight: 700;
}
.quiz-launch:hover { background: #3f9a6c; }

.cl-quiz-modal {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(28, 40, 54, .55);
  backdrop-filter: blur(2px);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  padding: 30px 16px;
  overflow-y: auto;
  opacity: 0;
  pointer-events: none;
  transition: opacity .3s;
}
.cl-quiz-modal.show { opacity: 1; pointer-events: auto; }
.cl-quiz-card {
  position: relative;
  width: min(760px, 100%);
  background: var(--cream);
  border-radius: 18px;
  box-shadow: 0 24px 60px rgba(0,0,0,.35);
  padding: 26px 28px 30px;
  margin: auto;
  animation: cl-slide .4s cubic-bezier(.2,1.3,.4,1);
}
.cl-quiz-close {
  position: absolute; top: 16px; right: 16px;
  width: 34px; height: 34px; padding: 0;
  border-radius: 50%;
  background: #e8e4d8;
  font-size: 1rem;
}
.cl-quiz-title { margin: 0 4px 4px 0; font-size: 1.4rem; color: var(--navy-deep); }
.cl-quiz-sub { margin: 0 0 20px; color: var(--ink-soft); font-size: .95rem; line-height: 1.5; }
.cl-quiz-score {
  margin-top: 22px;
  padding: 14px 18px;
  border-radius: 12px;
  background: #fff;
  border: 1px solid #e7e1d1;
  font-size: 1.02rem;
  text-align: center;
}
.cl-quiz-score.all { background: #e3f3ea; border-color: var(--green); }

/* ---------------- Question-bank page ---------------- */

.bank {
  max-width: 900px;
  margin: 0 auto;
  padding: 30px 22px 80px;
}
.bank-hero { text-align: center; margin-bottom: 26px; }
.bank-hero h1 { color: var(--navy-deep); font-size: 2rem; margin: 0 0 8px; }
.bank-hero p { color: var(--ink-soft); max-width: 620px; margin: 0 auto; line-height: 1.55; }
.bank-back { display: inline-block; margin-bottom: 18px; text-decoration: none; font-weight: 600; color: var(--ink-soft); }
.bank-back:hover { color: var(--navy); }
.bank-section-h {
  font-size: 1.02rem;
  text-transform: uppercase;
  letter-spacing: .05em;
  color: var(--navy);
  margin: 26px 2px 4px;
}

/* ---------------- Hub: full-width question-bank card ---------------- */

.bank-card {
  grid-column: 1 / -1;               /* span every column on its own row */
  display: flex;
  align-items: center;
  gap: 26px;
  background: linear-gradient(135deg, var(--navy) 0%, var(--navy-deep) 100%);
  color: #fff;
  border-radius: var(--radius);
  box-shadow: var(--card-shadow);
  overflow: hidden;
  text-decoration: none;
  padding: 26px 30px;
  transition: transform .18s ease, box-shadow .18s ease;
}
.bank-card:hover { transform: translateY(-4px); box-shadow: 0 16px 38px rgba(43,57,71,.28); }
.bank-card .bank-icon {
  flex: 0 0 auto;
  font-size: 2.8rem;
  width: 76px; height: 76px;
  display: flex; align-items: center; justify-content: center;
  background: rgba(255,255,255,.14);
  border-radius: 18px;
}
.bank-card .bank-text { flex: 1 1 auto; }
.bank-card .tag {
  display: inline-block;
  font-size: .72rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: .05em;
  padding: 2px 9px; border-radius: 999px;
  margin-bottom: 8px;
  background: rgba(255,255,255,.18); color: #fff;
}
.bank-card h3 { margin: 0 0 6px; font-size: 1.35rem; color: #fff; }
.bank-card p { margin: 0; color: rgba(255,255,255,.82); font-size: .95rem; line-height: 1.5; }
.bank-card .bank-go {
  flex: 0 0 auto;
  font-weight: 700;
  background: #fff;
  color: var(--navy-deep);
  padding: 10px 20px;
  border-radius: 999px;
}

/* A visible focus ring everywhere, so a keyboard user can see where they are.
   Only .part-btn had one, which made tabbing through the page invisible. */
a:focus-visible,
button:focus-visible,
select:focus-visible,
input:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid #d9a441;
  outline-offset: 2px;
  border-radius: 4px;
}
/* A closed drawer is only slid off-screen, so everything inside it stayed in the
   tab order — a dozen phantom stops, including every "Show answer" button in the
   question paper. visibility:hidden takes them out while still allowing the
   slide-out to animate (the visibility change is delayed until the slide ends). */
.notes-drawer {
  visibility: hidden;
  transition: transform .3s ease, visibility 0s linear .3s;
}
.notes-drawer.open {
  visibility: visible;
  transition: transform .3s ease, visibility 0s;
}

/* Respect a reduced-motion preference: the sliding completion card, the confetti
   and the shake feedback are decoration, and for some students they are worse than
   decoration. The lab itself still animates — that IS the experiment. */
@media (prefers-reduced-motion: reduce) {
  .cl-win .cl-win-card,
  .notes-drawer, .paper-drawer,
  .nb-entry, .cl-toast, .cl-instruction {
    animation: none !important;
    transition-duration: .01ms !important;
  }
}

/* ---------------- Responsive ---------------- */

@media (max-width: 980px) {
  /* align-items must be `stretch` here. With the default `flex-start` from
     .layout, a COLUMN flex container sizes each child to its own content — and
     #stage-wrap's content is the canvas, so the canvas asks the wrap how wide it
     is, the wrap answers "as wide as the canvas", and it can never shrink. A
     window dragged narrower then left the bench overflowing the page. */
  .layout { flex-direction: column; align-items: stretch; }
  .sidebar { position: static; flex: 1 1 auto; width: 100%; }
}

/* Below this width the nine top-bar controls cannot fit on one row: they used to
   keep their natural width (flex: none) and simply run off the right of the
   screen, taking ↺ Reset and 📄 Question paper with them. Wrap instead — the
   one-row rule is about desktop clutter, not about hiding controls on a phone. */
@media (max-width: 760px) {
  .topbar { flex-wrap: wrap; row-gap: 6px; }
  .topbar .actions { flex: 1 1 100%; justify-content: flex-start; }
}

@media (max-width: 620px) {
  .quiz-q { flex-direction: column; }
  .quiz-side { align-self: flex-start; justify-content: flex-start; }
  .quiz-smiley { width: 108px; }
  .bank-card { flex-direction: column; text-align: center; }
}

/* Written mode: the notes are gated behind a deliberate click (engine.js) — the
   drawer otherwise reads as the mark scheme while the answer boxes are open. */
.notes-gate p { font-size: .92rem; line-height: 1.55; color: var(--ink-soft); margin: 8px 0 16px; }
.notes-gate .notes-reveal { font-size: .9rem; }

/* ==========================================================================
   KEYBOARD BENCH (accessible mirror of the canvas apparatus)
   The bench is a canvas, so without this there is no way to perform a single
   experiment without a pointer. These are real buttons in reading order; they
   drive the same grab/drop code the mouse does.
   ========================================================================== */
.cl-a11y {
  /* Closed, this is one line: it must not steal room from the bench or push the
     instruction banner away from it. Padding grows only when it is opened. */
  margin: 6px 10px 2px;
  padding: 2px 10px;
  border: 1px solid var(--line, #e2e7ee);
  border-radius: 10px;
  background: var(--panel, #fbfcfe);
}
.cl-a11y:has(.cl-a11y-d[open]) { padding: 8px 12px; }
.cl-a11y-h {
  margin: 0 0 4px;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink, #22303c);
}
.cl-a11y-hint, .cl-a11y-step, .cl-a11y-live {
  margin: 0 0 6px;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--muted, #5b6a72);
}
.cl-a11y-step { font-weight: 600; color: var(--ink, #22303c); }
.cl-a11y-live:empty { display: none; }
.cl-a11y-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.cl-a11y-btn {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  /* 44px minimum target (WCAG 2.2 Target Size) */
  min-height: 44px;
  padding: 6px 10px;
  border: 1px solid var(--line, #cfd8e3);
  border-radius: 8px;
  background: #fff;
  cursor: pointer;
  text-align: left;
  font: inherit;
}
.cl-a11y-btn:hover { background: #eef4fb; }
.cl-a11y-btn:focus-visible {
  outline: 3px solid #2f6fb5;
  outline-offset: 2px;
}
.cl-a11y-name { font-size: 13px; font-weight: 600; color: var(--ink, #22303c); }
.cl-a11y-sub  { font-size: 11px; color: var(--muted, #6b7a86); }

/* The keyboard bench is a fallback route, not a second UI. As an always-expanded
   block it took 130-260px of every page and pushed the instruction banner away from
   the bench. It is a <details> now: one line closed, everything still in the DOM and
   in the tab order (never display:none, which would remove it). */
.cl-a11y-h {
  cursor: pointer;
  list-style: none;
  padding: 2px 0;
  min-height: 28px;
  display: flex;
  align-items: center;
}
.cl-a11y-h::-webkit-details-marker { display: none; }
.cl-a11y-h::before {
  content: "▸";   /* the real character, not a CSS escape: a mangled \25B8 rendered as a control code */
  margin-right: 7px;
  color: var(--ink-soft, #5b6b7c);
  transition: rotate .15s ease;
}
.cl-a11y-d[open] > .cl-a11y-h::before { rotate: 90deg; }
.cl-a11y-h:focus-visible { outline: 3px solid #2f6fb5; outline-offset: 2px; border-radius: 6px; }
.cl-a11y-d:not([open]) + .cl-a11y-live { margin-top: 0; }
@media (prefers-reduced-motion: reduce) { .cl-a11y-h::before { transition: none; } }

@media (prefers-reduced-motion: reduce) {
  .cl-a11y-btn { transition: none; }
}

/* ==========================================================================
   FIRST-RUN BENCH HELP (A-01)
   The pour gesture — hold a bottle over a tube and tilt it — was explained
   nowhere, so a student could not perform step one of any practical.
   ========================================================================== */
.cl-help {
  position: fixed; inset: 0; z-index: 200;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  background: rgba(28, 34, 44, .55);
  backdrop-filter: blur(2px);
}
.cl-help-card {
  max-width: 560px; width: 100%;
  background: var(--paper, #fdfcf8);
  border: 1px solid #e2dccb;
  border-radius: 16px;
  padding: 22px 26px;
  box-shadow: 0 18px 50px rgba(20, 26, 34, .35);
  max-height: 90vh; overflow: auto;
}
.cl-help-card h2 { margin: 0 0 4px; font-size: 1.25rem; color: var(--navy, #33506d); }
.cl-help-lead { margin: 0 0 12px; color: var(--ink-soft, #5b6b7c); font-size: .92rem; }
.cl-help-list { margin: 0 0 14px; padding-left: 20px; }
.cl-help-list li { margin-bottom: 9px; font-size: .93rem; line-height: 1.5; }
.cl-help-note {
  margin: 0 0 16px; padding: 9px 12px;
  background: #eef4fb; border: 1px solid #d5e3f2; border-radius: 10px;
  font-size: .86rem; line-height: 1.5; color: #2f4a63;
}
.cl-help-actions { display: flex; justify-content: flex-end; }
.cl-help-actions button { min-height: 44px; padding: 10px 20px; }
@media (prefers-reduced-motion: reduce) { .cl-help { backdrop-filter: none; } }

/* ==========================================================================
   PHONE TAP TARGETS (A-07, WCAG 2.2 Target Size)
   At 360px the toolbar wrapped to three rows and 19 controls measured under
   24px in one dimension — Reset sat in that same cluster. Grow the hit area
   (padding, not type size) and let the secondary tools wrap below the title
   rather than competing with it.
   ========================================================================== */
@media (max-width: 600px) {
  .topbar { flex-wrap: wrap; gap: 8px 10px; padding: 8px 12px; }
  .topbar h1 { flex: 1 1 100%; font-size: .95rem; order: -1; }
  .topbar .actions { flex: 1 1 100%; justify-content: flex-start; gap: 8px; }
  .topbar .actions button,
  .topbar .back {
    min-height: 44px;
    min-width: 44px;
    padding: 10px 12px;
    font-size: .82rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
  /* Reset is destructive — keep it off the end of the row, away from Demo/Free */
  #btn-reset { margin-left: auto; }

  /* the step chevrons and nav arrows were 26px squares */
  .step-nav-btn, .step-toggle { min-width: 44px; min-height: 44px; }
  ol#steps .step-label { min-height: 44px; display: flex; align-items: center; }

  /* notebook controls */
  .nb-check, .nb-reveal { min-height: 44px; padding: 10px 16px; }
  .nb-entry select,
  .nb-entry input,
  .nb-entry textarea { min-height: 44px; font-size: 16px; }  /* 16px stops iOS zooming on focus */
  .close-notes { min-width: 44px; min-height: 44px; }
  .hub-filters button { min-height: 44px; padding: 10px 14px; }
  .cl-a11y-btn { min-height: 44px; }
}

/* At phone width the instruction banner is long enough to wrap to four or five
   lines. Absolutely positioned in the stage's reserved strip it then grew UP over
   the keyboard panel and the bench. Put it back in normal flow below the bench,
   where it simply pushes the page down like any other block. */
@media (max-width: 600px) {
  #stage-wrap { padding-bottom: 10px; }
  .cl-instruction {
    position: static;
    transform: none;
    max-width: none;
    margin: 10px 10px 4px;
    border-radius: 12px;
    text-align: left;
    font-size: .9rem;
    line-height: 1.45;
  }
  /* the keyboard panel goes below the sentence, not between it and the bench */
  .cl-a11y { order: 2; }
}

/* "⋯ More" — the toolbar carries eleven controls. At 44px each that is three rows
   on a phone, pushing the bench off screen. Keep the ones a student uses while
   working; fold the rest away. */
.topbar .actions .more-toggle { display: none; }
@media (max-width: 600px) {
  .topbar .actions .more-toggle { display: inline-flex; }
  .topbar .actions.collapsed > button.secondary { display: none; }
}

/* The keyboard bench's status line is an aria-live region. With the panel CLOSED it
   still rendered every announcement as visible text under the bench — duplicating
   the toast for sighted users. Clip it while closed (clipped text is still read by
   screen readers); show it when the panel is open, where it is the visible feedback
   for keyboard operation. */
.cl-a11y-d:not([open]) + .cl-a11y-live {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
