/* Out-of-order simulator viewer — no framework, no build step.
 *
 * Two layouts share one DOM:
 *   body.layout-slide      — the lecture slide: bordered tables with grey
 *                            title bands, laid out as on the slide.
 *   body.layout-flow       — the pipeline: the whole machine as one strip, a
 *                            column per stage (flow.js; its styles are flow.css).
 */

:root {
  color-scheme: light dark;
  --bg: #f6f7f9;
  --panel: #ffffff;
  --ink: #16181d;
  --dim: #6b7280;
  --line: #d9dde3;
  --accent: #2f6feb;
  --changed: #fff2c2;
  --changed-line: #e5b83a;
  --blocked: #ffd9d3;
  --blocked-line: #d9503c;
  --ready: #1a7f4b;
  --head: #2f6feb;
  --tail: #b45309;
  --retired: #eef1f5;
  --good: #167a4a;
  --good-bg: #e3f5ea;
  --bad: #b3261e;
  --bad-bg: #fde4e1;
  --follow: #e8f0fe;
  --focus: #dbe7ff;
  --slide-bg: #ffffff;
  --slide-head: #d9d9d9;
  --slide-line: #000000;
  --st-d: #dbe7ff; --st-s: #e6dcff; --st-x: #ffe6c7; --st-c: #d9f2e3; --st-r: #e5e7eb;
  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #14161a; --panel: #1c1f25; --ink: #e6e8ec; --dim: #9aa2ae;
    --line: #303640; --accent: #7aa2f7; --changed: #4a3d16; --changed-line: #b08a2a;
    --blocked: #4a2320; --blocked-line: #e0705c; --ready: #6ee7a8;
    --head: #7aa2f7; --tail: #f0b070; --retired: #23262d;
    --good: #6ee7a8; --good-bg: #173527; --bad: #f2837a; --bad-bg: #3d1f1c;
    --follow: #22304a; --focus: #2a3d66;
    --slide-bg: #1c1f25; --slide-head: #3a3f47; --slide-line: #b8bec8;
    --st-d: #263a63; --st-s: #3a2f63; --st-x: #5a3f1e; --st-c: #1f4a33; --st-r: #2c3038;
  }
}

* { box-sizing: border-box; }

/* Always reserve the scrollbar gutter: the events panel makes some cycles
 * taller than the viewport, and a scrollbar that comes and goes would shift
 * every column a few pixels as the student steps. */
html { scrollbar-gutter: stable; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: 14px/1.45 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
}

h1 { font-size: 17px; margin: 0; letter-spacing: -0.01em; }
h2 {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.08em;
  color: var(--dim); margin: 0 0 8px; font-weight: 600;
}
h2 .dim { text-transform: none; letter-spacing: 0; font-weight: 400; }

.dim { color: var(--dim); font-weight: 400; }
code { font-family: var(--mono); font-size: 0.92em; background: var(--bg); padding: 0 4px; border-radius: 3px; }

/* ---------- top bar ---------- */

.topbar {
  display: flex; align-items: center; gap: 20px; flex-wrap: wrap;
  padding: 12px 18px; background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.pickers { display: flex; gap: 14px; }
.pickers label, .speed, .quiz-toggle, .options summary {
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em;
  color: var(--dim); display: flex; align-items: center; gap: 6px;
}
select {
  font: inherit; font-size: 13px; text-transform: none; letter-spacing: 0;
  color: var(--ink); background: var(--panel);
  border: 1px solid var(--line); border-radius: 6px; padding: 3px 6px;
}
.config-summary {
  margin-left: auto; font-family: var(--mono); font-size: 11px; color: var(--dim);
  text-align: right;
  /* Always exactly two lines, whatever the machine, so the header keeps one
     height from lesson to lesson (at 42ch the superscalar and the no-renaming
     machines needed a third line and the page jumped).  A fixed width, not a
     max-width: the box must not depend on the text either.  Lines break only
     after a "·" (summaryLine() in viewer.js), so the width is set by the
     longest half: 60 characters for the "real latencies" preset, 50 for the
     longest recorded summary (no renaming).  balance evens the two lines; a
     hand-built machine with more policy flags than two lines hold is cut with
     an ellipsis rather than growing the header. */
  width: 62ch; max-width: 100%;
  line-height: 16px; height: 32px;
  text-wrap: balance;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2;
  overflow: hidden;
}
/* the summary (here and on the lesson page) breaks only after a "·": see
   summaryLine() in viewer.js */
.config-bit { white-space: nowrap; }
/* 62ch only where the header has room for it beside the title, the mode switch
   and the pickers (about 1160px); below that the box is 52ch, which still
   holds every recorded summary (longest half: 50 characters), so the header
   stays on one row down to about 800px.  The width follows the window, never
   the text, so the header's height still cannot change from machine to
   machine.  On a phone even 52ch at 11px (about 344px) is wider than a 360px
   screen leaves after the header's 18px padding each side -- "no renaming"
   would be the part cut off -- so scale the type to fit: a monospace ch is
   about 0.6em, 52ch is 31.2em, and 32 leaves a little slack.  (min() leaves it
   at 11px on anything wider than about 390px.) */
@media (max-width: 1160px) {
  .config-summary { width: 52ch; font-size: min(11px, calc((100vw - 36px) / 32)); }
}

/* ---------- the bar of the execution view: controls, strip, quiz ----------
 * One row, pinned to the top of the window, so that the tables start as high
 * on the page as they can.  The sections in it (the step controls, the strip
 * of what is being worked, the quiz bar) and the quiz bar's rows make no box
 * of their own (display: contents): what is in them lines up in the one flex
 * row, in the order given by `order`.  It wraps only in a window too narrow
 * for the row. */

.top-anchor {
  display: flex; align-items: center; gap: 6px 8px; flex-wrap: wrap;
  padding: 8px 18px; background: var(--panel);
  border-bottom: 1px solid var(--line); position: sticky; top: 0; z-index: 5;
}
.top-anchor > section, .top-anchor .quiz-row { display: contents; }
.top-anchor .lesson-strip > * { order: 1; }            /* the way back, what is being worked */
.top-anchor .controls > *     { order: 2; }            /* stepping */
.top-anchor .quiz-row > *     { order: 3; }            /* the quiz's setup */
.top-anchor .quiz-row > .quiz-name, .top-anchor #btn-download,
.top-anchor .quiz-row > .quiz-load { order: 4; }       /* the file */
.top-anchor .controls > .zoom, .top-anchor .controls > .options { order: 5; }
.top-anchor #btn-reset, .top-anchor .quiz-start,
.top-anchor #btn-download, .top-anchor .zoom { margin-left: 8px; }   /* a gap between the groups */
.top-anchor .quiz-spacer { display: none; }            /* the slider takes the room to spare */
.top-anchor #cycle-slider { flex: 1 1 110px; min-width: 110px; }
.top-anchor button, .top-anchor .quiz-load { padding-left: 8px; padding-right: 8px; white-space: nowrap; }
.top-anchor .quiz-progress { margin-left: 0; white-space: nowrap; }
.top-anchor .lesson-strip-title { white-space: nowrap; }
/* what the bar has to say hangs under it, over the margin beside the slide
   title: no room is taken from the tables */
.top-anchor .quiz-notes {
  position: absolute; top: 100%; right: 18px; margin-top: 6px;
  display: grid; gap: 4px; justify-items: end;
  max-width: min(680px, calc(100% - 36px)); pointer-events: none;
}
.top-anchor .quiz-score {
  background: var(--panel); border: 1px solid var(--line); border-radius: 6px;
  padding: 3px 9px; color: var(--dim);
}
.top-anchor .quiz-score:empty { display: none; }
button {
  font: inherit; padding: 5px 10px; cursor: pointer;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--line); border-radius: 6px;
}
button:hover { border-color: var(--accent); color: var(--accent); }
button:disabled { opacity: 0.35; cursor: default; border-color: var(--line); color: var(--ink); }
button.primary { background: var(--accent); color: #fff; border-color: var(--accent); }
button.primary:hover { filter: brightness(1.08); color: #fff; }
.controls button { min-width: 38px; }
#btn-play.playing { background: var(--accent); color: #fff; border-color: var(--accent); }
#cycle-slider { flex: 1 1 220px; min-width: 160px; accent-color: var(--accent); }
.cycle-readout { font-family: var(--mono); font-size: 13px; white-space: nowrap; }
.cycle-readout b { font-size: 15px; }
.quiz-toggle { cursor: pointer; }
.zoom { display: inline-flex; align-items: center; gap: 2px; margin-left: 4px; }
.zoom button { min-width: 30px; padding: 4px 6px; }
.zoom .zoom-readout { min-width: 52px; font-family: var(--mono); font-size: 12px; }

/* quiz: cycles before the start cycle shown as a given starting point / worked example */
.quiz-start input[type="number"] { width: 3.5em; font: inherit; font-family: var(--mono); padding: 1px 4px; }
input.q.given { background: var(--retired); color: var(--dim); cursor: default; }
body.layout-slide input.q.given { color: var(--ink); }
.quiz-given-note { font-size: 12px; color: var(--dim); }

input.q.q-derived { background: var(--retired); cursor: default; }

/* quiz drag & drop: program table -> ROB slot only */
.quiz-drag { display: flex; align-items: center; gap: 6px; font-size: 12px; cursor: pointer; }
td.q-dragsrc { cursor: grab; user-select: none; }
input.q[draggable="true"] { cursor: grab; }
td.q-dragsrc:active { cursor: grabbing; }
input.q.drop-ok { outline: 2px solid var(--accent); outline-offset: 1px; background: var(--focus); }

/* view options popover */
.options { position: relative; }
.options summary {
  cursor: pointer; list-style: none; padding: 5px 10px;
  border: 1px solid var(--line); border-radius: 6px; user-select: none;
}
.options summary::-webkit-details-marker { display: none; }
.options[open] summary { border-color: var(--accent); color: var(--accent); }
.options-body {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 20;
  min-width: 300px; padding: 12px 14px; display: grid; gap: 8px;
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12); font-size: 13px;
}
.opt-group { display: flex; gap: 12px; align-items: center; flex-wrap: wrap; }
.opt-label { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--dim); min-width: 48px; }
.options-body label { display: flex; align-items: center; gap: 6px; cursor: pointer; }
.opt-row { display: flex; align-items: center; gap: 8px; }
.options-body select { font-size: 13px; }
.options-body button { font-size: 13px; }

