:root {
  --bg: #ffffff;
  --fg: #1a1b1e;
  --muted: #5c5f66;
  --border: #e0e2e6;
  --panel-bg: #f8f9fa;
  --chip-bg: #eef0f2;
  --chip-bg-active: #1971c2;
  --chip-fg-active: #ffffff;
  --accent: #1971c2;
  --shadow: 0 8px 24px rgba(0,0,0,0.12);
  /* This site's highlight. Several values, because one yellow cannot do
     every job: --hl is the graphic one (rules, bars, the marker behind a
     phrase), --hl-fg the text one, darkened to stay readable as type on a
     white page (#fcc419 as a word on white is about 1.7:1), and --hl-grad
     the display gradient for the alpha|beta|gamma line, which on this
     theme has to run through the darker end of the family to read at all. */
  --hl: #fcc419;
  --hl-fg: #8a5a00;
  --hl-wash: rgba(252, 196, 25, 0.22);
  --hl-grad: linear-gradient(135deg, #b35c00 0%, #e8a600 55%, #f08c00 100%);
  --hl-glow: rgba(252, 196, 25, 0.28);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg: #16171a;
    --fg: #eceef0;
    --muted: #9a9ea6;
    --border: #2c2e33;
    --panel-bg: #1d1e22;
    --chip-bg: #26282c;
    --chip-bg-active: #4dabf7;
    --chip-fg-active: #0b0c0e;
    --accent: #4dabf7;
    --shadow: 0 8px 24px rgba(0,0,0,0.5);
    /* On the dark page the bright yellow IS the readable one, so the
       gradient can run the full amber-to-gold range. */
    --hl: #fcc419;
    --hl-fg: #ffd43b;
    --hl-wash: rgba(252, 196, 25, 0.16);
    --hl-grad: linear-gradient(135deg, #f59f00 0%, #fcc419 55%, #ffe066 100%);
    --hl-glow: rgba(252, 196, 25, 0.4);
  }
}

* { box-sizing: border-box; }

/* NO `html { scroll-behavior: smooth }` here, however tempting it looks for
   the Contents links. Measured: in the engine this was tested in it does
   not animate the scroll, it cancels it -- window.scrollTo() and
   scrollIntoView() both become no-ops, which breaks jumping to a section,
   the docs deep links, and the scroll-to-top on every route change. An
   animation is not worth navigation. */

/* Every link in the accent colour, visited or not: the browser's default
   dark blue vanishes on the dark theme. */
a { color: var(--accent); }
a:visited { color: var(--accent); }

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  background: var(--bg);
  color: var(--fg);
  line-height: 1.45;
}

.site-header {
  padding: 2rem 1.5rem 0.5rem;
  text-align: center;
}
.site-header h1 { margin: 0 0 0.25rem; font-size: 1.9rem; }
.site-header h1 a { color: inherit; text-decoration: none; }
.tagline { color: var(--muted); margin: 0; }
.site-nav {
  display: flex;
  justify-content: center;
  gap: 1.25rem;
  margin-top: 0.9rem;
}
.site-nav a {
  color: var(--muted);
  text-decoration: none;
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  padding-bottom: 0.2rem;
  border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--fg); }
.site-nav a.active { color: var(--accent); border-bottom-color: var(--accent); }

