/* ECE 211 interactive notes: shared theme.
   Light palette on :root; dark via media query (system) and [data-theme] (explicit).
   Typography is system font stacks by deliberate choice (zero font payload):
   system-ui for display and UI, the best available system serif for body text.
   KaTeX ships its own fonts, which are required for math and are the only
   downloaded fonts on the site.

   The palette follows the NC State brand (brand.ncsu.edu). Wolfpack Red #CC0000
   is reserved for chrome (links, eyebrows, primary buttons), so that the accent
   always reads as navigation; the hover-link highlight is Carmichael Aqua, whose
   complementary hue keeps a highlighted element distinct from an accented one
   under red-green color vision deficiency. Neutrals are the brand black tints.
   Dark mode cannot use Wolfpack Red directly (3.1:1 on the dark ground, below
   the text threshold), so it uses the 40 percent brand tint at 5.5:1. */

:root {
  --bg: #F2F2F2;
  --surface: #FFFFFF;
  --panel: #FAFAFA;
  --ink: #1A1A1A;
  --ink2: #4D4D4D;
  --line: #D6D6D6;
  --line2: #E8E8E8;
  --wire: #3D3D3D;
  --comp: #2B2B2B;
  --accent: #CC0000;            /* Wolfpack Red */
  --accent-soft: rgba(204, 0, 0, 0.10);
  --on-accent: #FFFFFF;         /* text on an accent-filled surface */
  --hl: #008473;                /* Carmichael Aqua */
  --hl-soft: rgba(0, 132, 115, 0.14);
  --hl-strong: rgba(0, 132, 115, 0.30);
  --grid: rgba(0, 0, 0, 0.06);
  --c1: #427E93;                /* Innovation Blue */
  --c2: #6F7D1C;                /* Genomic Green */
  --c3: #4156A1;                /* Bio-Indigo */
  --neg: #427E93;  /* power supplied */
  --pos: #D14905;  /* power absorbed, Pyroman Flame */
  --ok: #6F7D1C;
  /* Part rails: Genomic Green (shaded), Carmichael Aqua, Pyroman Flame (tinted),
     Bio-Indigo. The green is shaded and the flame tinted so that the pair, which
     collapses to a single hue under protanopia, stays separated by lightness;
     the worst-case pairwise separation across normal, protan, deutan, and tritan
     simulation is dE 23.7, and every rail clears 3:1 on both grounds. */
  --p1: #3B430F;
  --p2: #008473;
  --p3: #D4632B;
  --p4: #4156A1;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.06), 0 4px 14px rgba(0, 0, 0, 0.05);

  /* Two font stacks, and four role tokens defined in terms of them. Every rule
     names a role, never a stack, so the typeface of a whole class of elements is
     changed on one line here rather than in twenty rules.
       --f-label    uppercase tracked labels: nav, eyebrows, callout tags
       --f-control   interactive furniture: buttons, tabs, chips, slider labels
       --f-num       figures for reading and comparing: readouts, table numerals
       --f-fig       text drawn inside the schematics
     Monospace earns its place in --f-num (digits must align) and --f-fig (short
     symbolic labels). It is a poor fit for --f-label, which is set uppercase and
     tracked, so that role takes the display face.
     The monospace stack is ordered so that every platform reaches a designed face
     before the generic: SF Mono on Apple (through ui-monospace), Consolas on
     Windows, Noto Sans Mono on ChromeOS and Fedora, Liberation or DejaVu elsewhere
     on Linux, Roboto Mono on Android. Cascadia Mono is named rather than Cascadia
     Code, whose programming ligatures would rewrite sequences such as -> in a
     label. Courier New is deliberately absent: it is universal but too light and
     too narrow to carry text at these sizes. */
  --f-display: system-ui, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --f-body: Charter, "Bitstream Charter", "Iowan Old Style", Georgia, Cambria, "Times New Roman", serif;
  --f-mono: ui-monospace, "SF Mono", SFMono-Regular, Menlo, Monaco, "Cascadia Mono",
            Consolas, "Noto Sans Mono", "Noto Mono", "Liberation Mono", "Roboto Mono",
            "DejaVu Sans Mono", monospace;
  --f-math: "STIX Two Math", "Cambria Math", Cambria, Georgia, "Times New Roman", serif;
  --f-ui: var(--f-display);
  --f-label: var(--f-display);
  --f-control: var(--f-mono);
  --f-num: var(--f-mono);
  --f-fig: var(--f-mono);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #131313;
    --surface: #1C1C1C;
    --panel: #181818;
    --ink: #EDEDED;
    --ink2: #ABABAB;
    --line: #363636;
    --line2: #292929;
    --wire: #CFCFCF;
    --comp: #DADADA;
    --accent: #E06666;
    --accent-soft: rgba(224, 102, 102, 0.14);
    --on-accent: #1A0505;
    --hl: #3FC7B0;
    --hl-soft: rgba(63, 199, 176, 0.16);
    --hl-strong: rgba(63, 199, 176, 0.32);
    --grid: rgba(255, 255, 255, 0.07);
    --c1: #7EB8CC;
    --c2: #A8B84A;
    --c3: #8899E0;
    --neg: #7EB8CC;
    --pos: #F0834A;
    --ok: #A8B84A;
    --p1: #A1AB6B;
    --p2: #339D8F;
    --p3: #D14905;
    --p4: #6778B4;
    --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.3);
  }
}
:root[data-theme="dark"] {
  --bg: #131313;
  --surface: #1C1C1C;
  --panel: #181818;
  --ink: #EDEDED;
  --ink2: #ABABAB;
  --line: #363636;
  --line2: #292929;
  --wire: #CFCFCF;
  --comp: #DADADA;
  --accent: #E06666;
  --accent-soft: rgba(224, 102, 102, 0.14);
  --on-accent: #1A0505;
  --hl: #3FC7B0;
  --hl-soft: rgba(63, 199, 176, 0.16);
  --hl-strong: rgba(63, 199, 176, 0.32);
  --grid: rgba(255, 255, 255, 0.07);
  --c1: #7EB8CC;
  --c2: #A8B84A;
  --c3: #8899E0;
  --neg: #7EB8CC;
  --pos: #F0834A;
  --ok: #A8B84A;
  --p1: #A1AB6B;
  --p2: #339D8F;
  --p3: #D14905;
  --p4: #6778B4;
  --shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 4px 14px rgba(0, 0, 0, 0.3);
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: 16.5px;
  line-height: 1.66;
  -webkit-text-size-adjust: 100%;
}
/* Motion preference. Animations run by default; the top-right toggle in
   _layouts/base.njk sets data-anim="off" on the root element (persisted in
   localStorage). The OS reduced-motion setting keeps instant scrolling, but
   the animation kill switch is the explicit toggle, not the media query:
   a frozen flow overlay would otherwise linger as meaningless dashes. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}
:root[data-anim="off"] *,
:root[data-anim="off"] *::before,
:root[data-anim="off"] *::after { animation: none !important; transition: none !important; }
/* !important: setFlow() drives the overlay's visibility as an inline style */
:root[data-anim="off"] .fig .flowline { visibility: hidden !important; }