/* panels popover */
.panels-body { left: 0; right: auto; min-width: 280px; }
.panels-note { font-size: 11px; max-width: 34ch; }

/* machine panel: the hardware structures and widths */
.machine summary.changed-machine { border-color: var(--accent); color: var(--accent); }
.machine summary.error { border-color: var(--bad); color: var(--bad); }
.machine-body { left: 0; right: auto; min-width: 560px; max-width: min(92vw, 760px); }
.machine-groups { display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr)); gap: 10px 18px; }
.machine-group { border: 1px solid var(--line); border-radius: 8px; padding: 6px 10px 8px; margin: 0; min-width: 0; }
.machine-group legend { font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--dim); padding: 0 4px; }
.machine-row { display: flex; align-items: center; justify-content: space-between; gap: 10px; padding: 2px 0; cursor: default; }
.machine-label { flex: 1 1 auto; }
.machine-num { width: 64px; font: inherit; font-size: 13px; text-align: right; color: var(--ink); background: var(--panel);
               border: 1px solid var(--line); border-radius: 6px; padding: 2px 6px; }
.machine-num.non-default, .machine-choice.non-default { border-color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent); }
.machine-bool { accent-color: var(--accent); width: 16px; height: 16px; }
/* the functional units: a row per kind, a column per knob */
.machine-group.units { grid-column: 1 / -1; }
.machine-units { border-collapse: collapse; margin-top: 2px; }
.machine-units th { font-weight: 500; text-align: left; padding: 2px 10px 2px 0; white-space: nowrap; }
.machine-units thead th { font-size: 11px; color: var(--dim); text-align: center; padding-right: 10px; }
.machine-units thead th:first-child { text-align: left; }
.machine-units td { padding: 2px 10px 2px 0; text-align: center; }
.machine-units .machine-unit { font-weight: 600; letter-spacing: 0.04em; }
.machine-units .machine-ops { margin-left: 8px; font-family: var(--mono); font-weight: 400; color: var(--dim); }
.machine-presets { justify-content: flex-start; }
.machine-error { color: var(--bad); background: var(--bad-bg); border-radius: 6px; padding: 6px 10px; font-size: 13px; white-space: pre-wrap; }

/* custom program editor */

.load-error {
  margin: 18px; padding: 14px 16px; border-radius: 8px;
  background: var(--blocked); border: 1px solid var(--blocked-line);
  font-family: var(--mono); font-size: 12px; white-space: pre-wrap;
}

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

.grid { display: grid; gap: 14px; padding: 14px 18px 28px; align-items: start; position: relative; }
.alu-panel      { grid-area: alu; }
.slide-head     { grid-area: title; }
.rob-panel      { grid-area: rob; }
.rs-panel       { grid-area: rs; }
.map-panel      { grid-area: map; }
.cdb-panel      { grid-area: cdb; }
.free-panel     { grid-area: free; }
.program-panel  { grid-area: program; }
.timeline-panel { grid-area: timeline; }
.ref-panels    { grid-area: reference; }
.deps-panel     { grid-area: deps; }
.events-panel   { grid-area: events; }

/* The first column is exactly as wide as the ROB / RS tables; the pipeline
 * diagram sits beside them, where it is visible without scrolling. */
/* The ROB occupies one row and the RS starts in the next, so the two are
 * always a row-gap apart whatever the sizes of the panels beside them.  The
 * right column is the record of the run, stacked top to bottom in its
 * wrapper: the pipeline diagram, then what happened this cycle directly under
 * it, whose lines wrap in the column rather than stretching across the page.
 * The 1fr row under the stations takes whatever the record needs beyond the
 * tables beside it, so a tall diagram never pushes the ROB and RS apart.
 * PARKED: the "Program & timings" panel is hidden in index.html; without
 * `hidden` it is the first panel of this column again. */
body.layout-slide .grid {
  grid-template-columns: max-content minmax(190px, 0.55fr) minmax(320px, 1fr);
  grid-template-areas:
    "title    title     title"
    "rob      map       record"
    "rs       cdb       record"
    "rs       free      record"
    ".        .         record"
    "deps     deps      record";
  grid-template-rows: auto auto auto auto 1fr auto;
  row-gap: 18px;
}
body.layout-slide .record { grid-area: record; display: flex; flex-direction: column; gap: 18px; min-width: 0; }
body.layout-slide .events li .detail { min-width: 0; overflow-wrap: anywhere; }
.record        { display: contents; }
/* What only the pipeline layout shows. */
body:not(.layout-flow) .pipeline-only, body:not(.layout-flow) .ref-sep { display: none; }

/* The caption over the record of the run: the tables that describe the run, not the machine. */
.ref-sep { flex-basis: 100%; font-size: 11.5px; color: var(--dim); }

@media (max-width: 1000px) {
  body.layout-slide .grid {
    grid-template-columns: 1fr; column-gap: 14px; row-gap: 14px; padding-right: 18px;
    grid-template-areas: "title" "rob" "rs" "map" "cdb" "free" "program" "deps" "reference" "timeline" "events";
    grid-template-rows: none;
  }
  body.layout-slide .record { display: contents; }
}