.conf-dot {
  display: inline-block;
  width: 0.6em; height: 0.6em;
  border-radius: 50%;
  margin: 0 0.15em;
}
.conf-dot.verified { background: #2f9e44; }
.conf-dot.inferred { background: #1971c2; }
.conf-dot.illustrative { background: #f08c00; }

main {
  max-width: 1200px;
  margin: 0 auto;
  padding: 0 1.5rem 3rem;
  display: grid;
  /* Without an explicit track, the single implicit column auto-sizes to
     its widest child's content -- the same "fit-content ignores max-width"
     problem as .map-page, just one level up, at the grid track itself.
     minmax(0, 1fr) is the standard fix: the track can shrink below its
     content's size instead of growing main past the viewport. */
  grid-template-columns: minmax(0, 1fr);
  gap: 1.5rem;
}


.chip-row { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.chip {
  border: 1px solid var(--border);
  background: var(--chip-bg);
  color: var(--fg);
  padding: 0.3rem 0.7rem;
  border-radius: 999px;
  font-size: 0.85rem;
  cursor: pointer;
  user-select: none;
  transition: background 0.12s, color 0.12s, transform 0.06s;
}
.chip:hover { transform: translateY(-1px); }
.chip.active {
  background: var(--chip-bg-active);
  color: var(--chip-fg-active);
  border-color: var(--chip-bg-active);
}

.reset-btn {
  justify-self: start;
  background: none;
  border: 1px solid var(--border);
  color: var(--muted);
  padding: 0.35rem 0.8rem;
  border-radius: 6px;
  cursor: pointer;
  font-size: 0.8rem;
}
.reset-btn:hover { color: var(--fg); border-color: var(--fg); }

.matrix-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 10px;
}
table.matrix {
  border-collapse: collapse;
  width: 100%;
  min-width: 600px;
}
table.matrix th, table.matrix td {
  border: 1px solid var(--border);
  padding: 0;
  text-align: left;
}
table.matrix thead th {
  background: var(--panel-bg);
  padding: 0.6rem 0.7rem;
  font-size: 0.8rem;
  white-space: nowrap;
  position: sticky;
  top: 0;
}
th.problem-col { min-width: 210px; }
td.problem-cell {
  padding: 0.6rem 0.7rem;
  vertical-align: top;
  background: var(--panel-bg);
}
td.problem-cell .notation { font-weight: 700; font-size: 0.95rem; }
td.problem-cell .pname { color: var(--muted); font-size: 0.78rem; margin-top: 0.15rem; }

td.result-cell { text-align: center; vertical-align: middle; padding: 0; }
.badge {
  display: block;
  width: 100%;
  height: 100%;
  min-height: 3rem;
  border: none;
  cursor: pointer;
  color: white;
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.02em;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.4rem;
  transition: filter 0.1s;
}
.badge:hover { filter: brightness(1.1); }
.badge.na { background: transparent; color: var(--muted); cursor: default; font-weight: 400; }
.badge .conf-flag { margin-left: 0.35em; opacity: 0.85; font-size: 0.9em; }

.empty-state { padding: 2rem; text-align: center; color: var(--muted); }

.legend { }
.legend h2 { font-size: 0.9rem; margin: 0 0 0.5rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.legend-items { display: flex; flex-wrap: wrap; gap: 0.6rem; }
.legend-item {
  display: flex; align-items: center; gap: 0.4rem;
  font-size: 0.8rem;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.25rem 0.6rem 0.25rem 0.4rem;
}
.legend-swatch { width: 0.9em; height: 0.9em; border-radius: 3px; flex-shrink: 0; }

/* Search: the parameter chips, row count and legend around the matrix */
.search-params {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.4rem;
  margin: 0 0 0.8rem;
}
.search-params-label {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  font-weight: 600;
  margin-right: 0.4rem;
}
.search-params .chip { padding: 0.2rem 0.55rem; font-size: 0.8rem; }
.search-status {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin: 0 0 0.6rem;
  font-size: 0.85rem;
  color: var(--muted);
}
.search-only-param { cursor: pointer; }
.search-problem-link {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-weight: 700;
  font-size: 0.95rem;
  color: var(--fg);
  text-align: left;
  cursor: pointer;
}
.search-problem-link:hover { color: var(--accent); text-decoration: underline; }
.search-matrix .badge { min-height: 2.4rem; }
/* Wide enough that the longest classical label ("pseudo-polynomial time
   solvable") takes two lines instead of stretching every row to three. */
.search-matrix td.result-cell:nth-child(2) { min-width: 10.5rem; }
.search-legend { margin-top: 1.2rem; }
.search-legend .legend-items + .legend-items { margin-top: 0.5rem; }
.search-legend-label { align-self: center; font-size: 0.8rem; color: var(--muted); }

.detail-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,0.35);
  z-index: 40;
}
.detail-panel {
  position: fixed;
  top: 0; right: 0;
  /* --content-min-width is set from JS when a panel's content (the
     parameter diagram) needs more room than the default, so it never has
     to scroll horizontally. The diagram wraps at SZ_PT_MAX_DIAGRAM_W
     (260px), which with the paddings is this default. */
  width: min(max(320px, var(--content-min-width, 0px)), 92vw);
  height: 100%;
  background: var(--bg);
  border-left: 1px solid var(--border);
  box-shadow: var(--shadow);
  z-index: 50;
  padding: 1.25rem 1.1rem;
  overflow-y: auto;
}
.detail-close {
  position: absolute; top: 1rem; right: 1rem;
  background: none; border: none; font-size: 1.4rem;
  color: var(--muted); cursor: pointer; line-height: 1;
}
.detail-minimize {
  position: absolute; top: 1rem; right: 2.6rem;
  background: none; border: none; font-size: 1.4rem;
  color: var(--muted); cursor: pointer; line-height: 1;
}
.detail-close:hover, .detail-minimize:hover { color: var(--fg); }
/* The minimized panel: a tab at the bottom right naming the problem. */
.detail-dock {
  position: fixed; right: 1rem; bottom: 1rem; z-index: 45;
  display: flex; align-items: stretch;
  background: var(--panel-bg); border: 1px solid var(--border); border-radius: 999px;
  box-shadow: var(--shadow); overflow: hidden;
}
.detail-dock-restore {
  background: none; border: none; cursor: pointer; color: var(--fg);
  font: inherit; font-size: 0.85rem; font-weight: 600; padding: 0.45rem 0.4rem 0.45rem 0.9rem;
  max-width: 18rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.detail-dock-restore::before { content: "\2197  "; color: var(--muted); font-weight: 400; }
.detail-dock-restore:hover { color: var(--accent); }
.detail-dock-close {
  background: none; border: none; border-left: 1px solid var(--border); cursor: pointer;
  color: var(--muted); font-size: 1.1rem; line-height: 1; padding: 0 0.7rem 0 0.55rem;
}
.detail-dock-close:hover { color: var(--fg); }
/* display:flex above would beat the hidden attribute's display:none. */
.detail-dock[hidden] { display: none; }
.detail-content h3 { margin-top: 0; }
.detail-class-badge {
  display: inline-block;
  padding: 0.25rem 0.7rem;
  border-radius: 999px;
  color: white;
  font-weight: 600;
  font-size: 0.85rem;
  margin-bottom: 0.75rem;
}
.detail-field { margin-bottom: 0.9rem; }
.param-tree-wrap {
  overflow-x: auto;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.5rem;
  background: var(--panel-bg);
}
.param-tree-wrap svg text { font-family: inherit; }
.detail-field h4 {
  margin: 0 0 0.25rem;
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
}
.detail-field p { margin: 0; font-size: 0.9rem; }

.site-footer {
  text-align: center;
  color: var(--muted);
  font-size: 0.8rem;
  padding: 1rem 1.5rem 3rem;
}
.site-footer a { color: var(--accent); }

/* Wiki-style problem page */
.wiki-page { max-width: 820px; margin: 0 auto; }
.wiki-back {
  display: inline-block;
  margin-bottom: 1rem;
  font-size: 0.85rem;
  color: var(--accent);
  text-decoration: none;
}
.wiki-back:hover { text-decoration: underline; }
.wiki-page h2 {
  margin: 0 0 0.15rem;
  font-size: 1.6rem;
}
.wiki-alphabetagamma {
  color: var(--muted);
  font-size: 0.95rem;
  margin: 0 0 1.25rem;
}
.wiki-status {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.75rem 1rem;
  margin-bottom: 1.25rem;
  font-size: 0.9rem;
}
.wiki-status b { color: var(--muted); text-transform: uppercase; font-size: 0.72rem; letter-spacing: 0.04em; display: block; margin-bottom: 0.2rem; }
.wiki-section { margin-bottom: 1.75rem; }
.wiki-section h3 {
  font-size: 0.8rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--muted);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.4rem;
  margin-bottom: 0.8rem;
}
.wiki-overview p { font-size: 0.95rem; }

.result-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.6rem; }
.result-row {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 0.8rem;
  align-items: start;
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 0.7rem 0.9rem;
  background: var(--panel-bg);
}
.result-row .param-name { font-weight: 600; font-size: 0.9rem; }
.result-row .param-name .sym { color: var(--muted); font-weight: 400; font-size: 0.8rem; display: block; }
.result-row .result-body p { margin: 0.15rem 0; font-size: 0.87rem; }
.result-row .result-body .cite-link { color: var(--accent); text-decoration: none; }
.result-row .result-body .cite-link:hover { text-decoration: underline; }
.inline-cite { color: var(--accent); text-decoration: underline; text-decoration-style: dotted; }
.inline-cite:hover { text-decoration-style: solid; }
.class-pill {
  display: inline-block;
  padding: 0.2rem 0.6rem;
  border-radius: 999px;
  color: white;
  font-weight: 600;
  font-size: 0.75rem;
  white-space: nowrap;
  height: fit-content;
}

.related-links { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.related-links a {
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.3rem 0.7rem;
  font-size: 0.82rem;
  color: var(--fg);
  text-decoration: none;
  background: var(--chip-bg);
}
.related-links a:hover { border-color: var(--accent); color: var(--accent); }

/* Documentation pages -- prose, so a readable measure (~70 characters)
   rather than the full page width the diagrams use. */
.docs-page { max-width: 820px; margin: 0 auto; counter-reset: docs-section; }
/* Sections are numbered by CSS counter rather than by hand, so the numbers
   match the Contents list (an <ol>) without anyone maintaining them. */
.docs-section { margin-top: 3.2rem; counter-increment: docs-section; counter-reset: docs-sub; }
.docs-section h3 {
  display: flex;
  align-items: baseline;
  gap: 0.6rem;
  font-size: 1.75rem;
  line-height: 1.25;
  letter-spacing: -0.01em;
  margin: 0 0 1rem;
  padding-bottom: 0.5rem;
  border-bottom: 3px solid var(--hl);
}
.docs-section h3::before {
  content: counter(docs-section);
  flex: none;
  font-size: 0.95rem;
  font-weight: 700;
  /* Ink, not var(--bg): on the light theme that would be white on yellow,
     which is about 1.6:1. Dark on yellow reads in both themes. */
  color: #2b1d00;
  background: var(--hl);
  border-radius: 6px;
  padding: 0.15rem 0.5rem;
  transform: translateY(-0.15em);
}
.docs-section h4 {
  counter-increment: docs-sub;
  font-size: 1.22rem;
  line-height: 1.3;
  margin: 2.2rem 0 0.5rem;
  padding-left: 0.7rem;
  border-left: 4px solid var(--hl);
}
.docs-section h4::before {
  content: counter(docs-section) "." counter(docs-sub) "  ";
  color: var(--hl-fg);
  font-weight: 700;
}
.docs-section p { line-height: 1.7; margin: 0 0 0.9rem; }
/* Bold in the prose is what the sentence turns on, so it carries the
   highlight colour rather than weight alone. */
.docs-section p > b, .docs-section li > b { color: var(--hl-fg); }
/* For the one phrase in a paragraph that has to be read even when the
   paragraph isn't. */
.docs-section mark {
  background: var(--hl-wash);
  color: inherit;
  padding: 0.05rem 0.25rem;
  border-radius: 3px;
  box-decoration-break: clone;
  -webkit-box-decoration-break: clone;
}
.docs-section code {
  background: var(--hover-bg, rgba(128,128,128,0.12));
  border: 1px solid var(--border);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
  font-size: 0.88em;
}
.docs-example {
  border-left: 3px solid var(--hl);
  padding: 0.2rem 0 0.2rem 0.8rem;
  color: var(--muted);
}
/* "↑ Contents", sitting at the end of every heading the Contents lists. */
.docs-back {
  flex: none;
  margin-left: auto;
  /* Top-aligned, not centred: a heading that wraps to two lines on a narrow
     screen would otherwise park this in the middle of the gap beside it. */
  align-self: flex-start;
  margin-top: 0.25rem;
  font-size: 0.72rem;
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--border);
  border-radius: 999px;
  padding: 0.12rem 0.55rem;
  white-space: nowrap;
  cursor: pointer;
}
.docs-back:hover { border-color: var(--hl); color: var(--hl-fg); }
.docs-section h4 .docs-back { float: right; margin-left: 0.8rem; }
.docs-list { line-height: 1.6; padding-left: 1.1rem; }
.docs-list li { margin-bottom: 0.5rem; }
/* The type table is the one wide thing on the page; let it scroll inside
   its own box rather than widening the prose column. */
.docs-table-wrap { overflow-x: auto; margin: 1rem 0 0.5rem; }
.docs-table { border-collapse: collapse; width: 100%; font-size: 0.85rem; }
.docs-table th, .docs-table td {
  border: 1px solid var(--border);
  padding: 0.45rem 0.6rem;
  text-align: left;
  vertical-align: top;
}
.docs-table th { background: var(--hover-bg, rgba(128,128,128,0.12)); }
/* One result category inside "What kinds of result the corpus contains":
   a level below the h4 subsections, so the Contents doesn't grow a row per
   category, and the "About / Becomes" line that frames each one. */
.docs-page h5 {
  margin: 2rem 0 0.3rem;
  font-size: 1.05rem;
  color: var(--hl-fg);
  border-bottom: 1px solid var(--border);
  padding-bottom: 0.3rem;
}
/* "About: ... Becomes: ..." -- its two labels take the prose highlight
   like any other bold in a docs paragraph, which is what makes the line
   scannable at a glance. */
.docs-result-about { margin: 0.3rem 0; color: var(--muted); font-size: 0.85rem; }

/* .view is the actual grid item under main (not .map-page, which is just
   a normal block child of it) -- same min-width:auto default grid-item
   behavior applies here, one level higher than where it was first fixed. */
.view { min-width: 0; }
.view h2.page-title { text-align: center; margin-bottom: 1.5rem; }

/* Problem maps index */
.map-list { max-width: 820px; margin: 0 auto; display: grid; gap: 0.8rem; }
.map-card {
  display: block;
  border: 1px solid var(--border);
  border-radius: 10px;
  padding: 1rem 1.2rem;
  background: var(--panel-bg);
  text-decoration: none;
  color: var(--fg);
}
.map-card:hover { border-color: var(--accent); }
.map-card h3 { margin: 0 0 0.3rem; }
.map-card p { margin: 0; color: var(--muted); font-size: 0.88rem; }

/* Problem map (poset diagram) */
/* No max-width cap: the canvas inside is already sized exactly to its
   content (computed in JS), so let the page grow to match it instead of
   clipping to an arbitrary cap and forcing .map-canvas-wrap to scroll. */
/* min-width:0 overrides the grid item's default min-width:auto -- without
   it, a wide child (the canvas) forces this item, and the whole page,
   wider than the viewport regardless of max-width -- that's the actual
   bug, not fit-content itself. */
/* width:100% (not fit-content) -- the canvas inside now scales/centers
   itself to fit via JS (fitMapCanvasToWidth in app.js), which assumes this
   page fills the available column width; fit-content would instead let the
   page shrink around a narrow diagram, throwing off that centering math. */
.map-page { width: 100%; min-width: 0; margin: 0 auto; }
.map-page-header { text-align: center; margin-bottom: 1rem; }
.map-page-header p { color: var(--muted); font-size: 0.9rem; max-width: 680px; margin: 0.3rem auto 0; }
/* .map-diagram is the positioning context for the TikZ button, kept as a
   sibling of .map-canvas-wrap (not a child) so the button never scrolls
   away when the canvas itself needs a horizontal scrollbar. */
.map-diagram { position: relative; }
.tikz-export-btn {
  position: absolute;
  top: 0.5rem;
  right: 0.5rem;
  z-index: 2;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: 6px;
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
}
.tikz-export-btn:hover { border-color: var(--accent); color: var(--accent); }
.auto-arrange-btn {
  position: absolute;
  top: 0.5rem;
  right: 5.6rem;
  z-index: 2;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: 6px;
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
}
.auto-arrange-btn:hover { border-color: var(--accent); color: var(--accent); }
/* Apply filter / Show all -- a flex row (like .map-history-controls on the
   opposite side) so the two buttons auto-size next to each other instead
   of needing their positions hand-tuned to their label widths. Reuses
   .map-history-btn for the buttons themselves (same look, same :disabled
   styling as Undo/Redo/Reset) -- which one is enabled says at a glance
   whether the filter is currently on. */
.sz-filter-controls { position: absolute; top: 0.5rem; right: 13rem; z-index: 2; display: flex; gap: 0.4rem; }
/* Opposite corner from the tikz/auto-arrange/filter cluster (anchored to
   the right) so this can never collide with anything over there, whatever
   either side's label lengths happen to be. */
.map-history-controls { position: absolute; top: 0.5rem; left: 0.5rem; z-index: 2; display: flex; gap: 0.4rem; }
.map-history-btn {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: 6px;
  padding: 0.35rem 0.7rem;
  font-size: 0.78rem;
  cursor: pointer;
}
.map-history-btn:hover:not(:disabled) { border-color: var(--accent); color: var(--accent); }
.map-history-btn:disabled { opacity: 0.35; cursor: default; }
/* Toggled on a node (and every edge touching it) to hide it in place,
   without a full re-render -- see setSzNodeHidden/setMapNodeHidden.
   !important because .map-node/.sz-node/.sz-edge each set their own
   `display` at the same specificity (one class selector) further down this
   file -- without it, source order lets THOSE win over this one instead of
   the other way around, and a "hidden" node stays visible. */
.node-hidden { display: none !important; }
.map-canvas-wrap {
  /* Oversized diagrams are shrunk to fit via a CSS transform in
     fitMapCanvasToWidth() (app.js) rather than scrolled -- no horizontal
     scrolling anywhere on this site, diagrams included. overflow:hidden
     just guards against a transform-measurement edge case leaving a sliver
     of unscaled overflow. */
  overflow: hidden;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: var(--panel-bg);
  /* Extra room on top: the Undo/Redo and TikZ/Apply button rows sit over
     the top of the box (~65px deep) and used to cover the first row of
     nodes. */
  padding: 4.5rem 1.5rem 1.5rem;
}
.map-canvas { position: relative; }
.map-edge-svg { position: absolute; top: 0; left: 0; overflow: visible; }
.map-node {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  white-space: nowrap;
  border-radius: 6px;
  border: 2px solid transparent;
  padding: 0.25rem 0.35rem;
  font-weight: 600;
  font-size: 0.92rem;
  text-decoration: none;
  color: #111;
  box-shadow: 0 1px 3px rgba(0,0,0,0.25);
  cursor: grab;
  touch-action: none;
  user-select: none;
  z-index: 1;
}
.map-node:active { cursor: grabbing; z-index: 2; }
.map-node.outline { background: var(--panel-bg); }
@media (prefers-color-scheme: dark) {
  .map-node { color: #0b0c0e; }
  .map-node.outline { color: var(--fg); background: var(--bg); }
}
.map-legend { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: center; margin-top: 1.2rem; }

/* Scheduling Zoo overview: same map-node/map-canvas machinery, much smaller
   nodes and thinner edges since there are hundreds of them. */
.sz-node {
  padding: 0 4px;
  border-radius: 4px;
  font-weight: 600;
  line-height: 1;
  box-shadow: none;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.sz-node-dim { opacity: 0.12; }
.sz-filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  justify-content: center;
  margin: 0 auto 1rem;
  /* positioning context for the reset button, which is pulled out of the
     flow so the alpha|beta|gamma group stays centred rather than being
     shoved left by it */
  position: relative;
  padding-right: 8rem;
}
/* The overview's short introduction above the filters. The defined terms
   (Nodes, Arrows, Colors) stand out in the full text color against the
   muted prose; Graham's alpha|beta|gamma gets its own centered line. */
.sz-intro {
  /* As wide as the filter bar and diagram box below it. */
  max-width: none;
  margin: 1.6rem 0 1.5rem;
  color: var(--muted);
  font-size: 0.9rem;
  line-height: 1.55;
  text-align: left;
}
.sz-intro p { margin: 0 0 0.6rem; }
/* The browser-default link blue is nearly invisible on the dark panel. */
.sz-intro a, .design-intro a { color: var(--accent); }
.sz-intro code {
  background: rgba(128,128,128,0.16);
  border-radius: 3px;
  padding: 0.05rem 0.3rem;
  color: var(--fg);
  font-size: 0.9em;
}
.sz-def { color: var(--fg); font-weight: 700; }
.sz-graham {
  display: flex;
  justify-content: center;
  align-items: flex-start;
  gap: 1rem;
  margin: 0.4rem 0 0.9rem !important;
}
.sz-graham-field { display: flex; flex-direction: column; align-items: center; min-width: 6rem; }
.sz-graham-sym {
  font-size: 2.2rem;
  font-style: italic;
  font-weight: 700;
  line-height: 1.15;
  background: var(--hl-grad);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  text-shadow: 0 0 18px var(--hl-glow);
}
/* The separators take the TEXT yellow, not the graphic one: at this weight
   #fcc419 on a white page is barely there. */
.sz-graham-bar { font-size: 2.2rem; line-height: 1.15; color: var(--hl-fg); opacity: 0.55; }
.sz-graham-name {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--muted);
}
/* Left-aligned with the text around it; only the alpha|beta|gamma line is centred. */
.sz-intro-legend { margin: 0.2rem 0 0.8rem; justify-content: flex-start; }
.sz-arrow-key { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.3rem 0.5rem; }
.sz-line-swatch {
  display: inline-block;
  width: 1.6rem;
  border-top: 3px solid;
  margin: 0 0.1rem 0 0.8rem;
}
.sz-line-swatch:first-child { margin-left: 0; }
.sz-line-dashed { border-top-style: dashed; }
.sz-reset-filters-btn {
  position: absolute;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
}
.sz-filter {
  /* A flex item that gives way, not width:100% -- at full width it claimed
     the whole row on its own and pushed the three dropdowns onto a second
     line. It now shrinks to share the row and only grows into space the
     dropdowns don't need. */
  flex: 1 1 12rem;
  min-width: 8rem;
  max-width: 20rem;
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--panel-bg);
  color: var(--fg);
  font-size: 0.9rem;
}
.sz-filter-select {
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--panel-bg);
  color: var(--fg);
  font-size: 0.9rem;
}
.ms-dropdown { position: relative; display: inline-block; }
/* Graham's own field separators, drawn between the three dropdowns so
   the filter row reads as alpha|beta|gamma rather than as three
   unrelated controls that happen to sit next to each other. */