main { max-width: 860px; margin: 0 auto; padding: 0 20px 96px; }

a { color: var(--accent); text-underline-offset: 3px; }
:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; border-radius: 4px; }

/* ---------- header & nav ---------- */
.masthead { max-width: 860px; margin: 0 auto; padding: 44px 20px 10px; }
.eyebrow {
  font-family: var(--f-label); font-size: 12.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--accent); margin: 0 0 10px;
}
/* breadcrumb link back to the landing page; the arrow sits outside the text
   flow so the eyebrow stays aligned with the heading */
.eyebrow .crumb {
  color: inherit; text-decoration: none; position: relative;
  border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent);
}
.eyebrow .crumb::before {
  content: "\2190"; position: absolute; right: 100%; padding-right: 0.4em;
  border-bottom: 0; opacity: 0.75;
}
.eyebrow .crumb:hover { border-bottom-color: var(--accent); }
.eyebrow .crumb:hover::before { opacity: 1; }
h1 {
  font-family: var(--f-display);
  font-size: clamp(1.7rem, 4.5vw, 2.4rem); line-height: 1.12; margin: 0 0 12px;
  letter-spacing: -0.022em; font-weight: 700; text-wrap: balance;
}
.dek { color: var(--ink2); max-width: 62ch; margin: 0 0 8px; }