.panel {
  background: var(--panel); border: 1px solid var(--line);
  border-radius: 10px; padding: 12px 14px 14px; overflow-x: auto;
}

/* The row of the slide title: the title in the middle of the page whatever
   is beside it, and in quiz mode the buttons that work on the cycle on
   screen level with it, at its left. */
.slide-head {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center; column-gap: 12px; margin: 4px 0 -4px;
}
.slide-actions { grid-column: 1; justify-self: start; display: flex; flex-wrap: wrap; gap: 6px; }
.slide-actions button { font-size: 13px; padding: 5px 8px; white-space: nowrap; }
/* slide title, shown in the slide layout only */
.slide-title {
  grid-column: 2; margin: 0; font-size: 30px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ink); text-transform: none; text-align: center;
}
@media (max-width: 1000px) {
  /* one after the other: the title, then the buttons */
  .slide-head { grid-template-columns: minmax(0, 1fr); row-gap: 8px; }
  .slide-actions, .slide-title { grid-column: 1; }
  .slide-title { order: -1; }
}
/* quiz mode: whose cycle this is (viewer.js render; body.cycle-response,
   body.cycle-given).  The cycle number in the bar takes the same colour, for
   the pipeline layout, which has no slide title. */
.slide-tag {
  display: inline-block; vertical-align: middle; margin-left: 10px; padding: 3px 11px;
  border-radius: 999px; font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
}
.slide-tag.response { background: var(--accent); color: #fff; }
.slide-tag.given { background: color-mix(in srgb, var(--dim) 16%, transparent); color: var(--dim); }
body.cycle-response .cycle-readout b { color: var(--accent); }
body.cycle-given .cycle-readout b { color: var(--dim); }

/* ---------- tables: shared ---------- */

table { border-collapse: collapse; width: 100%; font-family: var(--mono); font-size: 12.5px; }
th {
  text-align: right; font-weight: 600; font-size: 10px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--dim); padding: 3px 6px;
  border-bottom: 1px solid var(--line); white-space: nowrap;
}
th.ins, td.ins { text-align: left; }
td {
  text-align: right; padding: 3px 6px; white-space: nowrap;
  border-bottom: 1px solid color-mix(in srgb, var(--line) 45%, transparent);
}
tbody tr:last-child td { border-bottom: none; }
td.empty { color: var(--dim); }
tr.free td { color: var(--dim); }
tr.retired-row td { background: var(--retired); color: var(--dim); }

td .cell {
  display: inline-block; padding: 1px 4px; margin: -1px -2px;
  border-radius: 4px; border: 1px solid transparent;
  min-width: 1.6em; text-align: right;
}
td.ins .cell { text-align: left; }
td .cell.changed { background: var(--changed); border-color: var(--changed-line); }
td .cell.blocked { background: var(--blocked); border-color: var(--blocked-line); }
body.no-changes .changed { background: transparent !important; border-color: transparent !important; }

.ready { color: var(--ready); font-weight: 600; }

/* The ready bit: a column of its own beside each tag, one bit of storage per
 * row.  Set, it is a green + in a green outline; clear, it is an empty box;
 * with no tag beside it, it is blank like the rest of the row. */
th.rdy, td.rdy { text-align: center !important; padding-left: 0 !important; padding-right: 0 !important; }
td.rdy { font-weight: 800; border-left: 1px dashed var(--line); }
td.rdy.on { color: var(--ready); box-shadow: inset 0 0 0 2px var(--ready); }
td.rdy.on.changed { background: var(--changed); }   /* set this cycle */

/* ROB head / tail: colour the row edge as well as the ht letter, so the
   circular order reads at a glance even when the buffer has wrapped. */
.ht    { color: var(--dim); }
.ht b.h { color: var(--head); }
.ht b.t { color: var(--tail); }
tr.head-row td:first-child { box-shadow: inset 3px 0 0 var(--head); }
tr.tail-row td:first-child { box-shadow: inset -3px 0 0 var(--tail); }
tr.head-row.tail-row td:first-child {
  box-shadow: inset 3px 0 0 var(--head), inset -3px 0 0 var(--tail);
}

/* P6 has no Told */

/* An issued instruction still occupies its station until it executes. */
tr.issued td { color: var(--dim); }
.pill {
  display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 999px;
  font-size: 9.5px; letter-spacing: 0.05em; text-transform: uppercase;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent);
  vertical-align: 1px; font-family: system-ui, sans-serif; font-weight: 600;
}

/* Follow an instruction across every table on hover; focus for step-by-event. */
tr.hl-insn td, li.hl-insn { background: var(--follow) !important; }
tr.hl-insn td.ins { font-weight: 600; }
tr.focus-insn td, li.focus-insn { background: var(--focus) !important; }
.focus-tag { outline: 2px solid var(--accent); outline-offset: 1px; border-radius: 4px; }

tr.flash { animation: flash 1.1s ease-out; }
@keyframes flash {
  0%   { background: var(--changed); }
  100% { background: transparent; }
}
tr.current-insn td { box-shadow: inset 2px 0 0 var(--accent); }

/* tag chips (free list, CDB) */
.taglist { display: flex; flex-wrap: wrap; gap: 5px; min-height: 24px; font-family: var(--mono); font-size: 12.5px; align-items: center; }
.tag {
  display: inline-block; padding: 2px 7px; border-radius: 5px;
  border: 1px solid var(--line); background: var(--bg);
}
.tag.next::before { content: "▸ "; color: var(--accent); }
.tag.changed { background: var(--changed); border-color: var(--changed-line); }
.tag.blocked { background: var(--blocked); border-color: var(--blocked-line); }
.none { color: var(--dim); font-style: italic; font-family: inherit; }
/* The free list is a fixed grid of slots, one per register that can be
 * free, so it never changes size as tags come and go: tags in the slots
 * they occupy, a dashed empty slot for each register in use.  The slide
 * layout lists the tags alone. */
.free-slot {
  display: inline-block; padding: 2px 7px; border-radius: 5px; box-sizing: border-box;
  border: 1px dashed color-mix(in srgb, var(--line) 80%, transparent); color: var(--dim); text-align: center;
}
body.layout-slide .free-slot { display: none; }
.cdb .tag { border-color: var(--accent); color: var(--accent); font-weight: 600; }

/* ---------- fixed column widths ----------
 * Column widths must not change from cycle to cycle (a tag appearing in an
 * empty cell, a number growing from 9 to 10), or the tables jump under the
 * student's eyes as they step.  Every column except the instruction/op column
 * gets a width sized for its widest possible content; the instruction column
 * takes the rest.  Sizes are in ch so they follow the font size. */
.rob, .rs, .map, .summary { table-layout: fixed; }
/* The ROB and RS tables are exactly as wide as their columns, so the rest of
 * the row is free for the map table, free list and pipeline diagram. */
.rob, .rs, body.layout-slide .slide-table.rob, body.layout-slide .slide-table.rs { width: auto; }
col.c-insn  { width: 18ch; }      /* "I10: R12=R11*R10" fits */
col.c-op    { width: 15ch; }      /* "I4" plus the "issued" pill */
col.c-ht    { width: 6ch; }       /* "ht" in bold when head and tail coincide */
col.c-slot  { width: 3.5ch; }
col.c-busy  { width: 5.5ch; }
col.c-tag   { width: 9ch; }       /* "p128+" plus padding, bold in the slide layout */
col.c-num   { width: 6ch; }       /* cycle numbers up to 4 digits, bold in the slide layout */
.rob td, .rs td, .summary td { overflow: hidden; text-overflow: ellipsis; }
.rob input.q, .rs input.q, .summary input.q { width: 100%; min-width: 0; box-sizing: border-box; }
col.c-reg   { width: 5ch; }
col.c-arrow { width: 3ch; }       /* collapsed to nothing in the slide layout */
col.c-map-tag { width: 9ch; }
col.c-rdy   { width: 5.5ch; }     /* the ready bit beside a tag: as wide as its "rdy" heading */
body.layout-slide .map col.c-map-tag { width: auto; }   /* the tag takes the slack, the bit stays one character wide */