.sz-field-sep {
  align-self: center;
  color: var(--muted);
  font-size: 1.15rem;
  line-height: 1;
  user-select: none;
}
.ms-toggle {
  padding: 0.5rem 0.7rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--panel-bg);
  color: var(--fg);
  font-size: 0.9rem;
  cursor: pointer;
  /* Fixed width, not max-width: the label is rewritten as values are
     switched on and off ("All objectives" -> "-Preemptive (pmtn)" -> "3
     required"), and with an intrinsic width every one of those changes
     resized the button and shoved its neighbours sideways. A fixed box
     means the text changes inside a frame that never moves. */
  width: 11.5rem;
  padding-right: 1.5rem;
  position: relative;
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ms-toggle:hover { border-color: var(--accent, #4c8bf5); }
/* Absolutely positioned (with matching padding-right above) so the caret
   sits at the fixed right edge instead of riding at the end of the label
   text, where a long selection would ellipsis it away. */
.ms-toggle::after { content: "▾"; position: absolute; right: 0.6rem; top: 50%; transform: translateY(-50%); }
.ms-panel {
  /* Opens UPWARD: the filter bar sits right above the diagram, so a menu
     dropping down covers the map it is filtering. placeFilterPanel() in
     app.js adds .ms-panel-down when the toggle is too near the top of the
     window for the menu to fit above it. */
  position: absolute;
  bottom: calc(100% + 4px);
  left: 0;
  z-index: 30;
  min-width: 100%;
  max-width: 340px;
  max-height: 280px;
  overflow-y: auto;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  box-shadow: var(--shadow);
  padding: 0.3rem 0;
}
.ms-panel-down { top: calc(100% + 4px); bottom: auto; }
.ms-option {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.35rem 0.7rem;
  font-size: 0.85rem;
  white-space: nowrap;
}
.ms-option:hover { background: var(--hover-bg, rgba(128,128,128,0.12)); }
.ms-option-label { cursor: pointer; }
/* Three-position switch per option: exclude (-) / ignore (dot) / require
   (+). Each segment is directly clickable rather than one button cycling
   through the states, so setting a value to a specific position is always
   one click and never overshoots. The active segment is the only colored
   one, so a glance down the list reads as "+ green = kept, - red = dropped,
   everything else ignored". */
.tri {
  display: inline-flex;
  flex-shrink: 0;
  border: 1px solid var(--border);
  border-radius: 999px;
  overflow: hidden;
  /* The track is a visible dark grey rather than transparent, so the whole
     control reads as a switch against the panel behind it instead of three
     floating glyphs. Inactive segments simply show this track; only the
     selected one is painted (grey in the middle, red left, green right). */
  background: rgba(128, 128, 128, 0.3);
}
.tri-seg {
  border: 0;
  background: transparent;
  color: var(--muted);
  font-size: 0.7rem;
  line-height: 1;
  padding: 0.2rem 0.36rem;
  cursor: pointer;
}
.tri-seg:hover { background: rgba(128, 128, 128, 0.5); }
.ms-option[data-state="in"] .tri-in,
.ms-group[data-state="in"] > .ms-option .tri-in { background: #2c8a3f; color: #fff; }
.ms-option[data-state="out"] .tri-out,
.ms-group[data-state="out"] > .ms-option .tri-out { background: #c92a2a; color: #fff; }
.ms-option[data-state="neutral"] .tri-neutral,
.ms-group[data-state="neutral"] > .ms-option .tri-neutral { background: rgba(128, 128, 128, 0.62); color: var(--fg); }

/* Settings picker: one collapsible group per beta field. The group's own
   switch means "this constraint is present / absent at all"; expanding it
   reveals that field's individual values as their own switches. Wider than
   the plain value dropdowns because the group labels are full phrases. */
/* Taller than the plain value panels: there are 14 groups plus the rare
   expander, and at the shared 280px cap only about five were visible with
   nothing on screen saying the rest were below the fold. */
.ms-panel-settings { min-width: 21rem; max-width: 23rem; max-height: min(60vh, 30rem); }
.ms-group + .ms-group { border-top: 1px solid var(--border); }
/* The entire header row is the expand/collapse target (see the click
   handler in wireSzSettingsDropdown) -- hence the pointer cursor on the
   whole row rather than only on the caret glyph. */
.ms-group-head { font-weight: 500; cursor: pointer; }
.ms-group-head:hover { background: var(--hover-bg, rgba(128,128,128,0.12)); }
.ms-caret {
  border: 0;
  background: transparent;
  color: var(--muted);
  cursor: pointer;
  font-size: 0.75rem;
  padding: 0.2rem 0.3rem;
  pointer-events: none; /* the row handles the click; this is just the glyph */
  transition: transform 0.12s;
}
.ms-caret[aria-expanded="true"] { transform: rotate(90deg); }
/* A value group ("Online") has no sub-values, so it gets a blank spacer
   where the caret would be -- keeping its label aligned with the groups
   above and below rather than shifted left on its own. */
.ms-caret-empty { display: inline-block; width: 0.75rem; }
.ms-group-leaf { cursor: default; }
.ms-group-leaf:hover { background: transparent; }
.ms-group-label { flex: 1; }
.ms-count {
  color: var(--muted);
  font-weight: 400;
  font-size: 0.75rem;
  margin-left: 0.4rem;
}
.ms-group-values { padding-left: 1.6rem; padding-bottom: 0.2rem; }
/* A nested sub-group (Shop > Job counts > n=2) indents once more and
   drops the divider lines, so the three levels read as a hierarchy
   rather than as three flat lists that happen to be inset. */
.ms-group-values .ms-group + .ms-group { border-top: 0; }
.ms-group-values .ms-group-head { font-weight: 400; }
.ms-group-values .ms-group-values { padding-left: 1.3rem; }
.ms-value { padding: 0.2rem 0.7rem 0.2rem 0; font-weight: 400; }
/* A value with no problems left under the current filter is dimmed rather
   than removed -- "this exists but nothing here has it" is worth seeing. */
.ms-zero { opacity: 0.4; }
.ms-rare { border-top: 1px solid var(--border); padding-top: 0.2rem; }
.ms-rare-label {
  color: var(--muted);
  font-size: 0.8rem;
  cursor: pointer;
  padding: 0.35rem 0;
  display: inline-block;
}
.sz-tool-btn {
  padding: 0.5rem 0.9rem;
  border-radius: 6px;
  border: 1px solid var(--border);
  background: var(--panel-bg);
  color: var(--fg);
  font-size: 0.9rem;
  cursor: pointer;
}
.sz-tool-btn:hover { border-color: var(--accent, #4c8bf5); }
/* Always rendered (never conditionally shown/hidden), so it never shifts
   .map-diagram's position above it -- unlike a live "N hidden" status line
   would. Sits below the diagram, explaining the drag-to-hide gesture once,
   in one fixed place. .map-hint-icon is a plain "i" for now -- a styling
   placeholder for a real icon later. */
.map-hint {
  max-width: 720px;
  margin: 0.8rem auto 0;
  text-align: center;
  color: var(--muted);
  font-size: 0.8rem;
}
.map-hint-icon {
  display: inline-block;
  width: 1.1em;
  height: 1.1em;
  line-height: 1.1em;
  border-radius: 50%;
  border: 1px solid var(--muted);
  text-align: center;
  font-size: 0.75em;
  font-style: italic;
  margin-right: 0.3em;
}
.sz-edge-dim { opacity: 0.06; }
.sz-edge-hit { stroke: transparent; stroke-width: 11px; fill: none; cursor: pointer; }
/* Keeps the line's own color (gray, or red for flagged) on hover -- only
   thickens it and adds a soft neon-yellow glow around it. The arrowhead
   (fill="context-stroke" on its marker, see arrowDef in app.js) always
   matches whatever stroke color the line has, so it never needs a separate
   hover marker -- it just glows along with the line automatically. */
.sz-edge:hover .sz-edge-visible {
  stroke-width: 3px !important;
  filter: drop-shadow(0 0 2px #f4ff00);
}
.sz-param-group {
  margin: 0.6rem 0;
  padding-left: 0.7rem;
  border-left: 2px solid #1c7ed6;
}
.sz-param-group h5 {
  margin: 0 0 0.3rem;
  font-size: 0.85rem;
  color: #1c7ed6;
}

.map-excluded {
  max-width: 720px;
  margin: 1.5rem auto 0;
  font-size: 0.85rem;
  color: var(--muted);
}
.map-excluded h3 {
  font-size: 0.75rem;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 0.5rem;
}
.map-excluded ul { margin: 0; padding-left: 1.1rem; }
.map-excluded li { margin-bottom: 0.4rem; }

/* width:100% (not a fixed max-width) so this matches .map-page and the
   fitMapCanvasToWidth() budget it shares with the map view -- a narrower
   cap here than what that function measures would let the graph overflow
   its own container even while "fitting" the wrong (wider) one. */
.design-page { width: 100%; margin: 0 auto; }
.design-intro { max-width: 780px; margin: -0.5rem auto 1.5rem; color: var(--muted); font-size: 0.9rem; text-align: center; }
.story-designer { max-width: 980px; margin: 0 auto 2.5rem; }
.story-picker { display: block; margin-bottom: 1rem; }
.story-search-wrap { position: relative; max-width: 720px; margin: 1rem auto 0; }
.story-search { width: 100%; }
.story-results { position: absolute; top: calc(100% + 4px); left: 0; right: 0; z-index: 20; max-height: 320px; overflow-y: auto; border: 1px solid var(--border); border-radius: 6px; background: var(--panel-bg); box-shadow: var(--shadow); }
.designer-search-tools { display: grid; grid-template-columns: minmax(220px, 1fr) auto; align-items: center; gap: 0.75rem; width: 100%; margin-top: 1rem; }
.designer-search-tools .story-search-wrap { max-width: none; width: 100%; margin: 0; }
.designer-filter-row { display: flex; flex-wrap: nowrap; justify-content: flex-end; align-items: center; gap: 0.6rem; margin: 0; }
.designer-search-tools > .story-results { position: relative; top: auto; left: auto; right: auto; width: 100%; max-height: none; overflow: visible; }
.designer-search-tools > .story-results { grid-column: 1 / -1; }
.designer-search-tools > .story-results .designer-mini-graph { min-width: 0; }
.story-result { display: block; width: 100%; min-height: 2.4rem; padding: 0.55rem 0.7rem; border: 0; border-bottom: 1px solid rgba(255,255,255,0.2); color: #111; text-align: left; cursor: grab; font: inherit; font-weight: 700; }
.story-result:last-child { border-bottom: 0; }
.story-result:hover, .story-result:focus { filter: brightness(1.12); outline: none; }
.story-result:disabled { cursor: default; opacity: 0.55; }
.story-empty { padding: 0.8rem; color: var(--muted); font-size: 0.85rem; }
.designer-mini-graph { position: relative; overflow: hidden; background: var(--panel-bg); }
.designer-mini-graph svg { position: absolute; inset: 0; pointer-events: none; }
.designer-mini-graph line { stroke: var(--muted); stroke-width: 1.5; }
.designer-mini-graph marker path { fill: var(--muted); }
.designer-mini-node { position: absolute; display: grid; place-items: center; padding: 0.2rem 0.35rem; border: 2px solid; border-radius: 4px; cursor: grab; font: inherit; font-size: 0.68rem; font-weight: 700; line-height: 1.1; overflow: hidden; text-overflow: ellipsis; white-space: normal; text-align: center; }
.designer-mini-node:hover, .designer-mini-node:focus { filter: brightness(1.12); outline: 2px solid var(--accent); }
.designer-mini-node.added { opacity: 0.45; cursor: default; }
.designer-mini-node.exact-fit { outline: 3px solid #4dabf7; outline-offset: 3px; box-shadow: 0 0 0 4px rgba(77,171,247,0.24), 0 0 16px rgba(77,171,247,0.85); }
.designer-draft-node { position: absolute; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 0.2rem; border: 2px dashed var(--accent); border-radius: 4px; background: var(--panel-bg); color: var(--accent); cursor: pointer; font: inherit; font-size: 0.72rem; font-weight: 700; }
.designer-draft-node strong { color: var(--fg); font-size: 0.72rem; }
.designer-draft-node:hover, .designer-draft-node:focus { background: var(--chip-bg); outline: 2px solid var(--accent); }
.designer-draft-plus { font-size: 1.1rem; line-height: 1; }
.story-canvas-wrap { min-height: 480px; border: 2px solid var(--border); border-radius: 6px; overflow: auto; background: var(--panel-bg); }
.story-canvas-wrap.drop-target { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 8%, var(--panel-bg)); }
.map-canvas-wrap.drop-target { border-color: var(--accent); box-shadow: inset 0 0 0 2px var(--accent); }
.story-canvas { position: relative; min-width: 680px; min-height: 260px; }
.story-canvas-empty { position: absolute; inset: 0; display: grid; place-items: center; color: var(--muted); pointer-events: none; }
.story-edge-svg { position: absolute; inset: 0; pointer-events: none; }
.story-edge-svg line { stroke: var(--muted); stroke-width: 2; }
.story-edge-svg marker path { fill: var(--muted); }
.story-node { position: absolute; display: grid; place-items: center; padding: 0.55rem 0.7rem; border: 2px solid var(--accent); border-radius: 6px; cursor: grab; font-size: 0.84rem; font-weight: 700; text-align: center; box-shadow: var(--shadow); user-select: none; }
.story-node:active { cursor: grabbing; }
.story-node small { display: block; margin-top: 0.15rem; color: var(--muted); font-weight: 400; }
@media (max-width: 700px) { .story-canvas { min-width: 600px; } }
@media (max-width: 1050px) { .designer-search-tools { grid-template-columns: 1fr; } .designer-filter-row { justify-content: center; flex-wrap: wrap; } }
.design-chip-row { display: flex; flex-wrap: wrap; gap: 0.4rem; justify-content: center; min-height: 2.1rem; }
.design-chip-empty { color: var(--muted); font-size: 0.82rem; font-style: italic; align-self: center; }
.design-chip { font-size: 0.78rem; }
.designer-restrictions { max-width: 980px; margin: 1.1rem auto 0; padding: 0.75rem 1rem; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); }
.designer-restrictions-label { margin-bottom: 0.45rem; color: var(--muted); font-size: 0.78rem; font-weight: 700; text-align: center; text-transform: uppercase; letter-spacing: 0.04em; }
.designer-restrictions .design-chip-row { min-height: 1.8rem; justify-content: center; }
.designer-restrictions-note { margin: 0.55rem 0 0; color: var(--muted); font-size: 0.75rem; text-align: center; }
.design-selected-label { text-align: center; font-size: 0.85rem; color: var(--muted); margin: 0.8rem 0 0.6rem; }
.design-graph-node { cursor: pointer; }
.design-graph-node.active { outline: 3px solid var(--accent); outline-offset: 2px; }
.design-graph-node.delete-armed,
.sz-node.delete-armed,
.map-node.delete-armed { opacity: 0.4; }
.map-canvas-wrap.delete-armed { border-color: #c92a2a; box-shadow: inset 0 0 0 2px #c92a2a; }
/* Selection is deliberately NOT blue: blue marks a problem the reader has
   classified themselves (.user-classified), which is a lasting fact about the
   problem, while selection is a passing interaction state. A neutral
   high-contrast ring keeps the two apart -- var(--fg) so it reads in both
   themes -- and the glow is what still makes it obvious which node is live. */
.designer-selected { outline: 3px solid var(--fg) !important; outline-offset: 4px; box-shadow: 0 0 0 4px rgba(128,128,128,0.30), 0 0 18px rgba(255,255,255,0.45); z-index: 4; }
.designer-relations { max-width: 980px; margin: 1rem auto 0; padding: 0.8rem 1rem; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border); text-align: center; }
.designer-relations-title { display: inline-block; margin-right: 0.6rem; color: var(--fg); font-size: 0.85rem; font-weight: 700; }
.designer-details-btn { display: inline-block; margin-bottom: 0.65rem; }
.designer-relations-group { display: flex; flex-wrap: wrap; justify-content: center; align-items: center; gap: 0.4rem; margin-top: 0.45rem; }
.designer-relations-group b { color: var(--muted); font-size: 0.78rem; margin-right: 0.25rem; }
.designer-relation-btn { padding: 0.35rem 0.55rem; border: 1px solid var(--border); border-radius: 5px; background: var(--panel-bg); color: var(--fg); cursor: pointer; font: inherit; font-size: 0.75rem; }
.designer-relation-btn:hover { border-color: var(--accent); color: var(--accent); }
.designer-relation-btn small { display: block; color: var(--muted); font-size: 0.65rem; }
.designer-relations-empty { color: var(--muted); font-size: 0.78rem; }
.designer-draft-label { display: inline-block; margin-left: 0.5rem; color: var(--accent); font-size: 0.78rem; font-weight: 700; }
.design-bin {
  position: fixed;
  bottom: 28px;
  left: 50%;
  transform: translateX(-50%) scale(0.85);
  width: 52px;
  height: 52px;
  border-radius: 50%;
  background: var(--panel-bg);
  border: 2px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.5rem;
  opacity: 0;
  pointer-events: none;
  z-index: 60;
  transition: opacity 0.12s, transform 0.12s, background 0.12s, border-color 0.12s;
}
.design-bin.visible { opacity: 1; transform: translateX(-50%) scale(1); }
.design-bin.hover { background: #c92a2a; border-color: #c92a2a; transform: translateX(-50%) scale(1.15); }
.design-exact { font-size: 0.85rem; color: var(--muted); margin: 0 0 0.4rem; }
.design-details { max-width: 780px; margin: 1.5rem auto 0; }
.design-details ul { margin: 0.3rem 0 0.8rem; padding-left: 1.2rem; }
.design-details li { margin-bottom: 0.25rem; }

/* Where the Problem Map Designer's new-problem box would be, when the
   filters don't describe one complete, well-formed problem: says why. */
.designer-draft-hint {
  position: absolute;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 0.6rem;
  border: 2px dashed var(--border);
  border-radius: 4px;
  color: var(--muted);
  font-size: 0.7rem;
  line-height: 1.2;
  text-align: center;
  overflow: hidden;
}
/* The designer's add button sits in the filter row: a long notation is cut
   with an ellipsis (the full text is in its tooltip). */
.designer-add-btn { max-width: 14rem; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.designer-add-btn:not(:disabled) { border-color: var(--accent); color: var(--accent); }

/* Documentation contents: sections and their subsections, linked as
   #/docs/<id>. */
.docs-toc {
  margin: 0 0 2rem;
  padding: 1rem 1.3rem 1.1rem;
  border: 1px solid var(--border);
  border-left: 4px solid var(--hl);
  border-radius: 8px;
  background: var(--panel-bg);
  scroll-margin-top: 1rem;
}
.docs-toc h3 {
  margin: 0 0 0.6rem;
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--hl-fg);
}
.docs-toc ol { margin: 0; padding-left: 1.4rem; line-height: 1.85; }
.docs-toc ol ol { padding-left: 1.2rem; font-size: 0.92em; line-height: 1.6; margin: 0.15rem 0 0.5rem; }
.docs-toc > ol > li { margin-bottom: 0.15rem; }
.docs-toc > ol > li::marker { color: var(--hl-fg); font-weight: 700; }
.docs-toc > ol > li > a { font-weight: 600; }
.docs-toc a { color: var(--accent); text-decoration: none; }
.docs-toc a:hover { text-decoration: underline; }
/* Clear of the heading's own bottom border when jumped to from Contents. */
.docs-section h3, .docs-section h4 { scroll-margin-top: 1.2rem; }

/* The overview's reading guide under its legend: the (i) beside a few
   short paragraphs. */
.sz-map-help {
  display: grid;
  grid-template-columns: auto 1fr;
  column-gap: 0.4rem;
  max-width: 780px;
  text-align: left;
  line-height: 1.5;
}
.sz-map-help .map-hint-icon { grid-row: 1 / span 3; margin-top: 0.2em; }
.sz-map-help p { grid-column: 2; margin: 0 0 0.45rem; }
.sz-map-help p:last-child { margin-bottom: 0; }

/* Scheduling Zoo map: Save as a New Problem Map, bottom right of the box,
   styled like the TikZ button; the box gets room for it at the bottom. */
.sz-save-map-btn {
  position: absolute;
  bottom: 0.5rem;
  right: 0.5rem;
  z-index: 2;
  background: var(--panel-bg);
  border: 1px solid var(--border);
  border-radius: 6px;
  color: var(--fg);
  font-size: 0.75rem;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
}
.sz-save-map-btn:hover { border-color: var(--accent); color: var(--accent); }
#view-schedulingzoo .map-canvas-wrap { padding-bottom: 3.2rem; }

/* Problem Map Designer: title and save, above the map. */
.designer-map-bar { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem; margin: 0 0 0.8rem; }
.designer-map-bar .designer-map-title { flex: 1 1 18rem; max-width: 28rem; }
.designer-save-status { color: var(--muted); font-size: 0.85rem; }
.designer-save-status a { color: var(--accent); }

/* Problem Maps: the create card, and saved maps with a delete button. */
.map-card-new h3 { color: var(--accent); }
.map-card-saved { display: flex; align-items: center; gap: 0.8rem; }
.map-card-saved .map-card-link { flex: 1; min-width: 0; color: inherit; text-decoration: none; }
.map-card-saved .map-card-delete { flex: none; }

/* Problem Map Designer: adding arrows by hand. */
.designer-add-arrow-btn { font-weight: 700; letter-spacing: 0.02em; }
.designer-add-arrow-btn[aria-pressed="true"] { border-color: var(--accent); color: var(--accent); background: var(--chip-bg); }
.arrow-mode .map-node { cursor: crosshair; }
.designer-arrow-hint { margin: 0.6rem 0 0; color: var(--fg); font-size: 0.85rem; text-align: center; }
.designer-user-edge { cursor: pointer; }
.designer-user-edge-hit { stroke: transparent; stroke-width: 12; pointer-events: stroke; }
/* The same arrows on the Scheduling Zoo overview (see szRenderUserEdges).
   They reuse the overview's own hit area, and say so by the cursor: every
   other arrow there opens a read-only explanation, these open the reader's
   own description of the reduction, to edit or remove. */
.sz-user-edge { cursor: pointer; }
/* The hint under the diagram is only there when there is something to say. */
.sz-arrow-hint:empty { display: none; }
.designer-dialog-backdrop {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  background: rgba(0, 0, 0, 0.45);
  padding: 1rem;
}
.designer-dialog {
  max-width: 560px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 10px;
  box-shadow: var(--shadow);
  padding: 1.2rem 1.4rem;
  font-size: 0.9rem;
  line-height: 1.5;
}
.designer-dialog h3 { margin: 0 0 0.7rem; font-size: 1.05rem; }
.designer-dialog ul { padding-left: 1.1rem; }
.designer-dialog-actions { display: flex; flex-wrap: wrap; justify-content: flex-end; gap: 0.5rem; margin-top: 1rem; }
.designer-dialog-report { text-decoration: none; border-color: var(--accent); color: var(--accent); }
.designer-dialog-claim b { color: inherit; }
.designer-dialog-source { color: var(--muted); }

/* Adding an arrow: the instruction floats at the top of the window, and the
   problem under the pointer (and the chosen origin) glows yellow. */
.designer-arrow-toast {
  position: fixed;
  top: 1rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 55;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.1rem;
  padding: 0.6rem 1.2rem;
  border: 1px solid #fcc419;
  border-radius: 8px;
  background: var(--bg);
  box-shadow: var(--shadow), 0 0 14px rgba(252, 196, 25, 0.35);
  font-size: 0.95rem;
  pointer-events: none;
  animation: designer-toast-in 0.15s ease-out;
}
.designer-arrow-toast b { color: #fcc419; letter-spacing: 0.01em; }
.designer-arrow-toast span { color: var(--muted); font-size: 0.75rem; }
@keyframes designer-toast-in { from { opacity: 0; transform: translate(-50%, -6px); } to { opacity: 1; transform: translate(-50%, 0); } }
.arrow-mode .map-node:hover,
.map-node.arrow-origin {
  outline: 3px solid #fcc419 !important;
  outline-offset: 3px;
  box-shadow: 0 0 0 4px rgba(252, 196, 25, 0.3), 0 0 18px rgba(252, 196, 25, 0.85) !important;
  z-index: 4;
}

/* Describing a hand-drawn reduction. */
.designer-reduction-dialog { max-width: 640px; max-height: calc(100vh - 2rem); overflow-y: auto; }
.designer-reduction-problem {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.92em;
  padding: 0.05rem 0.35rem;
  border-radius: 4px;
  background: var(--chip-bg);
  white-space: nowrap;
}
.designer-reduction-dialog h3 { line-height: 1.6; }
.designer-reduction-dialog fieldset { border: 1px solid var(--border); border-radius: 8px; margin: 0 0 0.7rem; padding: 0.4rem 0.8rem 0.6rem; }
.designer-reduction-dialog legend { padding: 0 0.3rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted); }
.designer-reduction-dialog legend a { text-transform: none; letter-spacing: 0; margin-left: 0.4rem; color: var(--accent); }
.designer-reduction-option { display: flex; align-items: flex-start; gap: 0.5rem; padding: 0.2rem 0; cursor: pointer; }
.designer-reduction-option input { margin-top: 0.3rem; }
.designer-reduction-option small { display: block; color: var(--muted); font-size: 0.78rem; line-height: 1.35; }
.designer-reduction-params { display: flex; flex-wrap: wrap; gap: 0.3rem; margin: 0.3rem 0 0 1.5rem; }
.designer-reduction-params.disabled { opacity: 0.4; }
.designer-reduction-params .chip { padding: 0.15rem 0.5rem; font-size: 0.75rem; }
.designer-reduction-params .chip input { display: none; }
.designer-reduction-note { display: block; font-size: 0.85rem; }
.designer-reduction-note small { color: var(--muted); }
.designer-reduction-note input { display: block; width: 100%; max-width: none; margin-top: 0.3rem; }

/* "Classify it yourself" affordances in the Scheduling Zoo panel: the class
   pill beside the notation, and each box in the parameter diagram. A reader's
   own claim is always drawn dashed, and labelled "yours, unverified", so it
   can never be mistaken for one of the cited results around it. */
button.class-pill.classify-btn {
  font: inherit;
  font-weight: 600;
  font-size: 0.85rem;
  cursor: pointer;
}
button.class-pill.classify-btn:hover { filter: brightness(1.12); }
button.class-pill.classify-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.classify-mine { border-style: dashed !important; }
g.sz-pt-classify { cursor: pointer; }
g.sz-pt-classify:hover rect { filter: brightness(1.15); }

/* A problem the reader classified themselves: a blue ring OUTSIDE the node's
   own border, wider than it, so the border still reads on top of it. That
   keeps the two facts separate -- the border and fill say which class, the
   blue ring says "this one is mine" -- and it works even for the unfilled
   classes, where an unfilled node already means "at least weakly NP-hard"
   and its orange border simply sits over the blue. */
.map-node.user-classified {
  box-shadow: 0 0 0 4px #2563eb, 0 1px 3px rgba(0, 0, 0, 0.25) !important;
}
@media (prefers-color-scheme: dark) {
  .map-node.user-classified {
    box-shadow: 0 0 0 4px #3b82f6, 0 1px 3px rgba(0, 0, 0, 0.5) !important;
  }
}
/* The designer's selection ring is also blue, so a selected node that the
   reader classified shows the selection further out, at its own offset. */
.map-node.user-classified.designer-selected { outline-offset: 6px; }

/* A problem the reader did NOT classify, but whose class moved because of
   one they did: a claim supersedes the corpus, and its consequences travel
   along the arrows. A soft light-blue glow rather than the solid ring --
   same colour family, so the link to the claim is obvious, but clearly the
   weaker mark of the two. */
.map-node.user-affected {
  box-shadow: 0 0 9px 3px rgba(96, 165, 250, 0.7), 0 1px 3px rgba(0, 0, 0, 0.25) !important;
}
/* Claimed AND affected can't both apply to one node -- a direct claim is
   never overridden -- so there is no combined case to resolve. */

/* The lens (Scheduling Zoo overview): two switches on the right edge of
   the box, vertically centred so they sit clear of the top-row button
   clusters at any label width. Written vertically, like tabs on the side
   of a binder, so they are a ~2rem strip -- and the box reserves that
   strip (padding-right below), the same way it reserves 4.5rem on top for
   the button rows, so no node is ever underneath them. */
.sz-lens {
  position: absolute;
  top: 50%;
  right: 0.5rem;
  transform: translateY(-50%);
  z-index: 2;
  display: flex;
  flex-direction: column;
  gap: 0.3rem;
}
#view-schedulingzoo .map-canvas-wrap { padding-right: 3.4rem; }
.sz-lens-btn {
  background: var(--panel-bg);
  border: 1px solid var(--border);
  color: var(--fg);
  border-radius: 6px;
  padding: 0.7rem 0.35rem;
  font-size: 0.78rem;
  cursor: pointer;
  white-space: nowrap;
  writing-mode: vertical-rl;
  text-orientation: mixed;
}
.sz-lens-btn:hover { border-color: var(--accent); color: var(--accent); }
.sz-lens-btn[aria-pressed="true"] {
  border-color: var(--hl);
  background: var(--hl-wash);
  color: var(--hl-fg);
}
.sz-lens-count { margin-left: 0.4rem; opacity: 0.6; font-variant-numeric: tabular-nums; }
/* With a lens on, the nodes that have that kind of result glow white and
   everything else dims. The glow is white in both themes -- on the light
   theme it barely reads against the panel on its own, which is exactly why
   the rest dims: the contrast is the dimming, the glow is the mark. The
   !important matches the user-classified / user-affected rings above, and
   a node that is both lit and claimed keeps its ring outside the glow. */
.map-diagram[data-lens] .sz-node { opacity: 0.45; }
.map-diagram[data-lens="params"] .sz-node.has-params,
.map-diagram[data-lens="approx"] .sz-node.has-approx,
.map-diagram[data-lens="open"] .sz-node.has-open {
  opacity: 1;
  z-index: 2;
  box-shadow: 0 0 0 2px #fff, 0 0 14px 6px rgba(255, 255, 255, 0.95), 0 1px 3px rgba(0, 0, 0, 0.25) !important;
}
.map-diagram[data-lens="params"] .sz-node.has-params.user-classified,
.map-diagram[data-lens="approx"] .sz-node.has-approx.user-classified,
.map-diagram[data-lens="open"] .sz-node.has-open.user-classified {
  box-shadow: 0 0 0 2px #fff, 0 0 14px 6px rgba(255, 255, 255, 0.95), 0 0 0 4px #2563eb !important;
}
/* The softer tier: no result of its own, but one reaches it along the
   arrows. Same white, half the reach, so the two read as one family with
   an obvious stronger and weaker member. */
.map-diagram[data-lens="params"] .sz-node.has-params-implied,
.map-diagram[data-lens="approx"] .sz-node.has-approx-implied,
.map-diagram[data-lens="open"] .sz-node.has-open-implied {
  opacity: 1;
  z-index: 2;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.75), 0 0 8px 3px rgba(255, 255, 255, 0.55), 0 1px 3px rgba(0, 0, 0, 0.25) !important;
}
.sz-lens-implied { opacity: 0.75; }
/* The same lens inside the problem panel: with it on, the results of that
   kind glow and the rest of the results dim, exactly as the nodes do. The
   glow sits on the <li> itself, so it wraps whatever a result renders as
   (a plain citation or a param-tree row). */
.sz-panel[data-lens] .result-list li { opacity: 0.5; transition: opacity 0.15s; }
/* A lit line is a lifted card, not a ring drawn round the text: room
   inside it, a faint fill, and a wide soft halo. On the light theme a
   white halo is invisible, so there it lifts with a drop shadow instead. */
.sz-panel[data-lens="params"] .detail-params .result-list li,
.sz-panel[data-lens="approx"] .result-list li.result-approx {
  opacity: 1;
  padding: 0.6rem 0.8rem;
  margin: 0.2rem -0.2rem;
  border-radius: 10px;
  background: #fff;
  box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.06), 0 3px 16px rgba(0, 0, 0, 0.14);
}
@media (prefers-color-scheme: dark) {
  .sz-panel[data-lens="params"] .detail-params .result-list li,
  .sz-panel[data-lens="approx"] .result-list li.result-approx {
    background: rgba(255, 255, 255, 0.055);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.28), 0 0 22px 4px rgba(255, 255, 255, 0.22), inset 0 0 18px rgba(255, 255, 255, 0.04);
  }
}
/* The parameterized section's own heading is the mark that it is the lit
   section; its list needs no dimming of its own. */
.sz-panel[data-lens="params"] .detail-params h4 { text-shadow: 0 0 12px rgba(255, 255, 255, 0.7); }

/* Panel: the reader's classification and the corpus one, one labelled line
   each. Deliberately not upper-cased -- these are two competing claims to
   compare, not section headings. */
.detail-class-row {
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  gap: 0.45rem;
  margin: 0.3rem 0;
}
/* "Open, but not in P unless FPT = W[1]" -- the same shape as the online
   note, in the open class's own grey so it does not read as a warning. */
.detail-whard {
  border-left: 3px solid var(--border);
  padding-left: 0.7rem;
}
.detail-whard h4 { color: var(--muted); }

/* The "this is an online problem" note in a problem's panel, in that
   class's own teal so it reads as the same thing as the node's colour.
   The heading is a step darker than the node fill: the fill as small type
   on the light theme's white is too pale to read. */
.detail-online {
  border-left: 3px solid #6fa1ab;
  padding-left: 0.7rem;
}
.detail-online h4 { color: #4a7680; }
@media (prefers-color-scheme: dark) {
  .detail-online h4 { color: #9dc2ca; }
}
.detail-class-label { color: var(--muted); font-size: 0.85rem; }
.detail-class-aside { color: var(--muted); font-size: 0.78rem; }

/* The panel heading, read one part at a time: every token of α|β|γ is its
   own hoverable (and focusable, and tappable) chip, and the explanation
   appears in ONE tooltip under the whole heading. Under the heading rather
   than under the token so it never has to be clamped against the panel's
   edge, and never has to move when a long name wraps. */
.detail-notation { position: relative; margin-bottom: 0.6rem; }
.notation-part {
  border-bottom: 1px dotted var(--muted);
  border-radius: 3px;
  padding: 0 1px;
  cursor: help;
}
.notation-part:hover,
.notation-part:focus,
.notation-part.active {
  background: var(--chip-bg);
  border-bottom-color: var(--accent);
  color: var(--accent);
  outline: none;
}
/* The separators are structure, not content: never highlighted, and never
   a target -- pointing between two fields should explain neither. */
.notation-sep { color: var(--muted); font-weight: 400; padding: 0 1px; }
/* "generalizes", between the two names in an arrow's heading. */
.notation-verb { color: var(--muted); font-weight: 400; }
.notation-tip {
  position: absolute;
  left: 0; right: 0; top: 100%;
  z-index: 3;
  margin-top: 0.3rem;
  padding: 0.45rem 0.6rem;
  border: 1px solid var(--accent);
  border-radius: 6px;
  background: var(--panel-bg);
  box-shadow: var(--shadow);
  font-size: 0.82rem;
  font-weight: 400;
  line-height: 1.45;
  white-space: normal;
}
.notation-tip-field { color: var(--muted); }
.notation-hint { margin: 0.2rem 0 0.6rem; color: var(--muted); font-size: 0.8rem; }

/* Shift-clicked into a selection, to drag (or drag out) as a group. A
   dashed neutral ring: solid neutral is the designer's single selection and
   blue belongs to the reader's own classifications, so this needs to be
   readable as "several picked out" without claiming either of those. */
.sz-node.sz-selected {
  outline: 2px dashed var(--fg);
  outline-offset: 2px;
  z-index: 3;
}

/* "Send my classifications" and "Reset my classifications": sit at the
   bottom-left of the diagram, facing "Save as a New Problem Map" at the
   bottom-right -- all of them actions on work the reader has done, kept away
   from the view controls up top. Only rendered once there is something to
   send. They wrap on a narrow diagram rather than run off it. */
.sz-claims-actions {
  position: absolute;
  bottom: 0.5rem;
  left: 0.5rem;
  z-index: 2;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem;
  max-width: calc(100% - 1rem);
}
/* display:flex above would otherwise beat the [hidden] default. */
.sz-claims-actions[hidden] { display: none; }
.sz-submit-claims-btn,
.sz-reset-claims-btn {
  background: var(--panel-bg);
  border: 1px solid #3b82f6;
  border-radius: 6px;
  color: var(--fg);
  font-size: 0.75rem;
  padding: 0.3rem 0.6rem;
  cursor: pointer;
}
.sz-submit-claims-btn:hover { border-color: var(--accent); color: var(--accent); }
/* Destructive, so it is the quiet one of the pair until pointed at, and
   then it turns the colour of the thing it undoes. */
.sz-reset-claims-btn { border-color: var(--border); color: var(--muted); }
.sz-reset-claims-btn:hover { border-color: #cf4444; color: #cf4444; }

/* The box drawn by dragging across empty canvas to select nodes. Lives
   inside .map-canvas, so it is positioned in canvas units and scales with
   the diagram like everything else. */
.sz-marquee {
  position: absolute;
  z-index: 4;
  border: 1px dashed var(--fg);
  background: rgba(128, 128, 128, 0.14);
  pointer-events: none;
}

/* Arrows the reader draws between parameters in a problem panel's diagram
   (see showParamArrowDialog): the same two-click mode as the map's →+. */
.sz-pt-arrow-bar { display: flex; align-items: center; gap: 0.5rem; margin: 0 0 0.4rem; }
.sz-pt-arrow-bar .sz-arrow-hint { font-size: 0.8rem; color: var(--muted); }
.param-tree-wrap.arrow-mode g.sz-pt-node { cursor: crosshair; }
g.sz-pt-node.arrow-origin rect { stroke: #fcc419 !important; stroke-width: 3; filter: drop-shadow(0 0 6px rgba(252, 196, 25, 0.85)); }
g.sz-pt-user-edge { cursor: pointer; }
g.sz-pt-user-edge .sz-pt-user-edge-hit { stroke: transparent; stroke-width: 12; pointer-events: stroke; }
g.sz-pt-user-edge:hover path:not(.sz-pt-user-edge-hit) { stroke-width: 3; }

/* Routed arrows are <path>s now (see edgePathD): never filled. */
svg path[data-from], svg path[data-to], svg path[data-sz-from], svg path[data-sz-pt-from] { fill: none; }

/* ---- the Scheduling Zoo problem panel (openSchedulingZooPanel) ---- */
.sz-toc {
  position: sticky; top: 0; z-index: 2;
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.2rem 0.75rem;
  margin: 0 0 0.7rem; padding: 0.35rem 0;
  background: var(--panel-bg); border-bottom: 1px solid var(--border);
  font-size: 0.78rem;
}
.sz-toc a { color: var(--muted); text-decoration: none; cursor: pointer; }
.sz-toc a:hover { color: var(--fg); text-decoration: underline; }
.sz-sec { margin: 0 0 1rem; scroll-margin-top: 2.6rem; }
.sz-sec h4 { margin: 0 0 0.3rem; font-size: 0.75rem; text-transform: uppercase; letter-spacing: 0.04em; color: var(--muted); }
.sz-sec h5 { margin: 0.5rem 0 0.25rem; font-size: 0.78rem; font-weight: 600; color: var(--muted); }
.sz-note { margin: 0 0 0.4rem; font-size: 0.82rem; color: var(--muted); line-height: 1.35; }
.sz-note b { color: var(--fg); }
.sz-legend-line { margin: 0.4rem 0 0; font-size: 0.78rem; display: flex; flex-wrap: wrap; gap: 0.2rem 0.8rem; }
/* One folded card per parameter (buildParamTreeHtml): the summary line is
   the whole answer, the results wait behind a click. */
.sz-param-card { margin: 0.3rem 0; border: 1px solid var(--border); border-radius: 8px; background: rgba(127, 127, 127, 0.05); scroll-margin-top: 2.6rem; }
.sz-param-card > summary { list-style: none; cursor: pointer; padding: 0.3rem 0.55rem; }
.sz-param-card > summary::-webkit-details-marker { display: none; }
.sz-param-card > summary:hover { background: rgba(127, 127, 127, 0.08); }
.sz-param-card[open] > summary { border-bottom: 1px solid var(--border); }
.sz-param-head { display: flex; align-items: center; flex-wrap: wrap; gap: 0.35rem 0.5rem; min-height: 1.4rem; }
.sz-param-head .class-pill { padding: 0.1rem 0.5rem; font-size: 0.7rem; }
.sz-param-name { font-weight: 700; font-size: 0.86rem; }
.sz-param-why { color: var(--muted); font-size: 0.75rem; min-width: 0; }
.sz-param-yours { color: var(--muted); font-size: 0.72rem; }
.sz-param-count { margin-left: auto; color: var(--muted); font-size: 0.7rem; }
.sz-param-count::after { content: " ▸"; }
.sz-param-card[open] .sz-param-count::after { content: " ▾"; }
.sz-param-body { padding: 0.35rem 0.55rem 0.45rem; }
.sz-res-line { font-size: 0.84rem; line-height: 1.4; padding: 0.15rem 0 0.15rem 0.5rem; border-left: 3px solid var(--border); margin: 0.2rem 0; }
.sz-res-line.result-lower { border-left-color: #cf4444; }
.sz-res-line.result-upper { border-left-color: #2c8a3f; }
.sz-res-line .sz-res-path { display: inline; }
.sz-res-line .sz-res-path::before { content: "· "; }
.sz-badges { white-space: nowrap; }
.sz-cite-badge {
  background: none; border: 0; padding: 0 0.1rem; margin: 0; cursor: pointer; font: inherit; font-size: 0.78rem;
  color: var(--accent); text-decoration: underline dotted;
}
.sz-cite-badge:hover, .sz-cite-badge.is-open { text-decoration: underline solid; }
.sz-res-detail { font-size: 0.78rem; color: var(--muted); padding: 0.1rem 0 0.1rem 0.5rem; margin: 0.1rem 0 0.1rem 0.6rem; border-left: 2px dotted var(--border); }
.sz-res-detail.result-lower { border-left-color: #cf4444; }
.sz-res-detail.result-upper { border-left-color: #2c8a3f; }
.sz-res-detail .sz-res-bound { color: var(--fg); }
.sz-res-bound { font-weight: 500; }
/* Classical and approximation results as the same cards, edged by side. */
.sz-res-card { border-left-width: 3px; }
.sz-res-card.result-lower { border-left-color: #cf4444; }
.sz-res-card.result-upper { border-left-color: #2c8a3f; }
.sz-res-card .sz-param-name { font-weight: 500; font-size: 0.82rem; }
.sz-res-card .result-list li { border-left: 0; background: none; padding: 0.15rem 0; }
.sz-res-gap { margin: 0.3rem 0 0.1rem; padding: 0.25rem 0.5rem; font-size: 0.78rem; color: var(--muted); border-left: 3px solid #f29a1f; background: rgba(242, 154, 31, 0.07); border-radius: 0 6px 6px 0; }
.sz-res-title { color: var(--muted); font-size: 0.78rem; }
.sz-res-cite { color: var(--muted); }
.sz-res-cite a { color: var(--accent); text-decoration: underline dotted; }
.sz-res-path { color: var(--muted); font-size: 0.76rem; margin-top: 0.1rem; }
.sz-panel .result-list li.sz-result-minor { border-left-color: var(--border); color: var(--muted); font-size: 0.78rem; padding: 0.2rem 0.55rem; }
.sz-panel .result-list li.sz-result-minor .sz-res-bound { font-weight: 500; }
/* Classical and approximation results as the same cards, edged by side. */
.sz-res-card { border-left-width: 3px; }
.sz-res-card.result-lower { border-left-color: #cf4444; }
.sz-res-card.result-upper { border-left-color: #2c8a3f; }
.sz-res-card .sz-param-name { font-weight: 500; font-size: 0.82rem; }
.sz-res-card .result-list li { border-left: 0; background: none; padding: 0.15rem 0; }
.sz-res-gap { margin: 0.3rem 0 0.1rem; padding: 0.25rem 0.5rem; font-size: 0.78rem; color: var(--muted); border-left: 3px solid #f29a1f; background: rgba(242, 154, 31, 0.07); border-radius: 0 6px 6px 0; }
.sz-res-title { color: var(--muted); font-size: 0.78rem; }
.sz-panel .result-list { gap: 0.35rem; }
.sz-panel .result-list li {
  padding: 0.3rem 0.55rem; font-size: 0.84rem; line-height: 1.35;
  border-left: 3px solid var(--border); border-radius: 0 6px 6px 0;
  background: rgba(127, 127, 127, 0.06);
}
.sz-panel .result-list li.result-lower { border-left-color: #cf4444; }
.sz-panel .result-list li.result-upper { border-left-color: #2c8a3f; }
.sz-panel .result-list li p { margin: 0 0 0.15rem !important; }
.sz-source { color: var(--muted); font-size: 0.74rem; border-top: 1px solid var(--border); padding-top: 0.5rem; }
.sz-source p { margin: 0; }
.sz-jump { color: var(--accent); text-decoration: underline dotted; cursor: pointer; }

/* ---- open problems (Mnich & van Bevern 2018): the ? flag, the diagram
   badge, the card, and the panel under the "open" lens ---- */
.sz-open-flag {
  display: inline-flex; align-items: center; justify-content: center;
  width: 1.05rem; height: 1.05rem; border-radius: 50%; flex: none;
  background: #fcc419; color: #111; font-size: 0.7rem; font-weight: 700; line-height: 1;
}
.sz-open-chip {
  padding: 0.1rem 0.5rem; border-radius: 999px; font-size: 0.7rem; font-weight: 600;
  border: 2px dashed #868e96; color: var(--muted);
}
.sz-open-q { margin: 0 0 0.3rem; font-size: 0.84rem; line-height: 1.4; }
.sz-open-card { border-left: 3px solid #fcc419; }
.sz-open-line { font-size: 0.78rem; color: var(--muted); margin-bottom: 0.25rem; display: flex; align-items: center; gap: 0.35rem; }
.sz-open-line b { color: var(--fg); font-weight: 600; }
.sz-param-card.sz-has-open { border-color: #fcc419; }
g.sz-pt-open { filter: drop-shadow(0 0 3px #fcc419); }
g.sz-pt-open-badge circle { fill: #fcc419; stroke: var(--panel-bg); stroke-width: 1.5; }
g.sz-pt-open-badge text { fill: #111; }
.sz-panel[data-lens="open"] .sz-open-card,
.sz-panel[data-lens="open"] .sz-param-card.sz-has-open {
  background: rgba(252, 196, 25, 0.1);
  box-shadow: 0 0 0 1px rgba(252, 196, 25, 0.6), 0 0 14px 2px rgba(252, 196, 25, 0.35);
}
.sz-panel[data-lens="open"] .sz-sec-open h4 { text-shadow: 0 0 12px rgba(252, 196, 25, 0.8); }

/* A result this site added on top of The Scheduling Zoo (additional_results.json). */
.sz-added-mark { color: var(--muted); cursor: help; margin-left: 1px; font-size: 0.8em; }