/* Authorship. The byline sits under the title and the acknowledgment closes the
   page, as on a paper; both take their text from src/_data/site.json. */
.byline { margin: 0 0 18px; line-height: 1.4; }
.byline-name {
  display: block; font-family: var(--f-display); font-weight: 600;
  font-size: 15.5px; color: var(--ink);
}
.byline-affil { display: block; font-size: 14px; color: var(--ink2); }

.hintcard {
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  margin: 18px 0 0; padding: 12px 16px;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  font-size: 15px; color: var(--ink2); box-shadow: var(--shadow);
}
.hintcard .tm { font-family: var(--f-math); font-size: 1.05em; }
.hintcard strong { color: var(--hl); }

.topnav {
  position: sticky; top: 0; z-index: 50;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--line);
  margin-top: 22px;
}
.topnav .rail {
  max-width: 860px; margin: 0 auto; padding: 8px 20px;
  display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none;
}
.topnav .rail::-webkit-scrollbar { display: none; }
.topnav a {
  font-family: var(--f-label); font-size: 12px; letter-spacing: 0.06em;
  text-transform: uppercase; text-decoration: none; white-space: nowrap;
  color: var(--ink2); padding: 5px 10px; border-radius: 999px; border: 1px solid transparent;
}
.topnav a:hover { color: var(--accent); border-color: var(--line); }
.topnav a.here { color: var(--accent); border-color: var(--accent); background: var(--accent-soft); }

/* fixed display-preference toggles (theme, motion); markup in _layouts/base.njk */
.prefs { position: fixed; top: 10px; right: 12px; z-index: 60; display: flex; gap: 6px; }
.prefs button {
  font-family: var(--f-label); font-size: 11px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink2);
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  border: 1px solid var(--line); border-radius: 999px;
  padding: 5px 11px; cursor: pointer;
}
.prefs button:hover { color: var(--accent); border-color: var(--accent); }

/* ---------- sections ---------- */
section { margin-top: 64px; scroll-margin-top: 64px; }
.sec-eyebrow {
  font-family: var(--f-label); font-size: 12.5px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink2); margin: 0 0 6px;
}
h2 {
  font-family: var(--f-display); font-size: 1.5rem; font-weight: 650;
  margin: 0 0 10px; letter-spacing: -0.018em; text-wrap: balance;
}
h3 {
  font-family: var(--f-display); font-size: 1.1rem; font-weight: 600;
  margin: 26px 0 8px; letter-spacing: -0.01em;
}
p { max-width: 68ch; }
section > p, section > .note, section > .warncard { margin-left: 0; }

.note, .warncard {
  border: 1px solid var(--line); border-inline-start: 3px solid var(--accent);
  background: var(--surface); border-radius: 8px;
  padding: 10px 16px; margin: 16px 0; font-size: 15px; max-width: 70ch;
}
.warncard { border-inline-start-color: var(--pos); }
.note .tag, .warncard .tag {
  font-family: var(--f-label); font-size: 11.5px; letter-spacing: 0.12em;
  text-transform: uppercase; display: block; margin-bottom: 2px; color: var(--accent);
}
.warncard .tag { color: var(--pos); }

/* ---------- figure panels (graph paper) ---------- */
.fig {
  background:
    linear-gradient(var(--grid) 1px, transparent 1px) 0 0 / 24px 24px,
    linear-gradient(90deg, var(--grid) 1px, transparent 1px) 0 0 / 24px 24px,
    var(--panel);
  border: 1px solid var(--line); border-radius: 12px;
  padding: 10px; margin: 14px 0; overflow-x: auto;
}
.fig svg { display: block; width: 100%; height: auto; min-width: 320px; }
.figcap { font-size: 14px; color: var(--ink2); margin: -4px 2px 18px; max-width: 70ch; }
.figcap > p { margin: 0 0 6px; }