/* Instruction queue: a table, one row per entry, the head (next to dispatch) on top. */
.iq { width: auto; }
.iq th.iq-pc, .iq td.iq-pc { width: 2.6em; text-align: left; padding-left: 4px; }
.iq td.iq-pc { font: 700 10.5px system-ui, sans-serif; letter-spacing: 0.06em; color: var(--accent); }
.iq td.slot { color: var(--dim); }
.iq-item.next td.ins { font-weight: 700; }
.iq-item.next td { background: var(--focus); }
.iq-item.none td, .iq-item.empty td { color: var(--dim); }
.iq-item.hl-insn td { background: var(--follow); }
.iq-item.focus-insn td { background: var(--focus); }
.iq-more { font-size: 11px; color: var(--dim); }

/* Physical register file: a table, one row per p_i. */
.prf { width: auto; }
.prf th.rdy, .prf td.preg-ready { text-align: center; }
.prf td.preg-tag { font-weight: 700; text-align: left; }
.prf td.preg-val { text-align: right; min-width: 3em; }
.prf td.preg-who { text-align: left; color: var(--dim); font-size: 11.5px; white-space: nowrap; }
.prf td.preg-who b { color: var(--ink); font-weight: 500; }
.preg.free td { color: var(--dim); }
.preg.free td.preg-tag { font-weight: 400; }
.preg.ready td.preg-val { color: var(--ready); font-weight: 700; }
.preg.ready td.preg-ready { color: var(--ready); font-weight: 800; box-shadow: inset 0 0 0 2px var(--ready); }   /* outlined, like td.rdy.on */
.preg.pending td.preg-val, .preg.pending td.preg-ready { color: var(--dim); }
.preg.changed td { background: var(--changed); }
.preg.blocked td { background: var(--blocked); }
.preg.hl-insn td { background: var(--follow); }
.preg.none td { color: var(--dim); }

/* Complete buffer */
.cbuf { display: flex; flex-wrap: wrap; gap: 6px; font-family: var(--mono); font-size: 12.5px; min-height: 24px; align-items: center; }
.cbuf .none { color: var(--dim); font-style: italic; font-size: 11.5px; }
.cbuf-chip {
  display: flex; align-items: center; gap: 6px; padding: 3px 8px; border-radius: 6px;
  background: var(--panel); border: 1px solid var(--line); white-space: nowrap;
}
.cbuf-chip.changed { background: var(--changed); border-color: var(--changed-line); }
.cbuf-chip.waiting { border-style: dashed; }
.cbuf-chip .cbuf-stage { color: var(--dim); font-size: 11px; }
.cbuf-chip.hl-insn { background: var(--follow); border-color: var(--accent); }

/* Functional units: a group per kind (ALU, MUL, FPU), a box per unit.  (The
 * pipeline layout stacks them into a thin column: flow.css.) */
.alu-units { display: flex; flex-direction: row; align-items: flex-start; gap: 10px; min-width: 200px; }
.alu-cells { display: contents; }
.alu-kind { display: flex; flex-direction: column; gap: 6px; min-width: 150px; flex: 1 1 0; }
.alu-kind-name { display: flex; align-items: baseline; gap: 6px; font-size: 10.5px; color: var(--dim); letter-spacing: 0.04em; white-space: nowrap; }
.alu-kind-name b { font-size: 11px; letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink); }
.alu-kind-name .alu-ops { font-family: var(--mono); font-size: 11.5px; color: var(--ink); }
.alu-kind-name .alu-timing { margin-left: auto; font-style: italic; }
.alu-unit { border: 1px solid var(--line); border-radius: 8px; padding: 6px 8px; background: color-mix(in srgb, var(--st-x) 45%, var(--panel)); }
.alu-name { font-size: 10px; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim); margin-bottom: 4px; }
.alu-slots { display: flex; flex-direction: column; gap: 4px; min-height: 22px; font-family: var(--mono); font-size: 12.5px; }
.alu-slots .none { color: var(--dim); font-style: italic; font-size: 11.5px; }
.alu-chip {
  display: flex; align-items: center; gap: 6px; padding: 3px 6px; border-radius: 6px;
  background: var(--panel); border: 1px solid var(--line); cursor: default; white-space: nowrap;
}
.alu-chip.changed { background: var(--changed); border-color: var(--changed-line); }
.alu-chip.waiting { border-style: dashed; }
.alu-chip .alu-stage { color: var(--dim); font-size: 11px; margin-left: auto; }
.alu-chip.hl-insn { background: var(--follow); border-color: var(--accent); }
.alu-chip.focus-insn { background: var(--focus); }

/* A token: the chip that slides from one structure to the next when stepping. */
.token {
  position: absolute; left: 0; top: 0; padding: 2px 7px; border-radius: 6px;
  background: var(--accent); color: #fff; font: 700 11.5px var(--mono);
  box-shadow: 0 2px 6px rgba(0,0,0,0.25); will-change: transform; opacity: 0;
}

/* The pipeline diagram jumps to a cycle on click. */
.timeline .jump { cursor: pointer; }
.timeline th.jump:hover, .timeline td.jump:hover { outline: 1px solid var(--accent); outline-offset: -1px; }

/* ---------- tables: slide layout ---------- */

body.layout-slide .panel { background: transparent; border: none; border-radius: 0; padding: 0; }
body.layout-slide .panel-h { display: none; }
body.layout-slide .slide-table {
  width: 100%; border: 2px solid var(--slide-line); background: var(--slide-bg);
  font-size: 14px;
}
body.layout-slide .slide-table th, body.layout-slide .slide-table td {
  border: 1px solid var(--slide-line); padding: 4px 8px; text-align: left;
  white-space: nowrap;
}
body.layout-slide .slide-table thead th {
  background: var(--slide-head); color: var(--ink);
  font: 400 14px/1.35 system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;
  text-transform: none; letter-spacing: 0;
}
body.layout-slide .slide-table tr.ttl th { font-size: 16px; padding: 4px 8px; }
body.layout-slide .slide-table td { font-weight: 700; height: 1.9em; }
body.layout-slide .slide-table td.slot, body.layout-slide .slide-table td.busy { font-weight: 700; }
body.layout-slide .slide-table td.empty { color: transparent; }   /* blank, as on the slide */
body.layout-slide .slide-table tr.free td { color: transparent; }
body.layout-slide .slide-table tr.free td.slot { color: var(--ink); }
body.layout-slide .slide-table td .cell { text-align: left; min-width: 0; margin: 0; padding: 0 2px; }
body.layout-slide .slide-table td.empty .cell { color: transparent; }
/* A cell that just became empty is blank on the slide, not a yellow box. */
body.layout-slide .slide-table .cell:empty,
body.layout-slide .slide-table td.empty .cell.changed { background: transparent; border-color: transparent; }
body.layout-slide .slide-table tr.retired-row td { background: transparent; }
/* The slide has no arrow column: collapse it rather than hide it, so the fixed
 * column layout still sees three columns. */
