/* practice.css - what is specific to the practice site, and nothing else.
 *
 * Everything that used to be here as an override of app.css is gone: style.css is
 * Primer now, so the tokens, the Box treatment, the button and control styling and
 * the dark panels all arrive through app.css (which is generated from style.css
 * plus the simulator's additions). What is left is genuinely practice-only.
 *
 * The header bar is NOT here either - it comes from the simulator's own markup
 * through the practice-markup slice, so it stays in step with the other apps by
 * being the same markup rather than by being kept similar. shell.js only moves the
 * `here` marker onto the Practice link.
 */

/* --------------------------------------------------- breadcrumb and sub-line */
/* The breadcrumb IS the h1, the way a repo page's owner/name is, so the centred
   heading style.css gives an h1 has to be undone for this page. */
.gh-crumb {
  max-width: 1280px;
  margin: 0 auto;
  padding: 16px 24px 0;
  text-align: left;
  font-size: 20px;
  font-weight: 400;
  display: flex;
  align-items: center;
  gap: 6px;
  flex-wrap: wrap;
}
.gh-crumb a { color: var(--accent-fg); text-decoration: none; font-weight: 600; }
.gh-crumb a:hover { text-decoration: underline; }
.gh-crumb .sep { color: var(--fg-muted); }
.gh-crumb .here { font-weight: 600; color: var(--fg-default); }
.gh-crumb .gh-label { font-size: 12px; margin-left: 6px; }
.gh-sub {
  max-width: 1280px;
  margin: 4px auto 0;
  padding: 0 24px;
  text-align: left;
  font-size: 14px;
  color: var(--fg-muted);
}

/* Every link inside a container this site owns, so none is left at the browser's
   default blue - legible on white, nearly invisible on a dark canvas. */
.gh-page a, .gh-readme a, .ex-sheet-body a { color: var(--accent-fg); }

/* 64px upstream fits three digits; the practice pages' default run length is four
   ("2000"), and a field that clips its own value reads as a rendering fault. */
#maxTimeInput { width: 76px; }