/* build-time KaTeX output */
.katex { font-size: 1.08em; }
.eq .katex-display {
  margin: 0; text-align: left;
  overflow-x: auto; overflow-y: hidden;
  padding: 8px 2px 12px;
}
.eq .katex-display > .katex { text-align: left; }
.katex [data-ref] {
  cursor: pointer; border-radius: 5px; padding: 0 0.15em;
  transition: background 0.12s, box-shadow 0.12s;
}
.katex [data-ref]:hover, .katex [data-ref].hv, .katex [data-ref].hl {
  background: var(--hl-soft);
  box-shadow: inset 0 0 0 1px var(--hl-strong);
}

/* SVG primitives */
.fig .w   { stroke: var(--wire); stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.fig .st  { stroke: var(--comp); stroke-width: 2; fill: none; stroke-linecap: round; stroke-linejoin: round; }
.fig .fillpanel { fill: var(--panel); }
.fig .nd  { fill: var(--wire); stroke: none; }
.fig .term { fill: var(--panel); stroke: var(--wire); stroke-width: 2; }
.fig text { fill: var(--ink); font-family: var(--f-fig); font-size: 13.5px; }
.fig text.mt { font-family: var(--f-math); font-style: italic; font-size: 15.5px; }
.fig text.lab { font-style: normal; font-family: var(--f-fig); font-size: 12.5px; fill: var(--ink2); }
.fig text.pm { font-style: normal; font-family: var(--f-fig); font-size: 13px; font-weight: 700; fill: var(--ink2); }
.fig .cur line, .fig .cur path { stroke: var(--accent); stroke-width: 2; fill: none; stroke-linecap: round; }
.fig .cur polygon { fill: var(--accent); stroke: none; }
.fig .cur text { fill: var(--accent); }
.fig .looparrow path { stroke: var(--c3); stroke-width: 2; fill: none; }
.fig .looparrow polygon { fill: var(--c3); }
.fig .looparrow text { fill: var(--c3); font-family: var(--f-fig); font-size: 12px; font-style: normal; }
.fig .blob path {
  stroke: var(--hl); stroke-width: 2; stroke-dasharray: 7 6;
  fill: var(--hl-soft);
}
.fig .flowline { fill: none; stroke-width: 3.4; stroke-linecap: round;
  stroke-dasharray: 0.5 10.5; animation: flowmove var(--dur, 1.6s) linear infinite; }
@keyframes flowmove { to { stroke-dashoffset: -11; } }

/* linkable + highlight (hover .hv / persistent .hl share styling) */
.lk { cursor: pointer; }
g.lk :is(path, line, polyline, circle, rect, polygon) {
  transition: stroke 0.12s, fill 0.12s, stroke-width 0.12s;
}
g.hv :is(path, line, polyline, rect)    { stroke: var(--hl) !important; }
g.hl :is(path, line, polyline, rect)    { stroke: var(--hl) !important; }
g.hv circle, g.hl circle { stroke: var(--hl) !important; }
g.hv circle.nd, g.hl circle.nd { fill: var(--hl) !important; stroke: none !important; }
g.hv polygon, g.hl polygon { fill: var(--hl) !important; stroke: none; }
g.hv text, g.hl text { fill: var(--hl) !important; }
/* The highlight carries a second channel, independent of hue: the stroke thickens.
   Colour alone is not sufficient. The highlight sits close in lightness to the
   near-black wires, so a thin stroke changes hue without changing weight, and the
   dashed surfaces and the mesh zones are drawn in --hl at rest, so for those the
   colour does not change at all. The weight change also survives colour vision
   deficiency and greyscale printing. */
g.hv :is(path, line, polyline, rect, circle),
g.hl :is(path, line, polyline, rect, circle) { stroke-width: 3 !important; }
g.hv, g.hl { filter: drop-shadow(0 0 4px var(--hl-strong)); }

/* reveal / exclusive-frame elements */
.fig .rv { opacity: 0; transition: opacity 0.3s; }
.fig .rv.on { opacity: 1; }
.fig .xv { visibility: hidden; }
.fig .xv.on { visibility: visible; }

/* ---------- math & equations ---------- */
.m { font-family: var(--f-math); }
.m i { font-style: italic; letter-spacing: 0.02em; }
.m sub { font-size: 72%; }
.eq { font-size: 1.14rem; margin: 14px 0; }
p.eq {
  overflow-x: auto; overflow-y: hidden;
  white-space: nowrap; padding: 8px 0 12px;
}
.eq.center { text-align: center; }
.fr {
  display: inline-flex; flex-direction: column; text-align: center;
  vertical-align: middle; line-height: 1.25; font-size: 0.92em;
}
.fr > span:first-child { border-bottom: 1.2px solid currentColor; padding: 0 0.3em; }
.fr > span:last-child { padding: 0 0.3em; }

.tm {
  padding: 0.04em 0.18em; border-radius: 5px; cursor: pointer;
  transition: background 0.12s, box-shadow 0.12s;
}
.tm.hv, .tm.hl, .tm:hover {
  background: var(--hl-soft);
  box-shadow: inset 0 0 0 1px var(--hl-strong);
}

.ans {
  display: inline-block; padding: 2px 12px; border: 1.6px solid var(--ink);
  border-radius: 6px; font-weight: 600;
}

/* ---------- chips & stats ---------- */
.chips { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0; }
.chip {
  font-family: var(--f-control); font-size: 13px; letter-spacing: 0.03em;
  border: 1px solid var(--line); background: var(--surface);
  border-radius: 999px; padding: 4px 12px; color: var(--ink2);
}
.chip b { color: var(--ink); font-weight: 600; }
.chip.lkc { cursor: pointer; }
.chip.lkc:hover, .chip.hv { border-color: var(--hl); color: var(--hl); }
.chip.accent { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }

/* ---------- buttons, tabs, steppers ---------- */
.btn {
  font-family: var(--f-control); font-size: 13px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line); border-radius: 8px;
  padding: 7px 14px; cursor: pointer;
}
.btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.btn:disabled { opacity: 0.4; cursor: default; }
/* --on-accent carries the light/dark split (white on Wolfpack Red, near-black on
   the lightened dark-mode tint), so no theme-specific override is needed here. */