body.layout-slide .map col.c-arrow { width: 0; }
body.layout-slide .map td.arrow, body.layout-slide .map th.arrow {
  padding: 0; border-left: none; border-right: none; font-size: 0; overflow: hidden;
}
body.layout-slide .map { width: 100%; }
body.layout-slide .ht b.h, body.layout-slide .ht b.t { color: var(--ink); }
body.layout-slide tr.head-row td:first-child { box-shadow: inset 4px 0 0 var(--head); }
body.layout-slide tr.tail-row td:first-child { box-shadow: inset -4px 0 0 var(--tail); }
body.layout-slide tr.head-row.tail-row td:first-child {
  box-shadow: inset 4px 0 0 var(--head), inset -4px 0 0 var(--tail);
}
body.layout-slide .free td { height: auto; }
body.layout-slide .taglist { display: block; min-height: 1.4em; font-size: 14px; font-weight: 700; }
body.layout-slide .taglist .tag {
  display: inline; border: none; background: none; padding: 0 1px; border-radius: 3px;
}
body.layout-slide .taglist .tag + .tag::before { content: ","; color: var(--ink); }
body.layout-slide .taglist .tag.next::before { content: none; }
body.layout-slide .taglist .tag.changed { background: var(--changed); }
body.layout-slide .taglist .tag.blocked { background: var(--blocked); }
body.layout-slide .taglist .none { color: transparent; }
body.layout-slide .cdb td .none { color: transparent; }
body.layout-slide .cdb .tag { color: var(--ink); font-weight: 700; border: none; background: none; padding: 0; }
body.layout-slide .cdb .tag.changed { background: var(--changed); }
body.layout-slide .cdb .tag.blocked { background: var(--blocked); }
body.layout-slide tr.issued td { color: var(--ink); }
body.layout-slide .pill { font-size: 9px; }
body.layout-slide .program-panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px 14px;
}
body.layout-slide .program-panel .panel-h { display: block; }
body.layout-slide .timeline-panel, body.layout-slide .events-panel, body.layout-slide .deps-panel,
body.layout-slide .ref-machine-panel, body.layout-slide .ref-program-panel, body.layout-slide .ref-policy-panel {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px 14px 14px;
}
/* ...kept short: neither column is taller than the ROB and the reservation
   stations beside them */
body.layout-slide .ref-machine-panel, body.layout-slide .ref-program-panel, body.layout-slide .ref-policy-panel { padding: 8px 12px 8px; }
body.layout-slide .ref-panels .panel-h { margin-bottom: 4px; }
body.layout-slide .timeline-panel .panel-h, body.layout-slide .events-panel .panel-h, body.layout-slide .deps-panel .panel-h,
body.layout-slide .ref-panels .panel-h { display: block; }

/* beside the tables, in place of the pipeline diagram: the machine, every
   setting of it under the machine panel's headings, and the program */
/* side by side: the machine, one column of settings, and the program */
.ref-panels { display: flex; align-items: flex-start; gap: 14px; min-width: 0; }
.ref-machine-panel { flex: 0 1 264px; }
/* beside the machine: the program, and under it the policy settings */
.ref-side { flex: 1 1 170px; min-width: 0; display: flex; flex-direction: column; gap: 14px; }
.ref-machine-panel, .ref-program-panel, .ref-policy-panel { min-width: 0; overflow-x: auto; }
.ref-panels .panel-h .dim { margin-left: 6px; text-transform: none; letter-spacing: 0; font-weight: 400; }
.ref-machine-note { font-size: 11px; margin: -2px 0 3px; }
.ref-machine-note.non-default { color: var(--accent); }
.ref-knobs, .ref-program { font-size: 12px; line-height: 15px; }
/* (the ids: quiz mode pads every cell of the grid for its input boxes) */
#ref-panels td, #ref-panels th { padding-top: 1px; padding-bottom: 1px; }
/* the program: the instructions and their numbers, and nothing about them */
.ref-program { width: auto; }
.ref-program td { border: none; white-space: nowrap; }
.ref-program td:first-child { padding-right: 10px; color: var(--dim); }
.ref-knobs tr.ref-group th {
  text-align: left; font: 700 10.5px system-ui, sans-serif;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim); border-bottom: 1px solid var(--line);
}
/* the groups of settings, one under the other */
.ref-groups > table { width: 100%; margin: 0 0 3px; }
.ref-groups > table:last-child { margin-bottom: 0; }
/* the functional units: a row each, a column for each of how many, latency, pipelined */
.ref-units tr.ref-facets th { text-align: right; font: 600 10.5px system-ui, sans-serif; color: var(--dim); white-space: nowrap; text-transform: none; letter-spacing: 0; border: none; }
.ref-units td.val { width: auto; }
.ref-units td.knob { white-space: nowrap; }
.ref-units td, .ref-units th { padding-left: 3px; padding-right: 3px; }
.ref-groups td.knob, .ref-groups th.ins { padding-left: 2px; }
.ref-knobs tbody tr.ref-group th { padding-top: 2px; }
.ref-knobs td.knob { white-space: normal; }
.ref-knobs td.val { width: 2.2em; text-align: right; vertical-align: top; }
.sidebar-group { align-items: flex-start; flex-direction: column; gap: 4px; }

/* ---------- the lesson page's two timing tables ---------- */

.summary.compare td.earlier { color: var(--good); font-weight: 700; }
.summary.compare td.later { color: var(--bad); font-weight: 700; }
.compare-note { font-size: 11px; margin-top: 6px; }
.compare-note .earlier { color: var(--good); font-weight: 700; }
.compare-note .later { color: var(--bad); font-weight: 700; }

/* ---------- pipeline diagram ---------- */

/* ---------- dependence graph ---------- */
/* In the slide layout the panel is as wide as the ROB and the free list
 * together (the first two columns of the grid), and no wider: the first
 * column is sized by the ROB / RS tables, and the graph must not widen it
 * (width: 0 removes the panel from the columns' max-content, min-width
 * stretches it back to whatever they are).  Inside, the graph is as wide as
 * it is drawn and the legend takes the room beside it, so nothing is empty;
 * a graph too wide for the panel scrolls, with the legend under it. */
body.layout-slide .deps-panel { width: 0; min-width: 100%; box-sizing: border-box; }
.deps-body { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 8px 22px; }
.deps-body > .deps-wrap { flex: 0 1 auto; max-width: 100%; }
.deps-body > .deps-legend { flex: 1 1 260px; min-width: 0; margin-top: 0; }
.deps-body .dep-note { max-width: none; }
.deps-wrap { overflow-x: auto; }
.deps-panel svg { display: block; font-family: var(--mono); }
.deps-panel .node circle { fill: var(--panel); stroke: var(--dim); stroke-width: 1.5; }
.deps-panel .node text { font-size: 11px; font-weight: 700; fill: var(--ink); text-anchor: middle; dominant-baseline: central; }
.deps-panel .node.st-D circle { fill: var(--st-d); stroke: var(--ink); }
.deps-panel .node.st-S circle { fill: var(--st-s); stroke: var(--ink); }
.deps-panel .node.st-X circle { fill: var(--st-x); stroke: var(--ink); }
.deps-panel .node.st-C circle { fill: var(--st-c); stroke: var(--ink); }
.deps-panel .node.st-R circle { fill: var(--st-r); stroke: var(--dim); }
.deps-panel .node.st-R text { fill: var(--dim); }
.deps-panel .edge path { fill: none; stroke-width: 1.6; }
.deps-panel .edge.raw path { stroke: var(--accent); }
.deps-panel .edge.resolved path { stroke: var(--ready); }
.deps-panel .edge.blocking path { stroke: var(--blocked-line); stroke-width: 2.6; }
.deps-panel .edge text { font-size: 9px; fill: var(--dim); text-anchor: middle; }
.deps-panel .edge.raw text { fill: var(--accent); }
.deps-panel .edge.resolved text { fill: var(--ready); }
.deps-panel .edge.blocking text { fill: var(--blocked-line); font-weight: 700; }
.deps-panel .edge.hl-insn path { stroke-width: 2.6; }
.deps-panel .edge.hl-insn text { font-weight: 700; }
.deps-panel .edge.dimmed { opacity: 0.25; }
.deps-panel .baseline { stroke: var(--line); stroke-width: 1; }
.deps-panel .col-h { font-size: 9px; fill: var(--dim); text-anchor: middle; }
.deps-panel .arrowhead.raw { fill: var(--accent); }
.deps-panel .arrowhead.resolved { fill: var(--ready); }
.deps-panel .arrowhead.blocking { fill: var(--blocked-line); }
.deps-legend { font-size: 11px; margin-top: 6px; display: grid; gap: 4px; }
.dep-note { display: block; max-width: 70ch; line-height: 1.5; }
.dep-key { font-family: var(--mono); font-weight: 700; padding: 0 4px; border-radius: 3px; border-bottom: 2px solid; }
.dep-key.raw { color: var(--accent); border-color: var(--accent); }
body.layout-slide .deps-panel .panel-h { display: block; }