/* ------------------------------------------------------- underline tab strip */
.gh-tabs {
  max-width: 1280px;
  margin: 12px auto 0;
  padding: 0 24px;
  display: flex;
  gap: 8px;
  border-bottom: 1px solid var(--border-default);
}
.gh-tab {
  appearance: none;
  background: none;
  border: none;
  border-bottom: 2px solid transparent;
  cursor: pointer;
  color: var(--fg-default);
  font: inherit;
  font-size: 14px;
  padding: 8px 12px 10px;
  margin-bottom: -1px;
  display: flex;
  align-items: center;
  gap: 6px;
  border-radius: var(--radius) var(--radius) 0 0;
}
.gh-tab:hover { background: var(--canvas-subtle); }
.gh-tab.selected { border-bottom-color: #fd8c73; font-weight: 600; }
@media (prefers-color-scheme: dark) { .gh-tab.selected { border-bottom-color: #f78166; } }
.gh-tab svg { width: 16px; height: 16px; fill: var(--fg-muted); }

/* ------------------------------------------ the exercise sheet, a Primer dialog */
.ex-backdrop {
  position: fixed;
  inset: 0;
  z-index: 2000;
  display: none;
  align-items: center;
  justify-content: center;
  padding: 24px;
  background: rgba(31, 35, 40, 0.5);
}
.ex-backdrop.open { display: flex; }
/* Scroll belongs to the sheet's body while it is up; without this the page behind
   it scrolls under the pointer and the prompt appears to drift. */
body.ex-sheet-open { overflow: hidden; }
.ex-sheet {
  background: var(--canvas-default);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-overlay);
  width: 100%;
  max-width: 900px;
  max-height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.ex-sheet-head {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--border-default);
  flex-shrink: 0;
}
.ex-kicker {
  font-size: 12px;
  font-weight: 500;
  color: var(--fg-muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
}
.ex-sheet-title { font-size: 16px; font-weight: 600; color: var(--fg-default); }
.ex-sheet-meta {
  background: var(--canvas-subtle);
  border: 1px solid var(--border-muted);
  border-radius: 2em;
  padding: 2px 10px;
  font-size: 12px;
  color: var(--fg-muted);
}
.ex-close {
  margin-left: auto;
  border: none;
  background: none;
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  color: var(--fg-muted);
  padding: 4px 6px;
  border-radius: var(--radius);
}
.ex-close:hover { background: var(--canvas-subtle); color: var(--fg-default); }
.ex-sheet-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: 16px;
  font-size: 14px;
  line-height: 1.6;
  color: var(--fg-default);
}
.ex-sheet-body > * + * { margin-top: 16px; }
.ex-sheet-body h3 { font-size: 14px; font-weight: 600; }
.ex-sheet-body ul, .ex-sheet-body ol { padding-left: 22px; }
.ex-sheet-body li + li { margin-top: 4px; }
.ex-sheet-body code {
  font-family: var(--font-mono);
  font-size: 85%;
  background: var(--canvas-subtle);
  border-radius: var(--radius);
  padding: 0.2em 0.4em;
}
/* GitHub's fenced code block. A block, so it is not the same thing as inline code. */
.ex-sheet-body .ex-code {
  background: var(--canvas-subtle);
  border: 1px solid var(--border-muted);
  border-radius: var(--radius);
  padding: 12px 16px;
  font-family: var(--font-mono);
  font-size: 85%;
  line-height: 1.45;
  color: var(--fg-default);
  white-space: pre;
  overflow-x: auto;
}
.ex-sheet-body table { border-collapse: collapse; font-size: 14px; }
.ex-sheet-body th, .ex-sheet-body td {
  border: 1px solid var(--border-default);
  padding: 6px 13px;
  text-align: left;
}
.ex-sheet-body th { background: var(--canvas-subtle); font-weight: 600; }
.ex-sheet-body tr:nth-child(2n) td { background: var(--canvas-subtle); }
.ex-sheet-body .ex-note { font-size: 12px; color: var(--fg-muted); }
.ex-sheet-foot {
  flex-shrink: 0;
  border-top: 1px solid var(--border-default);
  background: var(--canvas-subtle);
  padding: 12px 16px;
  text-align: right;
}
.btn.ex-start { padding: 6px 16px; font-size: 14px; }

/* ------------- the verdict, a Primer state Label in the Console box header ---- */
/* "no checks reported" is the honest state for a design whose checker prints
   neither - the CPU problems are judged by the CPU / Memory Model card. */
.ex-verdict {
  margin-left: auto;
  margin-right: 8px;
  background: var(--canvas-default);
  border: 1px solid var(--border-default);
  border-radius: 2em;
  padding: 1px 10px;
  font-size: 12px;
  font-weight: 500;
  color: var(--fg-muted);
}
.ex-verdict.pass { background: var(--success-subtle); border-color: var(--success-fg); color: var(--success-fg); }
.ex-verdict.fail { background: var(--danger-subtle); border-color: var(--danger-fg); color: var(--danger-fg); }

/* -------------------------------------------- the hub, as a repo file listing */
.gh-page {
  max-width: 1328px;
  margin: 0 auto;
  padding: 16px 24px 32px;
}
.gh-box {
  background: var(--canvas-default);
  border: 1px solid var(--border-default);
  border-radius: var(--radius);
  overflow: hidden;
}
.gh-box-header {
  display: flex;
  align-items: center;
  gap: 12px;
  /* eight chips plus two labels and the count do not fit a narrow window, and a
     header that overflows would clip the last chips rather than reveal them. */
  flex-wrap: wrap;
  row-gap: 8px;
  padding: 8px 16px;
  background: var(--canvas-subtle);
  border-bottom: 1px solid var(--border-default);
  font-size: 14px;
}
.gh-filter-label { color: var(--fg-muted); font-weight: 600; white-space: nowrap; }
.gh-chips { display: flex; gap: 6px; flex-wrap: wrap; }
/* A chip carries the pill geometry of the .gh-label it filters on, so the control
   and the thing it selects read as the same object - and the colour therefore says
   which ROW a chip belongs to (neutral for category, blue for level, exactly as
   the row Labels are), never whether it is selected. Selection is .on below. */
.gh-chip {
  border: 1px solid var(--border-default);
  border-radius: 2em;
  padding: 0 10px;
  font: inherit;
  font-size: 12px;
  line-height: 20px;
  background: var(--canvas-default);
  color: var(--fg-muted);
  white-space: nowrap;
  cursor: pointer;
}
.gh-chip:hover { border-color: var(--fg-muted); }
.gh-chip.level { color: var(--accent-fg); border-color: var(--accent-fg); }
/* The site's existing selected-state idiom (.layout-btn.active,
   .hierarchy-node-row.active). Deliberately NOT a blue fill: there is no
   --accent-emphasis token here, so filling would mean painting --accent-fg as a
   background and finding a text colour for it - the --fg-on-emphasis trap.

   The inset ring is a SECOND encoding of the same bit, and it is not decoration.
   A category chip's on-state moves three things (fill, text, border), but a level
   chip is already accent-coloured when off, so the tint was all it had left to
   say - measured at 1.16:1 against the dark-mode canvas (#0d1117 -> #121d2f),
   which is not a difference anyone can see on a 20px pill. Doubling the ring
   weight with an inset shadow rather than a wider border is what keeps the two
   states the same size, so toggling a chip cannot reflow the row. */
.gh-chip.on {
  background: var(--accent-subtle);
  border-color: var(--accent-fg);
  color: var(--accent-fg);
  box-shadow: inset 0 0 0 1px var(--accent-fg);
}
.gh-chip:focus-visible { outline: 2px solid var(--accent-fg); outline-offset: 1px; }
.gh-count { margin-left: auto; color: var(--fg-muted); font-size: 12px; }
.gh-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 16px;
  border-top: 1px solid var(--border-muted);
  font-size: 14px;
}
.gh-row:first-of-type { border-top: none; }
.gh-row:hover { background: var(--canvas-subtle); }
/* Only ever shown when nothing matched, so it always sits directly under the
   header, whose own border-bottom would otherwise double up with this one. */
.gh-empty { border-top: none; color: var(--fg-muted); }
.gh-empty:hover { background: none; }
.gh-clear {
  border: 0;
  background: none;
  padding: 0;
  font: inherit;
  font-size: 14px;
  color: var(--accent-fg);
  cursor: pointer;
}
.gh-clear:hover { text-decoration: underline; }
/* One token drives both halves of the artwork. The glyphs are fill-drawn except the
   combinational gate's outline, which is stroked, so `color` is what is set and both
   `fill` and the glyph's own stroke="currentColor" follow from it - rather than a bare
   `fill`, which used to leave the stroked glyph resolving currentColor against the
   inherited --fg-default and so a shade darker than its neighbours. The viewBox is
   45x40, and preserveAspectRatio letterboxes it inside this square rather than
   distorting it. */
.gh-row-icon { width: 16px; height: 16px; color: var(--fg-muted); fill: currentColor; flex-shrink: 0; }
.gh-row a { color: var(--fg-default); text-decoration: none; }
.gh-row a:hover { color: var(--accent-fg); text-decoration: underline; }
.gh-row .gh-slug { color: var(--fg-muted); font-family: var(--font-mono); font-size: 12px; }
.gh-row .gh-blurb {
  color: var(--fg-muted);
  font-size: 12px;
  margin-left: auto;
  padding-left: 16px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.gh-row .gh-labels { display: flex; gap: 6px; flex-shrink: 0; }
.gh-label {
  border: 1px solid var(--border-default);
  border-radius: 2em;
  padding: 0 8px;
  font-size: 12px;
  line-height: 20px;
  color: var(--fg-muted);
  white-space: nowrap;
}
.gh-label.level { color: var(--accent-fg); border-color: var(--accent-fg); }
.gh-readme {
  margin: 16px 0 0;
  font-size: 14px;
  color: var(--fg-muted);
}

@media (max-width: 900px) {
  .gh-row .gh-blurb, .gh-row .gh-slug { display: none; }
  .gh-crumb, .gh-tabs, .gh-sub { padding-left: 16px; padding-right: 16px; }
}

/* ---------------------------------------------------------------------------
   The Netlist Viewer, on a page whose manifest entry says "synthesis": true.

   synth.css already carries every .rf-node* rule, because the nodes here are the
   same absolutely-positioned divs React Flow renders in synthesis.html - that is
   why this file needs so little. What is missing there is only the plumbing React
   Flow itself supplied: the two transformed layers, and the edges, which it drew
   from its own stylesheet (loaded from a CDN, so not available here).
   --------------------------------------------------------------------------- */
/* touch-action: none, where the waveform uses pan-y - and the difference is the
   product, not a preference. A waveform pans along ONE axis, so a page that keeps
   scrolling vertically over it loses nothing; a netlist is two-dimensional, so one
   finger has to be able to move it in both. React Flow's own pane does the same, which
   is also what synthesis.html gets today. The cost is real and bounded: a touch that
   lands inside this 520px box scrolls the graph rather than the page. */
#flowRoot { touch-action: none; cursor: grab; }
.pn-nodes, .pn-edges {
  position: absolute;
  inset: 0;
  transform-origin: 0 0;
}
/* Edges under nodes, as in React Flow, so a wire never crosses a gate symbol. */
.pn-edges { width: 100%; height: 100%; overflow: visible; pointer-events: none; }
/* Beats .rf-node's own `position: relative` (two classes to one), which is what
   lets a node be placed by the layout the engine already computed. */
.pn-nodes > .rf-node { position: absolute; }
.pn-edge {
  fill: none;
  stroke: var(--border-default);
  stroke-width: 1.5;
}
.pn-edge.bus { stroke-width: 3; }
/* paint-order draws the halo behind the glyphs, which is how a net name stays
   readable over a wire without a background rectangle to keep in step with it. */
.pn-edge-label {
  font: 9px "SF Mono", Menlo, Consolas, monospace;
  fill: var(--fg-muted);
  text-anchor: middle;
  paint-order: stroke;
  stroke: var(--canvas-subtle);
  stroke-width: 3px;
  stroke-linejoin: round;
}