.btn.primary { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
/* an accent-filled button keeps its label colour on hover; the fill shifts
   instead, since recolouring the label to the accent would hide it */
.btn.primary:hover:not(:disabled),
.tabs .btn[aria-selected="true"]:hover:not(:disabled) {
  color: var(--on-accent);
  background: color-mix(in srgb, var(--accent) 80%, var(--ink));
  border-color: color-mix(in srgb, var(--accent) 80%, var(--ink));
}

.tabs { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 4px; }
.tabs .btn[aria-selected="true"] { background: var(--accent); border-color: var(--accent); color: var(--on-accent); }
.tabpane { display: none; }
.tabpane.on { display: block; }

.stepper {
  border: 1px solid var(--line); border-radius: 12px; background: var(--surface);
  padding: 14px 16px 16px; margin: 18px 0; box-shadow: var(--shadow);
}
.stepper .fig { margin: 4px 0 12px; }
.step { display: none; }
.step.on { display: block; animation: stepin 0.25s ease; }
@keyframes stepin { from { opacity: 0; transform: translateY(3px); } }
.step h4 {
  margin: 0 0 6px; font-size: 1.02rem;
  font-family: var(--f-display); font-weight: 650;
  letter-spacing: 0.005em; color: var(--accent);
}
.step p { margin: 6px 0; font-size: 15.5px; }
.stepbar {
  display: flex; align-items: center; gap: 14px; margin-top: 14px;
  border-top: 1px solid var(--line2); padding-top: 12px;
}
.sdots { display: flex; gap: 6px; flex: 1; justify-content: center; }
.sdot {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--line); border: none; padding: 0; cursor: pointer;
}
.sdot.on { background: var(--accent); }