.timeline-wrap { overflow-x: auto; }
.timeline { width: auto; }
.timeline th, .timeline td {
  text-align: center; min-width: 23px; padding: 2px 2px; font-size: 11.5px;
}
.timeline th.ins, .timeline td.ins { text-align: left; padding-right: 10px; min-width: 0; }
.timeline th.now { color: var(--accent); }
.timeline td.now { box-shadow: inset 0 0 0 1px var(--accent); }
.timeline td.inflight { background: color-mix(in srgb, var(--line) 35%, transparent); }
.timeline td.stage { font-weight: 700; border-radius: 3px; }
.timeline td.stage-D { background: var(--st-d); }
.timeline td.stage-S { background: var(--st-s); }
.timeline td.stage-X, .timeline td.stage-x { background: var(--st-x); }
.timeline td.stage-x { font-weight: 400; color: var(--dim); }
.timeline td.stage-C { background: var(--st-c); }
.timeline td.stage-R { background: var(--st-r); }

/* ---------- events ---------- */

.events { list-style: none; margin: 0; padding: 0; display: grid; gap: 4px; }
.events li {
  display: flex; gap: 10px; align-items: baseline;
  padding: 4px 8px; border-radius: 6px; background: var(--bg);
  border: 1px solid transparent; font-size: 13px;
}
.events li[data-blocking] { cursor: pointer; }
.events li[data-blocking]:hover { border-color: var(--blocked-line); }
.events li.dimmed { opacity: 0.45; }
.events li.current { border-color: var(--accent); background: var(--focus); opacity: 1; }
.events .kind {
  font-family: var(--mono); font-size: 10px; letter-spacing: 0.06em;
  padding: 1px 6px; border-radius: 4px; min-width: 68px; text-align: center;
  background: color-mix(in srgb, var(--accent) 14%, transparent); color: var(--accent);
}
.events .kind.STALL    { background: var(--blocked); color: var(--blocked-line); }
.events .kind.RETIRE   { background: color-mix(in srgb, var(--good) 18%, transparent); color: var(--good); }
.events .kind.COMPLETE { background: color-mix(in srgb, var(--good) 12%, transparent); color: var(--good); }
.events .quiet { color: var(--dim); font-style: italic; }

/* ---------- quiz mode ---------- */

.quiz-bar { margin: 14px 18px 0; display: grid; gap: 8px; }
.quiz-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.quiz-title { font-weight: 600; }
.quiz-progress { color: var(--dim); font-family: var(--mono); font-size: 12px; margin-left: auto; }
.quiz-spacer { flex: 1; }
.quiz-score { font-family: var(--mono); font-size: 12px; }
.quiz-name { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--dim); }
.quiz-name input {
  font: inherit; font-size: 13px; color: var(--ink); background: var(--bg);
  border: 1px solid var(--line); border-radius: 6px; padding: 4px 7px;
}
.quiz-name input.bad { border-color: var(--bad); }
.quiz-load { cursor: pointer; font-size: 13px; padding: 5px 10px; border: 1px solid var(--line); border-radius: 6px; }
.quiz-load:hover { border-color: var(--accent); color: var(--accent); }
.quiz-hint { font-size: 12px; color: var(--dim); line-height: 1.6; }
.quiz-bar button { font-size: 13px; }

input.q {
  font: inherit; font-family: var(--mono); font-size: 12.5px; text-align: left;
  background: var(--bg); color: var(--ink);
  border: 1px solid var(--line); border-radius: 4px; padding: 2px 4px;
  width: 4.4em;
}
input.q:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
input.q-ht   { width: 2.8em; text-align: center; }
input.q-busy { width: 2.4em; text-align: center; }
input.q-insn { width: 5.2em; }
input.q-num  { width: 2.9em; text-align: right; }
input.q-list { width: 100%; }
input.q.ok  { border-color: var(--good); background: var(--good-bg); }
input.q.bad { border-color: var(--bad);  background: var(--bad-bg); }

/* A homework problem's cells (quiz.js, "a homework problem's cells"): a
 * control for each kind of value.  A number field has the letter it is
 * written with before it (I, p), and no spinner: the cells are narrow. */
.for-fields, body.quiz-fields .for-text { display: none; }
body.quiz-fields .for-fields { display: inline; }
.q-box { display: flex; align-items: center; gap: 2px; min-width: 0; }
.q-pre { font-family: var(--mono); font-size: 12.5px; color: var(--dim); user-select: none; }
.q-box input.q-f { flex: 1 1 0; width: 0; min-width: 0; }
input.q-f[type="number"] { appearance: textfield; -moz-appearance: textfield; }
input.q-f[type="number"]::-webkit-inner-spin-button,
input.q-f[type="number"]::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
input.q-f-stage { text-align: right; }
input.q.q-f-ht { width: 100%; min-width: 0; box-sizing: border-box; text-align: center; }
.rob input.q.q-f-check, .rs input.q.q-f-check, input.q.q-f-check {
  width: 15px; height: 15px; margin: 0; padding: 0; vertical-align: middle; accent-color: var(--accent);
}
td.q-cell-check { text-align: center; }
select.q {
  font: inherit; font-family: var(--mono); font-size: 12.5px; width: 100%; min-width: 0; box-sizing: border-box;
  background: var(--bg); color: var(--ink); border: 1px solid var(--line); border-radius: 4px; padding: 1px 2px;
}
select.q:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 2px color-mix(in srgb, var(--accent) 25%, transparent); }
select.q.given { background: var(--retired); color: var(--ink); opacity: 1; cursor: default; }
select.q.ok  { border-color: var(--good); background: var(--good-bg); }
select.q.bad { border-color: var(--bad);  background: var(--bad-bg); }
input.q.q-f-check.ok  { outline: 2px solid var(--good); outline-offset: 1px; }
input.q.q-f-check.bad { outline: 2px solid var(--bad); outline-offset: 1px; }
input.q.q-f-check:disabled { cursor: default; }
/* a given cycle's bits are there to be read: drawn, not the browser's greyed-out box */
input.q.q-f-check.given, body.layout-slide.quiz input.q.q-f-check.given {
  appearance: none; -webkit-appearance: none; border: 1.5px solid var(--dim); border-radius: 3px; background: transparent;
}
input.q.q-f-check.given:checked, body.layout-slide.quiz input.q.q-f-check.given:checked {
  border-color: var(--accent);
  background: var(--accent) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 12'%3E%3Cpath d='M2.5 6.2l2.4 2.4 4.6-5' fill='none' stroke='%23fff' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E") center / 11px no-repeat;
}
/* what the cell cannot hold (a number out of range, anything but h, t or ht
   in the h/t column): outlined, named in .quiz-invalid, not saved */
input.q.invalid, body.layout-slide.quiz input.q.invalid {
  border-color: var(--bad); background: var(--bad-bg); box-shadow: 0 0 0 2px color-mix(in srgb, var(--bad) 30%, transparent);
}
.quiz-invalid { font-size: 12px; color: var(--bad); background: var(--bad-bg); border-radius: 6px; padding: 5px 10px; }
/* the free list: a slot for each register that can be free, in a row; the
 * columns that hold a letter and a number are a little wider */
body.quiz.quiz-fields .taglist, body.quiz.quiz-fields .free .taglist { display: flex; flex-wrap: wrap; gap: 4px 6px; }
body.quiz.quiz-fields .taglist .q-box, body.quiz.quiz-fields .cdb .q-box, body.quiz.quiz-fields .map .q-box { width: 4.6em; }
body.quiz.quiz-fields col.c-ht { width: 6ch; }
body.quiz.quiz-fields col.c-insn, body.quiz.quiz-fields col.c-op { width: 9ch; }
body.layout-slide.quiz.quiz-fields select.q { font-size: 14px; font-weight: 700; background: var(--slide-bg); border-color: color-mix(in srgb, var(--slide-line) 30%, transparent); }
body.layout-slide.quiz.quiz-fields .q-pre { font-size: 14px; font-weight: 700; color: var(--ink); }

body.quiz td { padding: 2px 3px; }
body.quiz .taglist, body.quiz .free .taglist { min-height: 0; display: block; }   /* the quiz input, not the slot grid */
body.layout-slide.quiz .slide-table td { height: auto; padding: 3px 5px; }
body.layout-slide.quiz input.q { font-size: 14px; font-weight: 700; background: var(--slide-bg); border-color: color-mix(in srgb, var(--slide-line) 30%, transparent); }
body.layout-slide.quiz input.q.ok  { background: var(--good-bg); border-color: var(--good); }
body.layout-slide.quiz input.q.bad { background: var(--bad-bg); border-color: var(--bad); }

/* ---------- legend ---------- */

.legend {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px 18px 24px; font-size: 12px; color: var(--dim);
}
.swatch {
  display: inline-block; padding: 1px 7px; border-radius: 4px;
  border: 1px solid var(--line); font-family: var(--mono); font-size: 11px;
  min-width: 20px;
}
.swatch.changed { background: var(--changed); border-color: var(--changed-line); }
.swatch.blocked-ex { background: var(--blocked); border-color: var(--blocked-line); }
.swatch.ready-ex { border-color: var(--ready); box-shadow: inset 0 0 0 1px var(--ready); color: var(--ready); font-weight: 800; }
.swatch.head-ex { color: var(--head); font-weight: 700; box-shadow: inset 3px 0 0 var(--head); }
.swatch.tail-ex { color: var(--tail); font-weight: 700; box-shadow: inset -3px 0 0 var(--tail); }

/* ---------- lessons: the "Programs" mode ---------- */

/* the mode switch in the top bar */
.mode { display: inline-flex; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; position: relative; }
.mode label {
  display: flex; align-items: center; padding: 5px 12px; cursor: pointer; user-select: none;
  font-size: 11px; text-transform: uppercase; letter-spacing: 0.06em; color: var(--dim);
}
.mode label + label { border-left: 1px solid var(--line); }
.mode input { position: absolute; opacity: 0; width: 0; height: 0; }
.mode label:has(input:checked) { background: var(--accent); color: #fff; }
.mode label:hover { color: var(--accent); }
.mode label:has(input:checked):hover { color: #fff; }
/* while Execution is selected, the tab it is executing from (Programs or
   Homework) is outlined: the switch says what the page does and to what */
.mode label.source { color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); background: var(--follow); }
/* the layout tabs in the view popover: same control, sized to the popover text */
.options-body .layout-tabs label { padding: 4px 10px; text-transform: none; letter-spacing: 0; font-size: 13px; gap: 0; }

/* the lesson page (and the homework page, built from the same parts)
   replaces the execution view, controls and all */
body.mode-lesson .pickers, body.mode-lesson .controls, body.mode-lesson .quiz-bar,
body.mode-lesson .grid, body.mode-lesson .legend,
body.mode-lesson .lesson-strip, body.mode-lesson .top-anchor, body.mode-homework .top-anchor,
body.mode-homework .pickers, body.mode-homework .controls, body.mode-homework .quiz-bar,
body.mode-homework .grid, body.mode-homework .legend,
body.mode-homework .lesson-strip { display: none !important; }
.homework-cycles { font-size: 15px; font-weight: 600; margin: 0 0 6px; }
.homework-howto { margin: 0; max-width: 70ch; line-height: 1.45; }
/* the homework page is two rows of two cards, each pair as tall as the
   other: the program and the machine, then what to do and the homework file */
.homework-cols { display: flex; flex-wrap: wrap; gap: 16px; align-items: stretch; }
.homework-cols > .lesson-block { box-sizing: border-box; flex: 1 1 340px; }
/* the program is as wide as its table; the machine has the rest, and is
   on a row of its own before it has fewer than two columns of settings */
.homework-top > .lesson-block:first-child { flex: 0 1 auto; }
.homework-top > .lesson-block:last-child { flex-basis: 560px; }
.homework-bottom > .lesson-block { display: flex; flex-direction: column; }
.homework-bottom .homework-howto { font-size: 13px; }
.homework-bottom .lesson-actions { margin-top: auto; padding-top: 10px; align-items: center; }
/* the machine: a table for each group of settings, in columns of one width,
   the lecture machine's value beside this one's, a row that differs marked */
.homework-knobs { display: grid; grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); gap: 10px 28px; align-items: start; }
.homework-group { width: 100%; font-size: 12px; line-height: 1.25; }
.homework-group td, .homework-group th { padding-top: 2px; padding-bottom: 2px; }
.homework-group td.knob { white-space: normal; }
.homework-group th:not(.ins) { width: 4.6em; }
.homework-group td.lecture { font-weight: 400; color: var(--dim); }
.homework-group tr.differs td { background: var(--changed); }
.homework-group tr.differs td.lecture { color: var(--ink); }
/* the homework file: its buttons, what the last download or load came to,
   and on the rail how far along each problem is */
.homework-set-title { margin: 0; font-size: 13px; font-weight: 600; color: var(--dim); }
.homework-set .lesson-h .dim { margin-left: 6px; }
.homework-set .quiz-load { font-size: 14px; padding: 8px 16px; }
.homework-set-note { margin: 10px 0 0; max-width: 70ch; font-family: var(--mono); font-size: 12px; line-height: 1.45; }
.homework-set-note:empty { display: none; }
.lesson-item[data-progress="started"] .homework-progress { color: var(--accent); }
.lesson-item[data-progress="done"] .homework-progress { color: var(--good); font-weight: 600; }