/* ---------- controls (sliders) ---------- */
.controls {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 12px 22px; margin: 14px 0;
  background: var(--surface); border: 1px solid var(--line); border-radius: 10px;
  padding: 14px 16px;
}
.ctl label {
  display: block;
  font-family: var(--f-control); font-size: 13px; color: var(--ink2); margin-bottom: 4px;
}
.ctl output { float: right; color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
.ctl input[type="range"] { width: 100%; accent-color: var(--accent); }

/* ---------- meters ---------- */
.vbar { display: flex; height: 30px; gap: 2px; margin: 12px 0 8px; }
.vbar .seg { border-radius: 4px; min-width: 2px; transition: flex-grow 0.2s; }
.seg.s1 { background: var(--c1); } .seg.s2 { background: var(--c2); } .seg.s3 { background: var(--c3); }
.legendrow { display: flex; flex-wrap: wrap; gap: 8px 20px; font-size: 14.5px; }
.legendrow .key { display: inline-flex; align-items: center; gap: 7px; color: var(--ink2); cursor: pointer; padding: 2px 4px; border-radius: 5px; }
.legendrow .key.hv, .legendrow .key:hover { background: var(--hl-soft); }
.legendrow .swatch { width: 10px; height: 10px; border-radius: 3px; display: inline-block; }
.legendrow output { color: var(--ink); font-family: var(--f-num); font-size: 13.5px; font-variant-numeric: tabular-nums; }

table.ptable { border-collapse: collapse; width: 100%; margin: 10px 0; font-size: 14.5px; }
/* The header belongs to the table, so it takes the numeral face rather than the
   label face: a wider header would widen the whole table on a narrow screen. */
.ptable th {
  text-align: left; font-family: var(--f-num); font-size: 12px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--ink2); font-weight: 600;
  border-bottom: 1px solid var(--line); padding: 6px 10px;
}
.ptable td { padding: 7px 10px; border-bottom: 1px solid var(--line2); }
.ptable tr { cursor: pointer; }
.ptable tr.hv td, .ptable tbody tr:hover td { background: var(--hl-soft); }
.ptable td.num { font-family: var(--f-num); font-variant-numeric: tabular-nums; white-space: nowrap; }
.ptable tfoot td { border-top: 2px solid var(--line); border-bottom: none; font-weight: 700; }
.pbar { position: relative; width: 150px; height: 12px; background: var(--line2); border-radius: 6px; }
.pbar::after {
  content: ""; position: absolute; left: 50%; top: -2px; bottom: -2px;
  width: 1px; background: var(--ink2); opacity: 0.55;
}
.pbar span { position: absolute; top: 0; bottom: 0; border-radius: 6px; }
.pbar .sup { background: var(--neg); right: 50%; }
.pbar .abs { background: var(--pos); left: 50%; }

/* ---------- figure row (Y-Δ pair) ---------- */
.figrow { display: grid; grid-template-columns: 1fr 1fr; gap: 0 16px; align-items: start; }
@media (max-width: 640px) { .figrow { grid-template-columns: 1fr; } }

/* ---------- hoverable mesh zones (backyard counting) ---------- */
.fig .meshzone rect {
  fill: transparent; stroke: var(--hl); stroke-width: 1.6;
  stroke-dasharray: 6 5; stroke-opacity: 0; pointer-events: all;
}
.fig .meshzone.hv rect, .fig .meshzone:hover rect { fill: var(--hl-soft); stroke-opacity: 1; }
.fig .meshzone text { opacity: 0; font-family: var(--f-fig); font-size: 13px; transition: opacity 0.15s; }
.fig .meshzone.hv text, .fig .meshzone:hover text { opacity: 1; fill: var(--hl); }

/* ---------- details / practice ---------- */
details {
  border: 1px solid var(--line); border-radius: 10px; background: var(--surface);
  padding: 10px 16px; margin: 10px 0; max-width: 74ch;
}
details summary {
  cursor: pointer; font-family: var(--f-control); font-size: 13.5px;
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--accent);
}
details[open] summary { margin-bottom: 8px; }

footer {
  max-width: 860px; margin: 80px auto 0; padding: 18px 20px 40px;
  border-top: 1px solid var(--line); color: var(--ink2); font-size: 14px;
}
footer .rail { display: flex; flex-wrap: wrap; gap: 6px 18px; }
/* The attribution leads the footer and is set in the page ink, so that it reads
   as a statement of authorship rather than as one more utility note. */