.lesson-view {
  display: grid; grid-template-columns: minmax(230px, 300px) minmax(0, 1fr);
  gap: 18px; padding: 16px 18px 32px; align-items: start;
}
.lesson-rail { display: grid; gap: 6px; position: sticky; top: 12px; }
.lesson-group { margin: 10px 0 0; }
.lesson-group:first-child { margin-top: 0; }
.lesson-item {
  display: flex; gap: 10px; align-items: flex-start; text-align: left;
  padding: 8px 10px; border-radius: 8px; font: inherit; color: var(--ink);
  background: var(--panel); border: 1px solid var(--line); cursor: pointer;
}
.lesson-item:hover { border-color: var(--accent); color: var(--ink); }
.lesson-item.current { border-color: var(--accent); background: var(--follow); box-shadow: inset 3px 0 0 var(--accent); }
.lesson-num { font-family: var(--mono); font-size: 11px; color: var(--dim); min-width: 1.6em; padding-top: 2px; }
.lesson-item-body { display: grid; gap: 2px; min-width: 0; }
.lesson-item-body b { font-size: 13px; }
.lesson-item-point { font-size: 11.5px; color: var(--dim); line-height: 1.35; }
.lesson-main { display: grid; gap: 16px; min-width: 0; }
.lesson-kicker { margin: 0; }
.lesson-title { font-size: 28px; margin: 0; letter-spacing: -0.01em; }
.lesson-point { font-size: 16px; margin: 0; max-width: 70ch; }
/* the left column stacks the program block and, under it, the result */
.lesson-col { display: grid; gap: 16px; min-width: 0; justify-items: start; }
.lesson-col > .lesson-block { width: 100%; box-sizing: border-box; }
/* ...which is only as wide as its two timing tables */
.lesson-col > #lesson-result { width: fit-content; max-width: 100%; overflow-x: auto; }
.lesson-cols { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr)); gap: 16px; align-items: start; }
.lesson-block {
  background: var(--panel); border: 1px solid var(--line); border-radius: 10px;
  padding: 12px 14px 14px; min-width: 0; overflow-x: auto;
}
.lesson-h { margin-bottom: 8px; }
.lesson-prose p { margin: 10px 0 0; max-width: 70ch; line-height: 1.55; }
.lesson-program { width: auto; }
.lesson-program td.waits { color: var(--accent); font-weight: 600; }
.lesson-deps { margin-top: 10px; }
.deps-sub { font-size: 12px; margin: 4px 0 6px; }
.deps-sub .dim { font-weight: 400; margin-left: 6px; }
.lesson-knobs { width: auto; }
.lesson-knobs td.knob { font-family: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif; }
.lesson-knobs th:not(.ins) { text-align: center; white-space: normal; max-width: 15em; line-height: 1.3; vertical-align: bottom; }
.lesson-knobs td.val { text-align: center; font-weight: 600; }
.lesson-knobs td.non-default { color: var(--accent); }
.lesson-knobs td.differs { background: var(--changed); }
.lesson-config { margin-top: 8px; font-family: var(--mono); font-size: 11px; }
/* The result: a column per machine, as wide as its timing table, the cycle
 * count over the table.  The totals and the timings are two containers (the
 * viewer fills each); display: contents puts their children in the one grid. */
.lesson-machines { display: grid; grid-template-columns: repeat(2, max-content); gap: 12px 56px; align-items: start; }
.lesson-totals, .lesson-timings { display: contents; }
.lesson-total { display: grid; gap: 3px; }
.lesson-total b { font-size: 34px; line-height: 1; font-family: var(--mono); }
.lesson-total span { font-size: 12px; color: var(--dim); }
.lesson-timing table { width: auto; }
.lesson-watch { margin: 6px 0 0; padding-left: 20px; line-height: 1.55; max-width: 70ch; }
.lesson-watch li + li { margin-top: 4px; }
/* With two machines: a heading over each machine's bullets. */
.lesson-watch li.lesson-watch-h {
  list-style: none; margin: 10px 0 2px -20px; font: 700 11px system-ui, sans-serif;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--dim);
}
.lesson-watch li.lesson-watch-h:first-child { margin-top: 0; }
.lesson-actions { display: flex; gap: 10px; flex-wrap: wrap; }
.lesson-actions button { font-size: 14px; padding: 8px 16px; }
@media (max-width: 900px) {
  .lesson-view { grid-template-columns: 1fr; }
  .lesson-rail { position: static; }
  /* one machine after the other, each count still over its own table */
  .lesson-machines { grid-template-columns: minmax(0, 1fr); }
  .lesson-total:nth-child(2) { order: 3; }
  .lesson-timing:nth-child(1) { order: 2; }
  .lesson-timing:nth-child(2) { order: 4; }
}

/* the lesson strip: under the controls in the execution view */
.lesson-strip { margin: 12px 18px 0; display: flex; align-items: center; gap: 12px; flex-wrap: wrap; padding: 8px 12px; }
.lesson-strip-title b { font-size: 14px; }
.lesson-strip-callout { flex: 1 1 320px; color: var(--dim); }
.lesson-strip-callout.callout {
  color: var(--ink); background: var(--changed); border: 1px solid var(--changed-line);
  border-radius: 6px; padding: 4px 10px;
}
/* the event note: its own row under the callout while stepping by event
   (PARKED: see EVENT_NOTE_ENABLED in viewer.js) */
.lesson-strip-event {
  flex-basis: 100%; color: var(--ink); background: var(--focus); border: 1px solid var(--accent);
  border-radius: 6px; padding: 4px 10px; line-height: 1.45;
}
.lesson-strip-event .kind { margin-right: 6px; }
@media print {
  .lesson-strip { display: none !important; }
  body.mode-lesson .grid, body.mode-lesson .slide-title,
  body.mode-homework .grid, body.mode-homework .slide-title { display: none !important; }
  body.mode-lesson .lesson-view, body.mode-homework .lesson-view { display: block !important; padding: 0; }
  body.mode-lesson .lesson-rail, body.mode-homework .lesson-rail { display: none; }
}

/* ---------- print: one cycle as a slide (or a blank worksheet in quiz mode) ----------
 * PARKED: the "print this cycle" button is hidden in index.html; these rules
 * still apply to a browser print but nothing in the product offers one. */

@media print {
  body { background: #fff; color: #000; font-size: 13px; }
  .topbar, .top-anchor, .controls, .quiz-bar, .slide-actions, .legend, .load-error,
  .timeline-panel, .events-panel, .program-panel, .deps-panel, .options,
  .pipeline-only { display: none !important; }
  .grid {
    display: grid !important; padding: 0; gap: 12px;
    grid-template-columns: 2.2fr 0.7fr 0.5fr 0.8fr;
    grid-template-areas:
      "title title title title"
      "rob   rob   map   cdb"
      "rob   rob   free  free"
      "rs    rs    .     .";
  }
  .record { display: none !important; }
  .slide-head { display: block !important; margin: 0; }
  .slide-title { display: block !important; text-align: center; font-size: 26px; margin: 0; }
  .panel { background: transparent; border: none; padding: 0; }
  .panel-h { display: none; }
  .rob-panel::before { display: none; }
  .slide-table { border: 2px solid #000 !important; background: #fff !important; font-size: 13px; }
  .slide-table th, .slide-table td { border: 1px solid #000 !important; padding: 3px 6px; text-align: left; }
  .slide-table thead th { background: #d9d9d9 !important; color: #000; text-transform: none; letter-spacing: 0; font: 400 13px system-ui, sans-serif; }
  .slide-table tr.ttl { display: table-row !important; }
  .slide-table tr.ttl th { font-size: 15px; }
  .slide-table td { font-weight: 700; height: 1.8em; color: #000; }
  .slide-table td.empty, .slide-table tr.free td, .taglist .none, .cdb .none { color: transparent !important; }
  .slide-table tr.free td.slot { color: #000 !important; }
  .map td.arrow, .map th.arrow { display: none; }
  .cell, .tag { background: transparent !important; border-color: transparent !important; }
  .taglist { display: block; } .taglist .tag { display: inline; border: none; padding: 0; } .free-slot { display: none; }
  .taglist .tag + .tag::before { content: ","; } .tag.next::before { content: none !important; }
  .ready { color: #000; }
  td.rdy.on { box-shadow: none; color: #000; }
  .pill { display: none; }
  tr.head-row td:first-child, tr.tail-row td:first-child { box-shadow: none; }
  input.q, select.q { border: 1px solid #bbb; background: #fff; color: #000; }
  input.q.ok, input.q.bad { background: #fff; border-color: #bbb; }
}

/* ---------- last word ---------- */

/* The hidden attribute must beat every display rule above (.quiz-bar is a
   grid, td.cluster-col is a table-cell, ...).  Kept last, with !important, so
   it wins under a real cascade and under a naive last-rule-wins one alike. */
[hidden] { display: none !important; }