footer .credit { color: var(--ink); }

/* ---------- landing page ---------- */
/* ---------- landing page: the four parts ---------- */
/* Each part sets --part from its numbered token; the cards inside inherit it, so
   the rail colour is declared once per section. Colour is redundant coding here:
   the part title and the lecture number carry the same information in text. */
.part { margin: 40px 0 0; }
.part[data-part="1"] { --part: var(--p1); }
.part[data-part="2"] { --part: var(--p2); }
.part[data-part="3"] { --part: var(--p3); }
.part[data-part="4"] { --part: var(--p4); }
.part.closing { --part: var(--ink2); }
.part-head { border-inline-start: 3px solid var(--part); padding-inline-start: 14px; }
.part-eyebrow {
  font-family: var(--f-label); font-size: 12px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--part); margin: 0 0 4px;
}
.part-head h2 { margin: 0 0 6px; font-size: 1.32rem; }
.part-dek { margin: 0; color: var(--ink2); font-size: 14.5px; max-width: 62ch; }

/* Closing acknowledgment. It is not a part, so it takes no rail; the rule above
   it separates it from the last group of lectures. */
.colophon { margin: 44px 0 0; padding-top: 18px; border-top: 1px solid var(--line); }
.colophon h2 {
  font-family: var(--f-label); font-size: 12px; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--ink2); font-weight: 600; margin: 0 0 6px;
}
.colophon p { margin: 0; color: var(--ink2); font-size: 14.5px; max-width: 62ch; }

.lecture-list { list-style: none; padding: 0; display: grid; gap: 12px; margin: 16px 0 0; }
.lecture-list a {
  display: block; text-decoration: none; color: var(--ink);
  background: var(--surface); border: 1px solid var(--line);
  border-inline-start: 3px solid var(--part, var(--line));
  border-radius: 12px;
  padding: 16px 20px; box-shadow: var(--shadow);
}
.lecture-list a:hover { border-color: var(--accent); }
.lecture-list .lnum {
  font-family: var(--f-label); font-size: 12px; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--part, var(--accent));
}
.lecture-list h3 { margin: 4px 0 4px; }
.lecture-list p { margin: 0; color: var(--ink2); font-size: 14px; }
.lecture-list .soon { opacity: 0.55; pointer-events: none; }

@media (max-width: 560px) {
  .eq { font-size: 1.02rem; }
  .stepbar { flex-wrap: wrap; }
}

/* ---------- print: a complete worked document ---------- */
@media print {
  /* Every token is reset, and the selector list matches the specificity of the
     dark-theme blocks (which also apply while printing from a dark browser);
     source order then makes the print palette win. */
  :root, :root[data-theme="dark"], :root:not([data-theme="light"]) {
    --bg: #ffffff; --surface: #ffffff; --panel: #ffffff;
    --ink: #111111; --ink2: #3d3d3d; --line: #bcbcbc; --line2: #dcdcdc;
    --wire: #3D3D3D; --comp: #2B2B2B;
    --accent: #CC0000; --accent-soft: rgba(204, 0, 0, 0.10); --on-accent: #FFFFFF;
    --hl: #008473; --hl-soft: rgba(0, 132, 115, 0.14); --hl-strong: rgba(0, 132, 115, 0.30);
    --grid: rgba(0, 0, 0, 0.06);
    --c1: #427E93; --c2: #6F7D1C; --c3: #4156A1;
    --neg: #427E93; --pos: #D14905; --ok: #6F7D1C;
    --p1: #3B430F; --p2: #008473; --p3: #D4632B; --p4: #4156A1;
    --shadow: none;
  }
  .topnav, .stepbar, .hintcard, .prefs { display: none; }
  .ctl input[type="range"] { display: none; }
  .step { display: block !important; border-top: 1px solid var(--line2); padding-top: 8px; margin-top: 8px; }
  .step:first-of-type { border-top: none; margin-top: 0; }
  .fig, .note, .warncard, .step, details, table.ptable { break-inside: avoid; }
  section { margin-top: 36px; }
  .flowline { animation: none; }
}
