
/* NO WEBFONT IMPORT, deliberately (T150). Every output mode inlines
   this file verbatim -- the app page, the exported .html, the deck's
   standalone export (it copies the head's <style> blocks) and the
   widget's scoped copy -- so an @import of a hosted font meant that
   "self-contained" quietly included two servers, and a page read on a
   plane fell back to whatever the OS had. The families below stay
   FIRST in each stack: anyone who has IBM Plex installed still gets
   it, and nobody's page waits on a font server to draw its text. */

:root{
  /* T626: amber is a SCHEME token -- each scheme below says its own,
     darker in the light ones. It sat on `*` with a literal, so no
     scheme could re-ink it (2.1-2.5:1 on every light face). */
  --amber:#cf9a4e; --amber-soft:#caa06a66;
  --ink:#16202b; --ink-2:#33414f; --ink-3:#69788a;
  --paper:#fbfcfd; --paper-2:#eef2f6; --paper-3:#e2e8ee;
  --line:#d8e0e8;
  /* --chrome-2 is the SURFACE every menu, dialog, popup and input in
     the app sits on. It carried an alpha byte - the value ended in 44,
     i.e. 27% opaque - so every one of them was see-through and unreadable
     against whatever happened to be behind it — worst on the theme
     picker, which opens over the ribbon (2026-08-20, user: "some of
     the pop up menus like changing the theme still have weird
     transparent background"). Every consumer that wants
     translucency mixes its own with color-mix; none of them wanted
     this. The opaque value is the one every fallback already used. */
  --chrome:#11202c;--chrome-0:#0b141d;--chrome-1:#0e1926;
  --chrome-2:#162735;--chrome-3:#101c28;--chrome-4:#172838;
  --chrome-line:#ffffff14;
  --chrome-ink:#cdd9e3;--chrome-ink-2:#7e93a4;
  --chrome-ink-3:#607789;
  /* ---- the PRODUCT theme tokens. --paper-N / --ink-N draw the
     document and welcome surface; --chrome-N / --chrome-ink-N draw the
     app, editor, menus and panes; the remaining semantic colours cover
     interaction and feedback. A scheme redefines the complete set so a
     new component follows it without needing `body.light .thing` glue.
     Author-selected deck/figure colours and the fixed code-kind palette
     remain document data, not app chrome. */
  --accent:#39a9c0; --accent-deep:#1f7e93; --accent-soft:#8fd8ea;
  /* the resting FACE of every button. The first scheme pass only moved
     the accents, so buttons kept their hardcoded white-alpha faces and a
     theme looked like "just the central page" (2026-08-19, user). Now a
     scheme re-inks these and every button follows. */
  --btn-bg:#ffffff12; --btn-border:#ffffff40; --btn-ink:#d7e3ec;
  --surface-hover:#00000008;--surface-active:#00000012;
  --border-strong:#798b9b;--input-bg:#ffffff;
  --tooltip-bg:#172330;--tooltip-ink:#f2f6fa;
  /* Rich notebook outputs and slide previews are authored light islands.
     They do not inherit app-theme ink, which would make a white output
     white-on-white under a dark theme. */
  --output-paper:#fbfcfd;--output-ink:#16202b;
  --output-ink-2:#33414f;--output-line:#d8e0e8;
  --overlay:#07111bb8;--shadow:#00000080;
  --focus:var(--accent-soft);--selection:#39a9c04d;
  --danger:#ff796a;--warning:#e0a33a;--success:#46a892;
  --on-accent:#ffffff;--on-accent-deep:#ffffff;
  /* ---- the CODE-KIND palette: the single CSS source. The JS twin is
     TREE_FILL in app.js (exported as window.SemView.kindFill, which
     deck.js's NODE_FILL reads). One colour serves two kind names where
     they align: function/metric, data/dataset, settings/transform,
     print/note. Plotting/figure stay on var(--accent) — they follow the
     theme, deliberately not part of this fixed set. */
  --ck-imports:#a3855c; --ck-function:#46a892; --ck-data:#4d90c0;
  --ck-constant:#9a7cc0; --ck-settings:#5b7589; --ck-print:#cf9a4e;
  --ck-code:#8ba0b2;
}
/* The legacy --cyan alias must resolve PER ELEMENT, not once at :root:
   a custom property defined on :root evaluates its var() there and
   inherits the frozen result, so `--cyan:var(--accent)` on :root pinned
   every var(--cyan) rule to the default accent and no theme could touch
   them — which is why the first scheme pass "only changed the central
   page" (2026-08-19). On * each element re-resolves against the accent
   it actually inherits, so group-scoped accents reach every rule. */
*{--cyan:var(--accent); --cyan-deep:var(--accent-deep);
  --sans:'IBM Plex Sans',system-ui,'Segoe UI',Roboto,
    -apple-system,'Helvetica Neue',Arial,sans-serif;
  /* the mono stack carries the weight of the page (labels, chips, code
     runs, captions) and had the worst fallback: ui-monospace is ignored
     by Chrome on Windows and Menlo is macOS-only, so a Windows reader
     dropped all the way to Courier New. Cascadia/Consolas first, then
     the mac and Linux defaults. */
  --mono:'IBM Plex Mono',ui-monospace,'Cascadia Mono',Consolas,
    'SF Mono',Menlo,'DejaVu Sans Mono',monospace;
  --serif:'IBM Plex Serif',Georgia,'Times New Roman',serif;
  --rad:6px; --rail-w:300px;
}
*{box-sizing:border-box}
/* ---- button icons: inline SVG, never emoji (emoji are tofu in the mono
   font). One 16-grid, stroke-only, currentColor — so an icon is always
   the same weight as the label beside it and follows the theme. The
   base rule lives HERE (not app.css) because every bundle that shows a
   .bic needs it: the app page, the widget's scoped core.css, and card
   chrome cloned into decks. inline-block, not block: icons sit inside
   flex buttons (where display is blockified anyway) AND inline in text
   labels, where block would break the line. ---- */
.bic{width:14px;height:14px;flex:none;display:inline-block;
  vertical-align:-2px;stroke:currentColor;stroke-width:1.5;fill:none;
  stroke-linecap:round;stroke-linejoin:round;opacity:.9;}
/* reserve the scrollbar's width at all times: without it, switching to a
   view that does not scroll the page (the tree) widens the viewport and
   the CENTRED ribbon slides sideways — every button moving a few px is
   exactly the jump the user reported (2026-07-30) */
html{scroll-behavior:smooth;scrollbar-gutter:stable}
body{margin:0;font-family:var(--sans);color:var(--ink);
  background:var(--paper-2);line-height:1.5;
  -webkit-font-smoothing:antialiased;text-rendering:optimizeLegibility;}

/* ---------- layout ---------- */
.shell{display:grid;grid-template-columns:var(--rail-w) 1fr;min-height:100vh;}
.rail{position:sticky;top:0;height:100vh;overflow-y:auto;
  background:var(--chrome);color:var(--chrome-ink);
  border-right:1px solid var(--chrome-line);
  display:flex;flex-direction:column;}
.stage{min-width:0;}

/* ---------- rail header ---------- */
.railhead{padding:22px 22px 16px;border-bottom:1px solid var(--chrome-line);}
.nbshell .railhead{padding:10px 12px;position:relative;}
/* T624: the colour key's "?" rides the Options row, at its right end --
   beside the summary it would be inside the <details>, and a click on it
   would fold the menu */
.railhead>button.jv-q{position:absolute;top:13px;right:12px;margin:0;}
.outline-tools{position:relative;margin:0;}
.outline-tools summary{list-style:none;}
.outline-tools summary::-webkit-details-marker{display:none;}
.outline-tools summary::after{content:"▾";margin-left:auto;}
.outline-tools:not([open]) summary::after{content:"▸";}
.outline-options-menu{display:grid;grid-template-columns:1fr 1fr;gap:6px;
  padding-top:7px;}
.outline-options-menu label{grid-column:1/-1;display:flex;align-items:center;
  gap:5px;font:11px var(--sans);color:var(--chrome-ink-2);}
.outline-options-menu .rf-unhide{grid-column:1/-1;justify-content:flex-start;}
.outline-hide-hidden:not(.reveal-hidden) .navsec-row.sec-off,
.outline-hide-hidden:not(.reveal-hidden) .navsec-row.sec-under-off,
.outline-hide-hidden:not(.reveal-hidden) .navsec-row.head-off,
.outline-hide-hidden:not(.reveal-hidden) .navsec-row.sec-off+.navitems,
.outline-hide-hidden:not(.reveal-hidden) .navsec-row.sec-under-off+.navitems{display:none;}
.brand{font-family:var(--mono);font-size:10.5px;letter-spacing:.22em;
  text-transform:uppercase;color:var(--cyan);margin:0 0 12px;display:flex;
  align-items:center;gap:8px;}
.brand::before{content:"";width:7px;height:7px;border-radius:50%;
  background:var(--cyan);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 16%,transparent);}
/* a file name, in the face file names are written in. Smaller than the
   heading it replaced because a name has no spaces to wrap at and the
   rail is 256px wide. */
.railtitle{font-size:16px;font-weight:600;line-height:1.3;margin:0;
  color:#eef4f8;letter-spacing:-.01em;font-family:var(--mono);
  overflow-wrap:anywhere;}
/* the notebook's first heading, under the notebook's name */
.raildoct{font-size:12.5px;line-height:1.4;color:var(--chrome-ink-2);
  margin-top:5px;}
.railmeta{font-family:var(--mono);font-size:10.5px;color:var(--chrome-ink-2);
  margin-top:8px;letter-spacing:.02em;}
/* where this notebook came from: path + git commit + earlier versions,
   with the reload button beside it (it used to hide on the tab).
   It is DOCKED above the notebook ribbon, and the margin that spaced it
   under the notebook's name goes when it is. */
.railfile{display:flex;gap:4px;margin-top:11px;}
#file-dock .railfile{margin-top:0;gap:3px;}
/* the ribbon has ONE height and one baseline; a docked bar that keeps
   its sidebar metrics is exactly how that rule gets broken quietly */
#file-dock .rf-btn{height:28px;box-sizing:border-box;padding:0 7px;
  font-size:10.5px;flex:none;white-space:nowrap;}
#file-dock .rf-info{flex:none;max-width:150px;}
#file-dock .rf-reload{font-size:11px;padding:0 8px;}
.rf-btn{font-family:var(--sans);font-size:11.5px;letter-spacing:0;
  border:1px solid var(--btn-border);background:var(--btn-bg);
  color:var(--btn-ink);
  padding:6px 10px;border-radius:5px;cursor:pointer;
  transition:color .13s,background-color .13s,border-color .13s,
    box-shadow .13s,opacity .13s;
  display:inline-flex;align-items:center;gap:5px;line-height:1;}
.rf-btn:hover{border-color:var(--accent);color:var(--chrome-ink);
  background:var(--surface-active);}
.rf-info{flex:1;justify-content:flex-start;min-width:0;}
.rf-reload{flex:none;font-size:12px;padding:5px 9px;}
.rf-btn[hidden]{display:none!important;}
/* ---- CUSTOM VIEW: the styling bar + style panel (2026-07-29) --------
   A custom view is edited IN the document (you see exactly what you get),
   so its chrome is a second bar under the filter ribbon rather than a
   separate stage. */
/* NOWRAP like every other toolbar (2026-08-24 — it used to wrap and
   become a second band of chrome on narrow windows). fitRibbon measures
   this bar too: under pressure it shares rbc1's spacing stage, and the
   floor is the same sideways scroll the appbar uses — nothing is ever
   clipped unreachable, nothing wraps. */
.stylebar{display:flex;align-items:center;gap:8px;flex-wrap:nowrap;
  overflow-x:auto;scrollbar-width:thin;
  padding:7px 16px 8px;border-top:1px solid var(--chrome-line);
  background:var(--chrome-1);}
body.rbc1 .stylebar{gap:4px;}
body.rbc1 .stylebar .toggle{padding:0 9px;}
.stylebar[hidden]{display:none;}
.sb-name{font-family:var(--sans);font-size:13px;font-weight:600;
  color:var(--chrome-ink);max-width:220px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;}
body.light .sb-name{color:var(--ink);}
.sb-spring{flex:1;}
.stylebar .toggle{height:30px;box-sizing:border-box;padding:0 13px;
  font-size:11.5px;flex:none;white-space:nowrap;
  border:1px solid var(--btn-border);background:var(--btn-bg);
  color:var(--btn-ink);
  border-radius:6px;cursor:pointer;font-family:var(--mono);
  display:inline-flex;align-items:center;line-height:1;}
.stylebar .toggle:hover{border-color:var(--accent);color:var(--chrome-ink);}
.stylebar .toggle[hidden]{display:none!important;}
.stylebar .toggle.primary{background:var(--accent-deep);
  border-color:var(--accent-deep);color:var(--on-accent-deep);font-weight:600;}
.stylebar .toggle[aria-pressed="true"]{background:var(--accent-deep);
  border-color:var(--accent-deep);color:var(--on-accent-deep);}
/* the panel floats at body level — a sticky/positioned ancestor would
   trap it behind the header (the File-info panel learned this already) */
.stylepanel{position:fixed;z-index:210;width:302px;max-height:74vh;
  overflow-y:auto;background:var(--chrome-2);border:1px solid var(--chrome-line);
  border-radius:9px;padding:11px 12px 13px;
  box-shadow:0 14px 44px var(--shadow);}
.stylepanel[hidden]{display:none;}
.sp-h{font-family:var(--mono);font-size:9px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--chrome-ink-3);padding:0 0 8px;}
.sp-sub{font-size:11.5px;color:var(--chrome-ink-2);
  padding:0 0 9px;line-height:1.45;}
.sp-row{display:flex;align-items:center;gap:8px;padding:4px 0;}
.sp-rl{flex:1;font-size:12px;color:var(--chrome-ink);}
.sp-row input[type=color]{width:34px;height:24px;padding:0;flex:none;
  background:none;border:1px solid var(--chrome-line);border-radius:5px;
  cursor:pointer;}
.sp-row input[type=range]{width:118px;flex:none;}
.sp-row select,.sp-num{background:var(--input-bg);
  border:1px solid var(--border-strong);color:var(--chrome-ink);
  font-family:var(--mono);font-size:11px;padding:4px 6px;
  border-radius:5px;flex:none;}
.sp-num{width:56px;}
.sp-val{font-family:var(--mono);font-size:10px;color:var(--chrome-ink-3);width:38px;
  text-align:right;flex:none;}
.sp-btns{display:flex;gap:6px;padding-top:10px;margin-top:8px;
  border-top:1px solid var(--chrome-line);}
.sp-btns .toggle{flex:1;justify-content:center;}
.sp-warn{font-size:11px;color:var(--warning);padding:7px 0 2px;line-height:1.4;}
/* while styling: markdown cells and headings advertise that they are
   clickable targets, and each carries its own style button */
body.styling .card[data-note="1"],body.styling .sectionhead{cursor:pointer;}
body.styling .card[data-note="1"]:hover,
body.styling .sectionhead:hover{outline:2px dashed var(--cyan);
  outline-offset:3px;}
body.styling .card[data-note="1"].sty-sel,
body.styling .sectionhead.sty-sel{outline:2px solid var(--cyan);
  outline-offset:3px;}
.sty-btn{position:absolute;top:6px;left:8px;z-index:6;
  font-family:var(--sans);font-size:11px;letter-spacing:0;
  padding:3px 7px;border-radius:5px;
  border:1px solid var(--cyan);background:var(--paper);color:var(--cyan);
  cursor:pointer;opacity:0;transition:opacity .12s;}
.card[data-note="1"]:hover .sty-btn,.sty-btn:focus-visible{opacity:1;}
.sty-btn:hover{background:var(--cyan);color:var(--on-accent);}
/* a section's style button sits on its header line, before the eye */
.sectionhead .sty-btn{position:static;opacity:.7;margin-left:auto;}
.sectionhead:hover .sty-btn{opacity:1;}
/* a target that carries its OWN style says so — that is what the
   "Override individual styles" button is about */
.sty-own{border-color:var(--amber)!important;color:var(--amber)!important;}
.rf-panel{margin-top:8px;border:1px solid var(--chrome-line);
  border-radius:7px;padding:9px 10px;background:var(--surface-hover);}
.rf-panel[hidden]{display:none;}
/* T364: opened from the ribbon it hangs off <body>, like every other
   menu the bar drops -- the header is sticky, so a panel inside it
   paints behind the page */
.rf-panel.rf-float{position:fixed;z-index:200;width:300px;margin-top:0;
  background:var(--chrome-2);box-shadow:0 12px 40px var(--shadow);
  max-height:min(70vh,560px);overflow-y:auto;}
.rf-row{display:flex;flex-direction:column;gap:1px;margin-bottom:8px;
  min-width:0;}
.rf-row:last-child{margin-bottom:0;}
.rf-k{font-family:var(--mono);font-size:8.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--chrome-ink-2);}
/* one tidy line per fact: truncate, don't break a URL mid-word across
   three lines. The full value is on the element's title. */
.rf-v{font-family:var(--mono);font-size:10.5px;color:var(--chrome-ink);
  line-height:1.5;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;}
/* the commit message is prose — it may wrap, on word boundaries */
.rf-v.rf-sub{white-space:normal;overflow-wrap:anywhere;}
.rf-v.hash{color:var(--cyan);}
.rf-sub{color:var(--chrome-ink-2);font-size:9.5px;}
.rf-acts{display:flex;flex-wrap:wrap;gap:4px;margin-top:2px;}
.rf-live{color:var(--success);}
.rf-old{color:var(--amber);}
/* the commit hash IS a control, so it has to look like one */
.rf-hashbtn{background:color-mix(in srgb,var(--accent) 9%,transparent);border:1px solid color-mix(in srgb,var(--accent) 35%,transparent);
  padding:4px 9px;cursor:pointer;border-radius:5px;
  text-align:left;font-family:var(--mono);font-size:10.5px;
  color:var(--cyan);display:inline-flex;align-items:center;gap:7px;
  align-self:flex-start;max-width:100%;}
.rf-hashbtn:hover{background:color-mix(in srgb,var(--accent) 18%,transparent);border-color:var(--cyan);
  color:var(--chrome-ink);}
.rf-caret{font-size:8px;transition:transform .13s;opacity:.85;}
.rf-hashbtn.open .rf-caret{transform:rotate(180deg);}
.rf-commits{margin-top:7px;max-height:240px;overflow-y:auto;
  border-top:1px solid var(--chrome-line);padding-top:6px;}
/* T663: INFO READS AS A LIST OF FACTS (owner, 2026-10-28: "the
   information in info is hard to distinguish between the subheadings
   and text"). Label and value were both monospace, the label only
   smaller, greyer and in capitals. Now the file's name heads the panel
   with Reload beside it, and each fact is a row of two columns: its
   name quiet on the left in the interface's own type, its value on the
   right, brighter and larger -- a path in monospace, as code is. */
.rf-top{display:flex;align-items:center;gap:8px;margin-bottom:10px;
  padding-bottom:9px;border-bottom:1px solid var(--chrome-line);}
.rf-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font:600 13.5px var(--sans);color:var(--chrome-ink);}
.rf-top .rf-reload{flex:none;font:500 12px var(--sans);letter-spacing:0;
  padding:5px 9px;}
.rf-panel .rf-row{display:grid;grid-template-columns:68px minmax(0,1fr);
  column-gap:10px;row-gap:4px;align-items:baseline;margin-bottom:9px;}
.rf-panel .rf-row>:not(.rf-k){grid-column:2;}
.rf-panel .rf-row>.rf-commits{grid-column:1/-1;}
.rf-panel .rf-row>.rf-hashbtn{justify-self:start;}
.rf-panel .rf-k{font:500 11.5px var(--sans);letter-spacing:0;
  text-transform:none;color:var(--chrome-ink-2);}
.rf-panel .rf-k::first-letter{text-transform:uppercase;}
.rf-panel .rf-v{font:12.5px/1.45 var(--sans);color:var(--chrome-ink);}
.rf-panel .rf-v.rf-sub{font:11px/1.45 var(--mono);
  color:color-mix(in srgb,var(--chrome-ink) 80%,transparent);}
.rf-panel .rf-v.rf-old{color:var(--amber);}
.rf-panel .rf-row>.rf-hashbtn{font-size:11.5px;}
.rf-commits[hidden]{display:none;}
.rf-crow{display:flex;align-items:stretch;gap:3px;}
.rf-commit{display:grid;grid-template-columns:auto 1fr;gap:2px 8px;
  flex:1;min-width:0;text-align:left;background:none;
  border:1px solid transparent;
  border-radius:5px;padding:5px 6px;cursor:pointer;color:inherit;}
.rf-commit:hover{background:var(--surface-hover);
  border-color:var(--chrome-line);}
/* the same version, but side by side instead of in place */
.rf-newtab{flex:none;width:26px;background:none;cursor:pointer;
  border:1px solid transparent;border-radius:5px;
  color:var(--chrome-ink-2);font-size:12px;line-height:1;}
.rf-newtab:hover{background:var(--surface-hover);border-color:var(--chrome-line);
  color:var(--chrome-ink);}
.rf-ch{font-family:var(--mono);font-size:10px;color:var(--cyan);}
.rf-cm{font-family:var(--sans);font-size:11px;color:var(--chrome-ink);
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.rf-cd{grid-column:2;font-family:var(--mono);font-size:9px;
  color:var(--chrome-ink-2);}

/* ---------- nav ---------- */
.nav{padding:14px 12px 8px;flex:1 0 auto;}
.navsec{display:flex;justify-content:space-between;align-items:center;
  gap:8px;padding:9px 10px;margin-top:6px;border-radius:var(--rad);
  text-decoration:none;color:var(--chrome-ink);font-weight:600;font-size:13.5px;
  letter-spacing:-.005em;transition:background .15s,color .15s;}
.navsec:hover{background:var(--surface-hover);}
.navsec.active{background:var(--selection);color:var(--chrome-ink);}
/* a section row = a collapse chevron + the (clickable) section link */
.navsec-row{display:flex;align-items:center;gap:1px;margin-top:6px;}
.navsec-row .navsec{flex:1;margin-top:0;min-width:0;}
.navsec-chev{background:none;border:none;color:var(--chrome-ink-2);
  cursor:pointer;font-size:10px;line-height:1;padding:6px 3px;flex:none;
  border-radius:4px;transition:transform .15s,color .15s;}
.navsec-chev:hover{color:var(--chrome-ink);}
.navsec-row.collapsed .navsec-chev{transform:rotate(-90deg);}
.navitems.nav-collapsed{display:none;}
/* the three heading tiers nest progressively (indent + shrinking type) */
.navsec-l1 .navsec{font-size:14px;}
.navsec-l2{margin-left:12px;}
.navsec-l2 .navsec{font-size:12.5px;font-weight:500;}
.navsec-l3{margin-left:24px;}
.navsec-l3 .navsec{font-size:11.5px;font-weight:500;
  color:var(--chrome-ink-2);padding:6px 10px;}
/* Long notebooks: let the browser skip layout+paint for cards that are
   off-screen. Measured on a 260-card document this is where the time
   goes — not our JS, which runs in ~1ms. `auto` remembers each card's
   last real size, so the scrollbar stays honest. */
.content .card{content-visibility:auto;contain-intrinsic-size:auto 300px;}
/* …but never for a card that has been CLONED somewhere it must render in
   full: slide frames, tree nodes, trace steps, the raw view, printing */
.an-cell .card,.spane .card,.slide-fig .card,.tree-node .card,
.vo-step .card,.print-page .card,.rawview .card,.figmax .card{
  content-visibility:visible;contain-intrinsic-size:none;}
@media print{.content .card{content-visibility:visible!important;
  contain-intrinsic-size:none!important;}}
/* fully hidden (filtered out) cards + their sidebar entries disappear --
   and stay gone while you Peek: a peek shows what YOU hid, never what a
   filter did (2026-10-01, user: "the filter should still apply") */
.card.is-hidden,.section.is-hidden{display:none;}
.navitem.nav-hidden,.navsec-row.nav-hidden,.navitems.nav-hidden{
  display:none;}
.navsec-t{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.navsec-c{font-family:var(--mono);font-size:10px;color:var(--cyan);
  background:color-mix(in srgb,var(--accent) 9%,transparent);border-radius:20px;padding:1px 7px;min-width:18px;
  text-align:center;}
.navsec-c:empty{display:none;}
.navitems{margin:2px 0 4px 4px;padding-left:8px;
  border-left:1px solid var(--chrome-line);}
/* cell lists indent with their section's tier */
.navitems-l2{margin-left:16px;}
.navitems-l3{margin-left:28px;}
.navsub{font-family:var(--sans);font-size:11px;font-weight:600;
  letter-spacing:0;color:var(--chrome-ink-2);
  padding:9px 10px 3px;}
.navitem{display:flex;align-items:center;gap:9px;padding:5px 10px;
  border-radius:5px;text-decoration:none;color:var(--chrome-ink-2);
  font-size:12.5px;transition:color .15s,background .15s;}
.navitem:hover{color:var(--chrome-ink);background:var(--surface-hover);}
.navitem.active{color:var(--chrome-ink);}
.navitem-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;}
/* per-cell eye in the sidebar: click to hide/show a single cell. A cell
   hidden this way STAYS in the sidebar (dimmed, slashed eye) to restore. */
.navitem-eye{flex:none;font-size:11px;line-height:1;padding:1px 4px;
  border-radius:4px;position:relative;opacity:0;color:inherit;
  transition:opacity .12s,background .12s;}
.navitem:hover .navitem-eye,.navitem-eye:focus{opacity:.6;}
.navitem-eye:hover{opacity:1;background:var(--surface-active);}
.navitem.cell-off{opacity:.5;}
.navitem.cell-off .navitem-eye{opacity:.9;}
.navitem.cell-keep-visible .navitem-eye{opacity:.9;}
.card.cell-keep-visible .cell-eye,
.navitem.cell-keep-visible .navitem-eye{opacity:1;color:var(--cyan);}
/* ONE slash for every crossed-out eye: the item eye, the section-heading
   eyes, and the hide-all control (deck.css draws its own, larger one) */
.navitem.cell-off .navitem-eye::after,
.nbshell.reveal-hidden .card.cell-off .cell-eye::after,
.section.sec-headoff .sec-eye::after,
.navsec-row.head-off .navsec-eye::after,
.navsec-row.sec-off .navsec-hideall::after{content:"";position:absolute;
  left:3px;right:3px;top:calc(50% - 1px);height:1.5px;background:currentColor;
  transform:rotate(-18deg);border-radius:2px;}
.navitem .dot{width:9px;height:9px;border-radius:3px;flex:none;
  background:var(--chrome-ink-2);}
.navitem.k-figure .dot,.nk.k-figure .dot{background:var(--cyan);}
.navitem.k-dataset .dot,.nk.k-dataset .dot{background:var(--ck-data);}
.navitem.k-transform .dot,.nk.k-transform .dot{background:var(--ck-settings);}
.navitem.k-metric .dot,.nk.k-metric .dot{background:var(--ck-function);}
.navitem.k-note .dot,.nk.k-note .dot{background:var(--ck-print);
  border-radius:50%;}
.navitem.k-code .dot,.nk.k-code .dot{background:#56627033;
  border:1px solid #ffffff22;}
.navitem.ckmain-imports .dot,.nk.ckmain-imports .dot{background:var(--ck-imports);}
.navitem.ckmain-function .dot,.nk.ckmain-function .dot{background:var(--ck-function);}
.navitem.ckmain-data .dot,.nk.ckmain-data .dot{background:var(--ck-data);}
.navitem.ckmain-constant .dot,.nk.ckmain-constant .dot{background:var(--ck-constant);}
.navitem.ckmain-settings .dot,.nk.ckmain-settings .dot{background:var(--ck-settings);}
.navitem.ckmain-plotting .dot,.nk.ckmain-plotting .dot{background:var(--accent);}
.navitem.ckmain-print .dot,.nk.ckmain-print .dot{background:var(--ck-print);}
.navitem.ckmain-comments .dot,.nk.ckmain-comments .dot{background:#5f7386;}
/* light theme needs its own — a generic body.light .dot outranks these
   (same values as above: these rules exist for SPECIFICITY, not colour) */
body.light .navitem.ckmain-imports .dot,body.light .nk.ckmain-imports .dot{
  background:var(--ck-imports);}
body.light .navitem.ckmain-function .dot,body.light .nk.ckmain-function .dot{
  background:var(--ck-function);}
body.light .navitem.ckmain-data .dot,body.light .nk.ckmain-data .dot{
  background:var(--ck-data);}
body.light .navitem.ckmain-constant .dot,body.light .nk.ckmain-constant .dot{
  background:var(--ck-constant);}
body.light .navitem.ckmain-settings .dot,body.light .nk.ckmain-settings .dot{
  background:var(--ck-settings);}
body.light .navitem.ckmain-plotting .dot,body.light .nk.ckmain-plotting .dot{
  background:var(--accent);}
body.light .navitem.ckmain-comments .dot,body.light .nk.ckmain-comments .dot{background:#5f7386;}
body.light .navitem.ckmain-print .dot,body.light .nk.ckmain-print .dot{
  background:var(--ck-print);}

/* ---------- nav key (what the dot colours mean) ---------- */
.navkey{display:flex;flex-wrap:wrap;gap:4px 12px;align-items:center;
  padding:10px 12px 12px;margin:8px 10px 0;
  border-top:1px solid var(--chrome-line);}
.navkey-h{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--chrome-ink-2);flex:0 0 100%;}
.nk{display:inline-flex;align-items:center;gap:6px;font-size:11px;
  font-family:var(--mono);color:var(--chrome-ink-2);}
.nk .dot{width:6px;height:6px;border-radius:2px;flex:none;
  background:var(--chrome-ink-2);}
/* a thin rule marking the markdown | plots | code | output groups */
.navkey-div{width:1px;height:11px;flex:none;align-self:center;
  background:var(--chrome-line);margin:0 -3px;}

/* ---------- rail tabs: Sections | Variables ---------- */
.railtabs{display:flex;gap:3px;margin:10px 12px 0;padding:3px;
  border:1px solid var(--chrome-line);border-radius:8px;}
.railtab{flex:1;background:none;border:none;border-radius:6px;
  font-family:var(--mono);font-size:10px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--chrome-ink-2);padding:5px 0;
  cursor:pointer;transition:background .15s,color .15s;}
.railtab:hover{color:var(--chrome-ink);}
.railtab.active{background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--cyan);}

/* ---------- variables panel (the sidebar's other view) ---------- */
.varpanel{padding:12px 12px 8px;flex:1 0 auto;}
.var-controls{display:flex;gap:6px;margin-bottom:8px;}
.var-filter{flex:1;min-width:0;background:var(--input-bg);
  border:1px solid var(--chrome-line);border-radius:6px;
  color:var(--chrome-ink);font-family:var(--mono);font-size:11px;
  padding:4px 8px;}
.var-filter::placeholder{color:var(--chrome-ink-2);}
.var-order{display:flex;gap:2px;border:1px solid var(--chrome-line);
  border-radius:6px;padding:2px;flex:none;}
.varord-btn{background:none;border:none;border-radius:4px;cursor:pointer;
  font-family:var(--sans);font-size:11px;letter-spacing:0;
  color:var(--chrome-ink-2);padding:2px 7px;}
.varord-btn::first-letter{text-transform:uppercase;}
.varord-btn:hover{color:var(--chrome-ink);}
.varord-btn.active{background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--cyan);}
/* group headings the by-type view inserts (same voice as .navsub) */
.vargroup-h{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--chrome-ink-2);padding:10px 8px 3px;}
.var-line{display:flex;align-items:center;gap:6px;padding:3px 6px 3px 0;
  border-radius:5px;}
.var-line:hover{background:var(--surface-hover);}
.var-chev{background:none;border:none;color:var(--chrome-ink-2);
  cursor:pointer;font-size:12px;line-height:1;padding:2px 5px;flex:none;
  border-radius:4px;transition:transform .15s,color .15s;}
.var-chev:hover{color:var(--chrome-ink);}
.varrow.open .var-chev{transform:rotate(90deg);}
.var-name{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;font-family:var(--mono);font-size:12px;
  color:var(--chrome-ink);text-decoration:none;}
.var-name:hover{color:var(--chrome-ink);text-decoration:underline;}
.var-type{flex:none;font-family:var(--mono);font-size:9.5px;
  color:var(--chrome-ink-2);background:var(--surface-hover);border-radius:4px;
  padding:1px 5px;max-width:92px;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;}
.var-count{font-family:var(--mono);font-size:10px;color:var(--cyan);
  background:color-mix(in srgb,var(--accent) 9%,transparent);border-radius:20px;padding:1px 7px;min-width:18px;
  text-align:center;flex:none;}
.var-count:empty{display:none;}
/* the unfolded sites list: defined / redefined / used, one card each */
.var-uses{margin:0 0 4px 16px;padding-left:8px;
  border-left:1px solid var(--chrome-line);}
.var-use{display:flex;align-items:center;gap:7px;padding:3px 8px;
  border-radius:5px;text-decoration:none;color:var(--chrome-ink-2);
  font-size:11.5px;}
.var-use:hover{color:var(--chrome-ink);background:var(--surface-hover);}
.vu-tag{flex:none;font-family:var(--mono);font-size:8.5px;
  letter-spacing:.08em;text-transform:uppercase;border-radius:4px;
  padding:1px 5px;color:var(--chrome-ink-2);background:var(--surface-hover);}
.vu-tag.vu-defined{color:var(--cyan);background:color-mix(in srgb,var(--accent) 9%,transparent);}
.vu-tag.vu-redefined{color:var(--amber);
  background:color-mix(in srgb,var(--amber) 10%,transparent);}
.vu-t{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;}
/* rows the filter box rules out (and group headings left empty by it) */
.varrow.vf-out,.vargroup-h.vf-out{display:none;}
.var-empty{font-size:11.5px;color:var(--chrome-ink-2);padding:8px 4px;}
/* the type chip borrows the code-kind dot colours where kinds align */
.var-type.vg-imports{color:var(--ck-imports);}
.var-type.vg-constants{color:var(--ck-constant);}
.var-type.vg-functions{color:var(--ck-function);}
.var-type.vg-classes{color:#b07cc0;}
.var-type.vg-data{color:var(--ck-data);}
.var-type.vg-plotting{color:var(--accent);}
/* ---------- rail graph (signature) ---------- */
.railgraph{border-top:1px solid var(--chrome-line);padding:14px 14px 20px;
  margin-top:auto;background:var(--chrome-1);}
.railgraph-h{display:flex;justify-content:space-between;align-items:center;
  margin-bottom:8px;}
.railgraph .eyebrow{color:var(--amber);}
.rg-collapse{background:none;border:1px solid var(--chrome-line);
  color:var(--chrome-ink-2);width:22px;height:22px;border-radius:5px;
  cursor:pointer;font-size:14px;line-height:1;}
.rg-collapse:hover{color:var(--chrome-ink);border-color:var(--border-strong);}
.railgraph-b{overflow:auto;max-height:46vh;transition:max-height .3s ease;}
.railgraph.collapsed .railgraph-b{max-height:0;overflow:hidden;}
.provsvg text{font-family:var(--mono);font-size:9.5px;fill:var(--chrome-ink);
  pointer-events:none;}
/* the lit edge's colour fades; its width does not (2026-10-09, speed:
   reader #13) -- a stroke-width in transition re-laid out the outline's
   SVG paths every frame of a scroll with the outline open */
.provedge{fill:none;stroke:var(--amber-soft);stroke-width:1.4;
  transition:stroke .2s;}
.provedge.lit{stroke:var(--amber);stroke-width:2.2;}
.provnode{cursor:pointer;}
.provnode rect{transition:filter .2s,stroke .2s;stroke:transparent;stroke-width:2;}
.provnode:hover rect{filter:brightness(1.18);}
.provnode.active rect{stroke:var(--cyan);filter:brightness(1.12)
  drop-shadow(0 0 6px color-mix(in srgb,var(--accent) 47%,transparent));}
.provnode:focus-visible rect{stroke:var(--cyan);outline:none;}

/* ---------- toolbar ---------- */
.toolbar{position:sticky;top:0;z-index:20;display:flex;align-items:center;
  gap:12px;padding:12px 28px;
  background:color-mix(in srgb,var(--paper) 95%,transparent);
  backdrop-filter:blur(8px);border-bottom:1px solid var(--line);}
.menubtn{display:none;}
.tb-title{font-family:var(--mono);font-size:11px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--ink-3);margin-right:auto;
  overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}
.tb-actions{display:flex;gap:8px;flex:none;}
/* T679: a button is in the sans, as the ribbons and dialogs already were.
   The mono was the July bar's; it outlived it only here, so one screen
   set Save, Thumbnails and Add slide in 11px monospace beside 12px sans
   ribbon words. The mono stays for what is code: names, values, keys. */
.toggle{font-family:var(--sans);font-size:12px;letter-spacing:0;
  border:1px solid var(--btn-border);background:var(--btn-bg);
  color:var(--btn-ink);
  padding:7px 12px;border-radius:var(--rad);cursor:pointer;
  transition:color .15s,background-color .15s,border-color .15s,
    box-shadow .15s,opacity .15s;
  display:inline-flex;align-items:center;gap:7px;}
/* an author `display` beats the UA's [hidden] rule, so say it explicitly —
   without this, every el.hidden=true on a .toggle silently does nothing */
.toggle[hidden],.dbtn[hidden],.fgrp[hidden],.fgrp-row[hidden]{
  display:none!important;}
.toggle:hover{border-color:var(--accent);color:var(--ink);}
.toggle[aria-pressed="true"]{background:var(--accent-deep);
  color:var(--on-accent-deep);border-color:var(--accent-deep);}
/* the state colour rides on the button's own ICON now — a separate dot
   said the same thing twice and cost the bar ~56px it did not have */
.toggle.tv .tdot{display:none;}
.toggle.tv .bic{color:var(--cyan);opacity:1;}
.toggle.tv.half .bic{color:var(--amber);}
.toggle.tv.off .bic{opacity:.4;}
.toggle.tv.mixed .bic{color:var(--amber);opacity:.8;}
.toggle .tdot{width:6px;height:6px;border-radius:50%;background:currentColor;
  opacity:.4;}
/* every state word occupies the same slot, so the bar never re-flows
   just because a filter changed (On / Folded / Off / Mixed) */
.tvstate{display:inline-block;width:4.4ch;text-align:left;
  margin-left:.4em;overflow:hidden;}
/* T566: the state word wears its icon's colour, so "Plots On" reads as
   a setting and its value rather than as one two-word name */
.toggle.tv .tvstate{color:var(--cyan);}
.toggle.tv.half .tvstate,.toggle.tv.mixed .tvstate{color:var(--amber);}
.toggle.tv.off .tvstate{color:inherit;}
.toggle[aria-pressed="true"] .tdot{opacity:1;background:var(--cyan);}
/* view-mode buttons (Docs / Present): pressed = the view you are in */
.toggle.mode[aria-pressed="true"]{background:var(--accent-deep);
  color:var(--on-accent-deep);border-color:var(--accent-deep);}
.tb-sep{width:1px;height:22px;background:var(--line);margin:0 4px;
  flex:none;}
/* per-type state buttons: label shows the CURRENT state. Code cycles
   Visible (cyan dot) -> Collapsed (amber, half) -> Hidden (dim). */
.toggle.tv .tdot{opacity:1;background:var(--cyan);}
.toggle.tv.half .tdot{background:var(--amber);}
.toggle.tv.off .tdot{opacity:.3;background:currentColor;}
.toggle.tv.off{color:var(--ink-3);}
/* the selected sections disagree about this filter */
.toggle.tv.mixed .tdot{background:linear-gradient(90deg,
  var(--cyan) 50%,var(--ink-3) 50%);opacity:1;}
/* "Apply to" is set to no sections at all — nothing to filter */
.toggle.notarget{opacity:.4;cursor:not-allowed;}
/* a section filtered differently from the notebook default says so */
.section.has-fover .sectionhead .eyebrow::after{content:" · filtered";
  color:var(--amber);letter-spacing:.12em;}

/* ---------- content ---------- */
.content{max-width:920px;margin:0 auto;padding:30px 28px 30vh;}
.section{margin-bottom:14px;scroll-margin-top:70px;}
/* headings read the --hd-* vars for the same reason the notes read
   --md-*: a custom view can restyle every heading, one section's
   heading, or leave them alone (the fallbacks are the stock design) */
.sectionhead{padding:24px 0 6px;margin-bottom:8px;
  border-bottom:var(--hd-bw,1px) solid var(--hd-bd,var(--line));
  background:var(--hd-bg,transparent);
  display:flex;align-items:center;gap:8px;}
.sectionhead-txt{flex:1;min-width:0;cursor:pointer;}
.sectionhead-txt:focus-visible{outline:2px solid var(--accent);
  outline-offset:3px;border-radius:3px;}
.eyebrow{font-family:var(--mono);font-size:10px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--hd-accent,var(--cyan-deep));
  display:var(--hd-eyebrow,block);margin-bottom:6px;}
.sectionhead h2{font-size:calc(26px * var(--hd-size,1));
  font-weight:var(--hd-wt,600);margin:0;letter-spacing:-.02em;
  color:var(--hd-col,var(--ink));text-transform:var(--hd-caps,none);
  font-family:var(--hd-font,inherit);}
/* three heading tiers (# / ## / ###): descending size + indent, and the
   deepest drops the underline so the levels read apart at a glance.
   (These must FOLLOW the base .sectionhead h2 rule — same specificity.) */
.sectionhead-l2 h2{font-size:calc(21px * var(--hd-size,1));}
.sectionhead-l2{padding-top:16px;}
.sectionhead-l3 h2{font-size:calc(17px * var(--hd-size,1));}
.sectionhead-l3{padding-top:10px;border-bottom:none;padding-bottom:2px;}
.sectionhead-l3 .eyebrow{font-size:9px;margin-bottom:3px;}
.section.sec-l2 .sectionhead{margin-left:14px;}
.section.sec-l3 .sectionhead{margin-left:28px;}
/* main-view section controls: a collapse chevron (left) + a hide eye (right,
   on hover) — the sidebar has the same two, kept in sync */
.sec-chev{flex:none;display:inline-flex;align-items:center;gap:4px;
  background:none;border:none;color:var(--ink-3);cursor:pointer;
  font:500 11px var(--sans);letter-spacing:0;
  line-height:1;padding:5px 6px;border-radius:4px;
  transition:transform .15s,color .15s,background .15s;}
.sec-chev:hover{color:var(--ink);}
.sec-chev:hover,.sec-chev:focus-visible{background:var(--paper-2);}
.section.sec-collapsed .sec-chev{transform:none;}
.sec-chev-ic{display:inline-block;transition:transform .15s;}
.section.sec-collapsed .sec-chev-ic{transform:rotate(-90deg);}
.sec-eye{flex:none;background:none;border:none;color:var(--ink-3);
  cursor:pointer;font-size:14px;line-height:1;padding:3px 6px;
  border-radius:5px;opacity:0;transition:opacity .12s,background .12s;}
.sectionhead:hover .sec-eye,.sec-eye:focus-visible{opacity:.5;}
.sec-eye:hover{opacity:1;background:var(--paper-2);}
/* the eye hides the HEADING only; this names the bigger action in words —
   a glyph could not say "and everything in it" (2026-07-29) */
.sec-hideall{flex:none;background:none;border:1px solid transparent;
  color:var(--ink-3);cursor:pointer;font-family:var(--sans);font-size:11px;
  letter-spacing:0;line-height:1;padding:5px 8px;
  border-radius:5px;opacity:0;white-space:nowrap;
  transition:opacity .12s,background .12s,border-color .12s;}
.sectionhead:hover .sec-hideall,.sec-hideall:focus-visible{opacity:.65;}
.sec-hideall:hover{opacity:1;background:var(--paper-2);
  border-color:var(--line);color:var(--ink-2);}
/* collapsed folds the section's cards away; the header stays clickable */
.section.sec-collapsed .card{display:none;}
.section.sec-collapsed .sectionhead{margin-bottom:0;}
/* HEADING hidden: the title and its eyebrow go, the cards stay. The head
   itself survives as a thin hover strip so the controls that brought it
   here can bring it back in place (no round trip to the sidebar). */
.section.sec-headoff .sectionhead-txt{display:none;}
/* a hidden heading leaves NO trace in the feed — the faint stub that used
   to remain read as a rendering artefact. It lives in the sidebar only,
   which is where you bring it back from (2026-07-30). */
.section.sec-headoff .sectionhead{display:none;}
/* ...unless the sidebar's "Peek at hidden" is revealing them. That is a
   PEEK, not a reset: everything stays hidden underneath, marked amber so
   you can tell what you are looking at, and one more click puts it all
   away again. Each item's own eye still works while revealed, which is
   how you keep just the one you wanted back.
   IT REVEALS WHAT YOU HID BY HAND -- a cell's eye, a section's, a
   heading's, a folded section -- and NOTHING A FILTER HID. With Code
   off, a peek showed every code block in the notebook, because a blanket
   `display:revert!important` on every section, card and part undid the
   filters along with the eyes (2026-10-01, user: "with the 'peek at
   hidden', the filter should still apply"). A card a filter removed is
   .filt-gone (applyFilters), a section that is only empty because of
   the filters stays .is-hidden, and the parts (code, plots, output)
   keep their filter classes untouched. */
.nbshell.reveal-hidden .section.sec-headoff .sectionhead{display:flex;}
.nbshell.reveal-hidden .section.sec-headoff .sectionhead-txt{display:block;}
.nbshell.reveal-hidden .section.sec-under:not(.is-hidden),
.nbshell.reveal-hidden .section.sec-collapsed .card:not(.is-hidden){
  display:block;}
.nbshell.reveal-hidden .section.sec-off,
.nbshell.reveal-hidden .section.sec-under-off:not(.is-hidden),
.nbshell.reveal-hidden .section.sec-peek,
.nbshell.reveal-hidden .content .card.cell-off:not(.filt-gone){
  display:block;}
.nbshell.reveal-hidden .content .section.pg-out{display:none;}
.nbshell.reveal-hidden .section.sec-off,
.nbshell.reveal-hidden .section.sec-under-off,
.nbshell.reveal-hidden .content .card.cell-off:not(.filt-gone),
.nbshell.reveal-hidden .section.sec-headoff .sectionhead{
  outline:1px dashed var(--amber);outline-offset:4px;opacity:.62;}
.nbshell.reveal-hidden .section.sec-off:hover,
.nbshell.reveal-hidden .content .card.cell-off:not(.filt-gone):hover,
.nbshell.reveal-hidden .section.sec-headoff .sectionhead:hover{opacity:1;}
.nbshell.reveal-hidden .card.cell-off .cell-eye,
.nbshell.reveal-hidden .section.sec-off .sec-hideall{
  opacity:1;position:relative;color:var(--amber);}
.rf-unhide[aria-pressed="true"]{border-color:var(--amber);
  color:var(--amber);}
.section.sec-headoff .sec-eye{opacity:.5;position:relative;}
/* the struck-through eye = "hidden, click to bring it back" mark is the
   shared slash rule beside .navitem-eye above */
.navsec-row.head-off .navsec-t{opacity:.55;text-decoration:line-through;
  text-decoration-thickness:1px;}
.navsec-row.head-off .navsec-eye{opacity:.9;position:relative;}
/* hidden drops the whole section from the document (restore from the sidebar) */
.section.sec-off{display:none;}
.navsec-row.sec-off{opacity:.5;}
/* the tiers are a real hierarchy: collapsing / hiding an ancestor section
   folds every deeper section that follows it (recalcSecCascade sets these) */
.section.sec-under,.section.sec-under-off{display:none;}
.navsec-row.nav-under,.navitems.nav-under{display:none;}
.navsec-row.sec-under-off{opacity:.5;}
/* a hidden section keeps only its (dimmed) header row — fold its cell links
   away too, else they stay bright but point at a display:none target */
.navsec-row.sec-off+.navitems{display:none;}
.navsec-eye,.navsec-hideall{flex:none;font-size:11px;line-height:1;
  padding:1px 4px;border-radius:4px;position:relative;opacity:0;
  color:inherit;cursor:pointer;transition:opacity .12s,background .12s;}
.navsec-hideall{font-size:13px;}
.navsec-row:hover .navsec-eye,.navsec-eye:focus,
.navsec-row:hover .navsec-hideall,.navsec-hideall:focus{opacity:.6;}
.navsec-eye:hover,.navsec-hideall:hover{opacity:1;background:#ffffff14;}
.navsec-row.sec-off .navsec-hideall{opacity:.9;}
/* the strike belongs on whichever control did the hiding: ≡ for the whole
   section, the eye for the heading alone — drawn by the shared slash rule */

/* ---------- cards ---------- */
.card{background:var(--paper);border:1px solid var(--line);
  border-radius:10px;padding:18px 18px 16px;
  /* --vw-gap: a custom view sets the rhythm of the whole feed */
  margin:var(--vw-gap,14px) 0;
  scroll-margin-top:78px;position:relative;
  box-shadow:0 1px 2px color-mix(in srgb,var(--shadow) 16%,transparent);
  /* VISIBLE FROM THE FIRST PAINT. Cards used to start at opacity:0 and
     fade in when a scroll observer marked them, which could only happen
     once every script on the page had run: the headings painted and the
     cards stayed blank for seconds behind them (3.5 s on a four-notebook
     project at 4x), and every card scrolled into view for the first time
     paid an animation (2026-10-09, speed: load-app #1, reader #5).
     NO HOVER FADE EITHER (reader #2): the shadow below came in over
     0.2 s, and while the page scrolls under a still pointer every card
     that passes beneath it starts that fade -- a box-shadow, which the
     main thread restyles and repaints over the whole card each frame:
     25-40% of the cost of scrolling. It snaps on now. */}
.card:hover{box-shadow:0 6px 22px color-mix(in srgb,var(--shadow) 34%,transparent);}
.card::before{content:"";position:absolute;left:0;top:16px;bottom:16px;
  width:3px;border-radius:3px;background:var(--line);
  transition:background .2s;}
.card.k-figure::before{background:var(--cyan);}
.card.k-dataset::before{background:var(--ck-data);}
.card.k-transform::before{background:var(--ck-settings);}
.card.k-metric::before{background:var(--ck-function);}
.card.k-note::before{background:var(--ck-print);}
.card.k-code::before{background:var(--paper-3);}
.card.target-flash{border-color:var(--cyan);box-shadow:0 0 0 3px color-mix(in srgb,var(--accent) 20%,transparent);}

/* a markdown note the Markdown filter has COLLAPSED: only the header shows;
   click the header to expand in place, click again to fold. The :not(.expanded)
   guard means expanding simply reverts to the note's normal rules (so a
   "Show raw HTML" note behaves correctly). */
.card.collapsed{padding:9px 16px;}
.card.collapsed:not(.expanded)>.cardbody,
.card.collapsed:not(.expanded)>.caption,
.card.collapsed:not(.expanded)>.prov,
.card.collapsed:not(.expanded)>.note-src,
.card.collapsed:not(.expanded)>.htmltoggle{display:none;}
.card.collapsed>.cardhead{margin-bottom:0;cursor:pointer;}
.card.collapsed .cardtitle::before{content:"\25b8";margin-right:7px;
  color:var(--ink-3);display:inline-block;font-size:.85em;
  transition:transform .2s;}
.card.collapsed.expanded .cardtitle::before{transform:rotate(90deg);}
.card.collapsed>.cardhead:hover .cardtitle{color:var(--ink);}
.card.collapsed.expanded{padding:18px 18px 16px;}
.card.collapsed.expanded>.cardhead{margin-bottom:12px;}

/* ---- cell output parts: figure + printed output, filtered independently ---- */
.cb-part{display:block;}
.cb-fig.part-off,.cb-out.part-off{display:none;}
/* Plots = Collapsed folds a figure to a slim "show plot" bar (click to open) */
.cb-fig.part-fold>*{display:none;}
.cb-fig.part-fold{cursor:pointer;border:1px dashed var(--line);border-radius:8px;
  padding:8px 12px;position:relative;min-height:0;}
.cb-fig.part-fold::before{content:"\25b8  Show plot";font-family:var(--mono);
  font-size:11px;color:var(--ink-3);letter-spacing:.02em;}
.cb-fig.part-fold:hover::before{color:var(--cyan-deep);}
.cb-fig.part-fold.part-open{cursor:default;border:none;padding:0;}
.cb-fig.part-fold.part-open>*{display:revert;}
.cb-fig.part-fold.part-open::before{display:none;}
/* Output = Collapsed folds the printed output the same way (click to reveal) */
.cb-out.part-fold>*{display:none;}
.cb-out.part-fold{cursor:pointer;border:1px dashed var(--line);border-radius:8px;
  padding:8px 12px;margin-top:12px;position:relative;min-height:0;}
.cb-out.part-fold::before{content:"\25b8  Show output";font-family:var(--mono);
  font-size:11px;color:var(--ink-3);letter-spacing:.02em;}
.cb-out.part-fold:hover::before{color:var(--cyan-deep);}
.cb-out.part-fold.part-open{cursor:default;border:none;padding:0;}
/* :not(.ot-off):not(.ot-fold) so a child hidden or folded by the
   Output-types menu stays that way even when the collapsed output part is
   opened (the per-output states outrank the part-level fold) */
.cb-out.part-fold.part-open>*:not(.ot-off):not(.ot-fold){display:revert;}
/* one FRAME folded by its plot-type's own Fold (the Plot-types menu):
   the frame's content hides and the frame itself becomes the stub strip,
   exactly the part-fold pattern one level down. Click to open; the strip
   stays above the opened figure so it can be folded back. */
.cb-fig [data-pt].pt-fold{cursor:pointer;border:1px dashed var(--line);
  border-radius:8px;padding:8px 12px;min-height:0;}
.cb-fig [data-pt].pt-fold:not(.pt-open)>*{display:none;}
.cb-fig [data-pt].pt-fold::before{content:"\25b8  " attr(data-pt);
  display:block;font-family:var(--mono);font-size:11px;
  color:var(--ink-3);letter-spacing:.02em;}
.cb-fig [data-pt].pt-fold:hover::before{color:var(--cyan-deep);}
.cb-fig [data-pt].pt-fold.pt-open::before{
  content:"\25be  " attr(data-pt);margin-bottom:6px;}
.cb-out.part-fold.part-open::before{display:none;}

/* one line: badge, title (elided if long), then the actions pinned to the
   RIGHT. Without nowrap a long title pushed "Plot trace" onto its own row */
.cardhead{display:flex;align-items:center;gap:10px;margin-bottom:12px;
  padding-left:6px;flex-wrap:nowrap;min-width:0;}
/* The card's actions sit together at the top RIGHT in EVERY context a
   card renders — document, tree node, trace step, widget, export. These
   two lines used to live in the DECK stylesheet, so a card rendered
   without it lost the alignment and "Plot trace" dropped onto its own
   line under the title (2026-07-30). Layout of a card belongs with the
   card, not with whichever feature happened to add the button. */
.cardhead .plot-trace-btn{margin-left:auto;flex:none;white-space:nowrap;}
.cardhead .plot-trace-btn+.cell-eye{margin-left:0;}
.cardhead .badge,.cardhead .cell-eye{flex:none;}
/* per-cell eye on the card header: hide this one cell (restore via sidebar) */
/* ---- T242: THE PIN AND THE MARK -------------------------------------
   Two more head buttons, the same shape as the eye they sit beside:
   invisible until you look at the card, and STAYING visible once set,
   because a pin you cannot see is a filter you cannot explain. */
.cell-pin,.cell-mark{margin-left:0;flex:none;background:none;
  border:none;color:var(--ink-3);cursor:pointer;font-size:13px;
  line-height:1;padding:2px 6px;border-radius:5px;opacity:0;
  transition:opacity .15s,background .15s,color .15s;}
.cell-pin{margin-left:auto;}
.card:hover .cell-pin,.card:hover .cell-mark,
.cell-pin:focus-visible,.cell-mark:focus-visible{opacity:.55;}
.cell-pin:hover,.cell-mark:hover{opacity:1;background:var(--paper-2);}
.card.is-pinned .cell-pin{opacity:1;color:var(--cyan-deep);}
.cell-mark[aria-pressed="true"]{opacity:1;}
.mk-star .cell-mark{color:var(--amber,#c98a1e);}
.mk-heart .cell-mark{color:#d2555c;}
.mk-flag .cell-mark{color:#2f8f7d;}
/* a pinned card says so: the filters are set to hide it and it is
   here anyway, which is a fact the reader needs on the card */
.card.is-pinned{border-left:3px solid var(--cyan-deep);}
.cell-eye{flex:none;background:none;border:none;
  color:var(--ink-3);cursor:pointer;font-size:13px;line-height:1;
  padding:2px 6px;border-radius:5px;opacity:0;
  transition:opacity .15s,background .15s;}
.card:hover .cell-eye,.cell-eye:focus-visible{opacity:.55;}
.cell-eye:hover{opacity:1;background:var(--paper-2);}
/* The version comparison is a deliberate per-cell action, so keep its
   word visible and its place predictable even when other actions fade. */
.cell-history-btn{flex:none;display:inline-flex;align-items:center;gap:5px;
  margin-left:auto;padding:4px 7px;border:1px solid var(--line);
  border-radius:5px;background:none;color:var(--ink-3);cursor:pointer;
  font:600 10px var(--mono);white-space:nowrap;}
.cardhead .plot-trace-btn+.cell-history-btn{margin-left:0;}
.cardhead .cell-history-btn+.cell-pin{margin-left:0;}
/* T624: a local notebook's Versions waits for its repository (gitProbe) */
.cell-history-btn.local{display:none;}
.git-yes .cell-history-btn.local{display:inline-flex;}
.cell-history-btn:hover,.cell-history-btn:focus-visible{
  background:var(--paper-2);color:var(--ink);}
/* One comparison owns the screen; its timeline stays narrow while the
   current and chosen outputs each get room to breathe. */
dialog.cell-history{width:min(1120px,94vw);max-width:94vw;height:min(760px,86vh);
  max-height:86vh;box-sizing:border-box;padding:0;overflow:hidden;
  border:1px solid var(--line);border-radius:12px;background:var(--paper);
  color:var(--ink);box-shadow:0 18px 55px var(--shadow);}
dialog.cell-history::backdrop{background:#0009;}
/* shown with show(), not showModal() (app.js openCellHistory, reader #8):
   placed and stacked as the modal top layer placed it, over a backdrop
   of its own that takes the clicks outside it */
dialog.cell-history{position:fixed;inset:0;margin:auto;z-index:2001;}
.ch-backdrop{position:fixed;inset:0;z-index:2000;background:#0009;}
.ch-head{display:flex;align-items:center;justify-content:space-between;
  gap:16px;padding:17px 20px;border-bottom:1px solid var(--line);}
.ch-head span{font:600 10px var(--mono);letter-spacing:.13em;
  text-transform:uppercase;color:var(--ink-3);}
.ch-head h2{font-size:17px;margin:3px 0 0;line-height:1.25;}
.ch-close{border:1px solid var(--line);border-radius:6px;padding:7px 11px;
  background:var(--paper-2);color:var(--ink);cursor:pointer;}
.ch-main{display:grid;grid-template-columns:minmax(175px,225px) minmax(0,1fr);
  height:calc(100% - 73px);min-height:0;}
.ch-timeline{overflow:auto;padding:10px;border-right:1px solid var(--line);
  font-size:12px;color:var(--ink-3);}
.ch-commit{display:flex;flex-direction:column;gap:4px;width:100%;
  margin-bottom:4px;padding:9px;text-align:left;border:1px solid transparent;
  border-radius:6px;background:none;color:var(--ink-2);cursor:pointer;}
.ch-commit small{font:10px var(--mono);color:var(--ink-3);}
.ch-commit span{font-size:12px;line-height:1.35;}
.ch-commit:hover{background:var(--paper-2);}
.ch-commit[aria-current="true"]{border-color:var(--cyan);background:var(--paper-2);}
.ch-compare{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));
  min-width:0;min-height:0;overflow:auto;}
.ch-compare section{min-width:0;padding:16px;overflow:auto;}
.ch-compare section+section{border-left:1px solid var(--line);}
.ch-compare h3{font-size:12px;margin:0 0 12px;color:var(--ink-2);}
.ch-output{font-size:12px;line-height:1.5;overflow:auto;overflow-wrap:anywhere;}
.ch-output img,.ch-output svg{display:block;max-width:100%;height:auto;
  margin:0 0 12px;object-fit:contain;}
.ch-output pre{font:11px/1.45 var(--mono);white-space:pre-wrap;
  overflow-wrap:anywhere;margin:0;}
.ch-output .figzoom,.ch-output .fz-btn{display:none;}
.ch-source{font-size:11px;color:var(--ink-3);}
@media(max-width:700px){
  .ch-main{grid-template-columns:1fr;grid-template-rows:auto minmax(0,1fr);}
  .ch-timeline{display:flex;gap:6px;overflow-x:auto;overflow-y:hidden;
    border-right:0;border-bottom:1px solid var(--line);}
  .ch-commit{flex:none;width:170px;margin:0;}
  .ch-compare{grid-template-columns:1fr;}
  .ch-compare section+section{border-left:0;border-top:1px solid var(--line);}
}
/* Labels sit on the row the cell ALREADY has, rather than copying that
   cell into a list above the sections. Pin plus any reactions/categories
   show together: they are different facts about the cell. */
.navitem-mk{flex:none;display:flex;align-items:center;gap:3px;
  line-height:0;}
.navitem-mk .mk-i{display:flex;line-height:0;}
.navitem-mk .bic{width:11px;height:11px;}
.mk-i-pin{color:var(--cyan);}
.mk-i-star{color:var(--amber,#f0a848);}
.mk-i-heart{color:#e0757c;}
.mk-i-flag{color:#5fc4ac;}
.mk-i-smile{color:#8fbc68;}
.mk-i-main{color:var(--amber,#f0a848);}
.mk-i-cat{font:600 8px/1 var(--mono);letter-spacing:-.03em;
  color:#8fb7c8;border:1px solid #8fb7c866;border-radius:3px;padding:1px 2px;}
/* code fully hidden: the code tucked under figures disappears too */
.codewrap.code-off{display:none;}
.badge{font-family:var(--mono);font-size:9.5px;letter-spacing:.14em;
  text-transform:uppercase;padding:3px 8px;border-radius:4px;
  background:var(--paper-2);color:var(--ink-3);flex:none;}
.k-figure .badge{background:color-mix(in srgb,var(--accent) 8%,transparent);color:var(--cyan-deep);}
.k-dataset .badge{background:#4d90c014;
  color:color-mix(in srgb,#2f6f9e 60%,var(--ink));}
.k-transform .badge{background:#5b758914;color:#41566a;}
.k-metric .badge{background:#46a89214;
  color:color-mix(in srgb,#2c8c7d 60%,var(--ink));}
.k-note .badge{background:#cf9a4e1f;
  color:color-mix(in srgb,#8a6326 60%,var(--ink));}
/* printed-output cells read "print" (a steel tone, distinct from md notes) */
.k-print .badge{background:#5f7d8c1f;color:#3f5c6a;}
.navitem.k-print .dot,.nk.k-print .dot{background:#5f7d8c;}
.card.k-print::before{background:#5f7d8c;}
/* code subtypes (base rules read on the light paper theme) */
.ckmain-imports .badge{background:#8a6d4a1a;
  color:color-mix(in srgb,#7a5e38 60%,var(--ink));}
.ckmain-function .badge{background:#46a89218;
  color:color-mix(in srgb,#2c8c7d 60%,var(--ink));}
.ckmain-data .badge{background:#4d90c018;
  color:color-mix(in srgb,#2f6f9e 60%,var(--ink));}
.ckmain-constant .badge{background:#9a7cc01f;color:#6d4f95;}
.ckmain-settings .badge{background:#5b758918;color:#41566a;}
.ckmain-plotting .badge{background:color-mix(in srgb,var(--accent) 9%,transparent);color:var(--cyan-deep);}
.ckmain-print .badge{background:#cf9a4e1f;
  color:color-mix(in srgb,#8a6326 60%,var(--ink));}
.ckmain-comments .badge{background:#5f73861f;color:#4c5b66;}
/* dark theme (default) needs its own — a generic dark .badge otherwise
   outranks the base rules above */
body:not(.light) .ckmain-imports .badge{background:#8a6d4a2b;color:#c8a877;}
body:not(.light) .ckmain-function .badge{background:#46a8922b;color:#7fd0bd;}
body:not(.light) .ckmain-data .badge{background:#4d90c02b;color:#8fbfe0;}
body:not(.light) .ckmain-constant .badge{background:#9a7cc02b;color:#c3a9e0;}
body:not(.light) .ckmain-settings .badge{background:#5b75892b;color:#a7bccd;}
body:not(.light) .ckmain-plotting .badge{background:color-mix(in srgb,var(--accent) 17%,transparent);color:#5fc3d8;}
body:not(.light) .ckmain-print .badge{background:#cf9a4e2b;color:#dfb277;}
body:not(.light) .ckmain-comments .badge{background:#5f738633;color:#a2b2bd;}
.cardtitle{font-size:16px;font-weight:600;margin:0;letter-spacing:-.01em;
  flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;
  white-space:nowrap;}
/* titles that merely echo the first code line label the item in the
   nav, but are not repeated as a heading on the card */
.cardtitle.echo{display:none;}
.nodeid{font-family:var(--mono);font-size:10px;color:var(--ink-3);
  background:var(--paper-2);padding:2px 7px;border-radius:4px;flex:none;}

.cardbody{padding-left:6px;}
/* ---- figure zoom: a per-figure factor (--fz, set inline by the +/- on
   the card) multiplied by the feed-wide factor (--fzall on the shell).
   The CARD grows — border, header and all — so a bigger figure is never
   sitting outside its own cell. It stays centred on the column. ---- */
.nbshell{--fzall:1;}
.card.has-fig{--fz:1;
  width:calc(100% * var(--fz) * var(--fzall));
  margin-left:calc((1 - var(--fz) * var(--fzall)) * 50%);}
/* a wider card is not a bigger figure: a PNG at its natural size ignores
   a roomier box, because max-width only CAPS. While zoomed, the image
   fills the frame so it actually grows. */
.card.has-fig.zoomed .figframe img,
.card.has-fig.zoomed .figframe svg,
.card.has-fig.zoomed .figpage img{
  width:100%;max-width:none;height:auto;}
.cb-fig{position:relative;}
/* top-LEFT on purpose: Plotly/Bokeh draw their own toolbar top-right, and
   the two would sit on top of each other. Invisible until you point at the
   card, and un-clickable while invisible so you never hit it blind. */
.figzoom{position:absolute;top:6px;left:6px;z-index:4;display:flex;gap:3px;
  opacity:0;pointer-events:none;transition:opacity .13s;}
.card:hover .figzoom,.figzoom:focus-within{opacity:1;pointer-events:auto;}
.fz-btn{font-family:var(--mono);font-size:12px;line-height:1;width:23px;
  height:23px;padding:0;border-radius:5px;cursor:pointer;
  border:1px solid var(--line);background:var(--paper);color:var(--ink-2);}
.fz-btn:hover{border-color:var(--cyan);color:var(--ink);}
body:not(.light) .fz-btn{background:#0d1a24d9;border-color:#ffffff2b;
  color:#cfe0ea;}
body:not(.light) .fz-btn:hover{color:#fff;border-color:var(--cyan);}
/* T612: the bar's one worded button -- words plus icon, like every
   other action, so it is a pill rather than a square */
.fz-btn.fz-copy,.fz-btn.fz-q{width:auto;display:inline-flex;
  align-items:center;gap:4px;padding:0 8px;font-size:10.5px;}
.fz-copy .bic,.fz-q .bic{width:11px;height:11px;margin:0;}
/* the tree/trace clones and slide frames never carry the zoom chrome, and
   a cloned card is sized by its frame — never by the feed's zoom */
.tree-node .figzoom,.an-cell .figzoom,.spane .figzoom,.slide-fig .figzoom,
.vo-step .figzoom,.print-page .figzoom{display:none!important;}
.an-cell .card.has-fig,.spane .card.has-fig,.slide-fig .card.has-fig,
.tree-node .card.has-fig,.vo-step .card.has-fig,
.print-page .card.has-fig,.rawview .card.has-fig{
  width:100%!important;margin-left:0!important;}
/* full-screen figure viewer (⤢) */
.figmax{position:fixed;inset:0;z-index:300;background:var(--overlay);
  display:flex;align-items:center;justify-content:center;padding:34px;}
.figmax[hidden]{display:none;}
.figmax-box{max-width:96vw;max-height:92vh;overflow:auto;
  background:var(--output-paper);color:var(--output-ink);
  border-radius:10px;padding:10px;}
.figmax-box img,.figmax-box svg{max-width:100%;max-height:88vh;
  width:auto;height:auto;display:block;margin:0 auto;}
/* T255: the zoomed subtree. CSS `zoom` (not a transform) because it
   grows the LAYOUT box, so .figmax-box gets real scrollbars and a drag
   can pan with scrollLeft/scrollTop — a transform would paint over the
   edges and scroll nothing. */
.figmax-scale{zoom:var(--fmz,1);}
.figmax.zoomed .figmax-box{cursor:grab;}
.figmax.zoomed .figmax-box.panning{cursor:grabbing;}
/* T255: one bar, top right — the same boxed 12px mono control as every
   other bar in the app, words plus icons */
.figmax-bar{position:fixed;top:16px;right:18px;display:flex;gap:5px;
  align-items:center;z-index:2;}
.figmax-b{font-family:var(--mono);font-size:12px;line-height:1;
  height:30px;padding:0 10px;border-radius:7px;cursor:pointer;
  display:inline-flex;align-items:center;gap:5px;white-space:nowrap;
  border:1px solid #ffffff30;background:#0d1a24ee;color:#e7eff5;}
.figmax-b:hover{border-color:var(--cyan);color:#fff;}
.figmax-b .bic{width:14px;height:14px;flex:none;}
.figmax-val{min-width:88px;justify-content:center;}
.figframe{background:var(--output-paper);color:var(--output-ink);
  border:1px solid var(--output-line);border-radius:8px;
  padding:8px;overflow:auto;text-align:center;}
.figframe img{max-width:100%;height:auto;display:block;margin:0 auto;}
.figframe svg{max-width:100%;height:auto;}
/* interactive plots (plotly/bokeh/vega/folium) + video / gif outputs */
.figframe.plotframe{overflow:hidden;padding:0;}
.plotly-embed{width:100%;min-height:340px;}
.plotframe .rich,.plotframe .js-plotly-plot{width:100%;}
.vid-out{max-width:100%;height:auto;display:block;margin:0 auto;
  border-radius:6px;background:#000;}
/* in a slide frame these fill the frame like a figure */
.an-cell .plotly-embed,.spane .plotly-embed,
.slide-fig .plotly-embed{min-height:0;height:100%;flex:1;}
.an-cell .vid-out,.spane .vid-out,.slide-fig .vid-out{max-height:100%;
  width:auto;}

/* several figures from one cell: pager with prev/next arrows */
.figpager .figpage{display:none;}
.figpager .figpage.current{display:block;}
/* T700: the nav is ABOVE the figures (render/items.py), worded, and on
   a tinted band, so a cell with several figures says so before the
   first one is scrolled past */
.figpager-nav{display:flex;align-items:center;justify-content:center;
  gap:10px;margin:0 0 8px;padding:4px 6px;border-radius:7px;
  background:color-mix(in srgb,var(--cyan) 9%,transparent);
  border:1px solid color-mix(in srgb,var(--cyan) 28%,transparent);}
.fp-btn{font-family:var(--sans);font-size:12px;line-height:1;
  border:1px solid var(--paper-3);background:#fff;color:var(--ink-2);
  border-radius:6px;height:24px;cursor:pointer;padding:0 10px;}
.fp-btn:hover{border-color:var(--cyan);color:var(--ink);}
.fp-count{font-family:var(--sans);font-size:12px;font-weight:600;
  color:var(--ink-2);min-width:88px;text-align:center;}

/* huge markdown notes: clamped with a Show more toggle */
.cardbody.mdclamp{max-height:440px;overflow:hidden;position:relative;}
/* ...decided when the note first comes near the screen (app.js
   mdClampWatch), not by measuring every note at load -- each measure
   forced the layout of a card content-visibility was skipping. Until
   then a notebook's note is held at the clamp's height, so a long one
   never paints at full length and then jumps: the fade and Show more
   are all that arrive. `clip`, not hidden: no new formatting context,
   so a short note's margins lay out exactly as they will after. */
.nbshell:not(.tracetab) .content .card[data-note="1"]>.cardbody:not([data-mdclamp]){
  max-height:440px;overflow:clip;}
.cardbody.mdclamp::after{content:"";position:absolute;left:0;right:0;
  bottom:0;height:64px;pointer-events:none;
  background:linear-gradient(#fbfcfd00,var(--paper));}
.cardbody.mdclamp.mdopen{max-height:none;}
.cardbody.mdclamp.mdopen::after{display:none;}
.mdmore{display:block;margin:8px 0 0 6px;font-family:var(--mono);
  font-size:10.5px;border:1px solid var(--line);background:#fff;
  color:var(--cyan-deep);border-radius:6px;padding:4px 12px;
  cursor:pointer;}
.mdmore:hover{border-color:var(--cyan);color:var(--ink);}

/* notes with raw HTML: rendered by default, the source behind a tiny
   </> button floating top-right (visible on hover) */
.note-src{display:none;margin:9px 0 0;}
.card.showhtml .cardbody>.note{display:none;}
.card.showhtml .note-src{display:block;}
.htmltoggle{position:absolute;top:8px;right:64px;z-index:2;
  font-family:var(--mono);font-size:10px;letter-spacing:.04em;
  color:var(--ink-3);background:none;border:1px solid var(--line);
  cursor:pointer;padding:2px 7px;border-radius:5px;opacity:0;
  transition:opacity .15s,color .15s;}
.card:hover .htmltoggle,.htmltoggle:focus,
.card.showhtml .htmltoggle{opacity:.8;}
.htmltoggle:hover{opacity:1;color:var(--cyan-deep);
  border-color:var(--cyan);}
.htmltoggle .ht-hide{display:none;}
.card.showhtml .htmltoggle .ht-show{display:none;}
.card.showhtml .htmltoggle .ht-hide{display:inline;}
.an-cell .htmltoggle,.an-cell .note-src,
.spane .htmltoggle,.spane .note-src{display:none;}
/* markdown notes: minimal chrome. No MARKDOWN badge; a note with no real
   heading drops its "Note" title row too — controls float top-right, and
   hovering the card pops a small amber "markdown" label by its edge */
/* the markdown card's own box: background / border / padding / radius are
   all view-stylable, defaulting to the stock card look */
.card[data-note="1"]{position:relative;
  background:var(--md-bg,var(--paper));
  border-color:var(--md-bd,var(--line));
  border-width:var(--md-bw,1px);
  border-radius:var(--md-rad,10px);
  padding:var(--md-pad,18px) var(--md-pad,18px) calc(var(--md-pad,18px) - 2px);}
.card[data-note="1"] .badge{display:none;}
.card.note-untitled>.cardhead{position:absolute;top:6px;right:8px;
  z-index:2;margin:0;gap:6px;}
.card.note-untitled .cardtitle{display:none;}
.card.note-untitled::after{content:"markdown";position:absolute;
  left:14px;top:8px;font-family:var(--mono);font-size:8.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--amber);
  opacity:0;transition:opacity .15s;pointer-events:none;}
.card.note-untitled:hover::after{opacity:.85;}
/* tables inside notes render as real tables, not floating rows */
/* a table is text too: it must follow the TEXT stepper and a custom
   view's markdown size, or "make the text bigger" visibly skips it */
/* the raw view's markdown cells (.rawmd) draw theirs the same way (T666) */
.note table,.rawmd table{border-collapse:collapse;margin:10px 0;
  font-size:calc(13.5px * var(--mdscale,1) * var(--md-size,1));}
.note th,.note td,.rawmd th,.rawmd td{border:1px solid #00000022;
  padding:5px 11px;text-align:left;}
.note th,.rawmd th{background:#00000008;font-weight:600;}
body:not(.light) .note th,body:not(.light) .note td,
body:not(.light) .rawmd th,body:not(.light) .rawmd td{
  border-color:#ffffff26;}
body:not(.light) .note th,body:not(.light) .rawmd th{background:#ffffff0d;}
/* a Markdown table (T666) sits in a box of its own: wider than the
   column, it scrolls there, and the page never does */
.md-table{max-width:100%;overflow-x:auto;margin:10px 0;}
.md-table table{margin:0;}

pre.result,pre.stream,pre.error{font-family:var(--mono);font-size:12px;
  background:var(--paper-2);border:1px solid var(--paper-3);
  border-radius:7px;padding:11px 13px;overflow:auto;margin:0;line-height:1.45;}
pre.error{background:#fbf0ee;border-color:#f0d2cc;color:#8a3221;}
/* a huge printout (1000s of lines) scrolls inside a capped box in the
   document + raw views instead of running the whole page on. Short
   outputs are unaffected; slide frames keep their own sizing. */
.content pre.result,.content pre.stream,.content pre.error,
.content .rich,.content .jv-xr,
.rawview pre.result,.rawview pre.stream,.rawview .rich,
.rawview .jv-xr{max-height:min(440px,62vh);overflow:auto;}
.card.k-metric .cardbody pre.result{font-size:14px;
  background:#46a8920d;border-color:#46a89233;color:#1f5f54;
  font-weight:500;}

/* prose scales with the "Text size" control (--mdscale on the shell) —
   markdown notes and captions, not code or output */
.nbshell{--mdscale:1;background:var(--vw-bg,transparent);}
/* ---- CUSTOM VIEW styling (2026-07-29) -----------------------------
   Every prose/heading property a custom view can set reads from an
   INHERITED custom property, which is what gives the cascade for free:
   the value is stamped on .nbshell for "all markdown cells", on a
   .section for one section, or on a .card for one cell — narrowest
   wins, exactly like the user's mental model. Defaults in the var()
   fallbacks keep an unstyled document byte-identical to before. */
.note{font-family:var(--md-font,var(--serif));
  font-size:calc(15px * var(--mdscale) * var(--md-size,1));
  line-height:var(--md-lh,1.65);color:var(--md-col,var(--ink-2));
  text-align:var(--md-align,start);}
.note .caption{font-family:var(--md-font,var(--serif));font-style:normal;
  color:var(--md-col,var(--ink-2));margin:0;padding:0;border:none;
  font-size:calc(15px * var(--mdscale) * var(--md-size,1));}

.caption{font-family:var(--serif);font-size:calc(14px * var(--mdscale));
  color:var(--ink-2);margin:13px 0 0;padding-left:6px;line-height:1.6;}

/* a cell's printed output part, adjacent to its figure part (Output filter) */
.cb-out{margin-top:12px;}
.cb-fig+.cb-out{margin-top:14px;}

.prov{display:flex;align-items:center;gap:7px;flex-wrap:wrap;
  margin:13px 0 0;padding-left:6px;}
.prov-l{font-family:var(--mono);font-size:9.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--amber);}
.depchip{font-family:var(--mono);font-size:11px;color:var(--ink-2);
  text-decoration:none;background:#cf9a4e14;border:1px solid #cf9a4e33;
  padding:2px 9px;border-radius:20px;
  transition:color .15s,background-color .15s,border-color .15s,
    box-shadow .15s,opacity .15s;}
.depchip:hover{background:var(--amber);color:#fff;border-color:var(--amber);}

/* ---------- code ---------- */
.codewrap{margin:13px 0 0;border-top:1px solid var(--line);padding-top:11px;}
.codewrap.bare{border-top:none;padding-top:0;margin-top:10px;}
.codetoggle{font-family:var(--mono);font-size:11px;letter-spacing:.05em;
  color:var(--ink-3);background:none;border:none;cursor:pointer;padding:2px 6px;
  display:inline-flex;align-items:center;gap:7px;border-radius:5px;
  transition:color .15s;}
.codetoggle:hover{color:var(--cyan-deep);}
.codetoggle .chev{display:inline-block;transition:transform .2s;font-size:14px;}
.ct-hide{display:none;}
.codewrap[data-open] .codetoggle .chev{transform:rotate(90deg);}
.codewrap[data-open] .ct-show{display:none;}
.codewrap[data-open] .ct-hide{display:inline;}
.codebody{display:grid;grid-template-rows:0fr;transition:grid-template-rows .28s ease;}
.codewrap[data-open] .codebody{grid-template-rows:1fr;}
.codebody>.codeinner,.codeinner{overflow:hidden;min-height:0;}
.codestep{margin-top:14px;}
.codestep:first-child{margin-top:0;}
.codestep-h{display:flex;align-items:center;gap:9px;margin:0 0 7px;}
.stepnum{font-family:var(--mono);font-size:10px;font-weight:600;
  width:19px;height:19px;border-radius:5px;display:inline-flex;
  align-items:center;justify-content:center;
  background:color-mix(in srgb,var(--amber) 12%,transparent);
  color:var(--amber);flex:none;}
.steplabel{font-family:var(--mono);font-size:10.5px;letter-spacing:.1em;
  text-transform:uppercase;color:var(--ink-3);}
.codestep-out{margin-top:9px;}
.codestep pre.code{margin:0;}
.ct-steps{margin-left:9px;color:var(--ink-3);}
pre.code{font-family:var(--mono);font-size:12.5px;line-height:1.55;
  background:#0e1b25;color:#c9d6e0;border-radius:8px;padding:14px 16px;
  margin:9px 0 2px;overflow:auto;}
pre.code .kw{color:#6bb8d6;}
pre.code .bn{color:#86c5a8;}
pre.code .st{color:#d8a36a;}
pre.code .nu{color:#c98fd0;}
pre.code .co{color:#5d7185;}
pre.code .op{color:#9fb1c0;}

/* ---------- xarray repr ---------- */
/* jv-xr is OUR wrapper around the repr; xarray's own inner div is the one
   that carries .xr-wrap. They used to share the class name, and xarray's
   embedded `.xr-wrap{display:block !important}` overrode every junoview
   hide/fold rule on the wrapper (2026-08-03) */
.jv-xr{font-size:13px;overflow:auto;border:1px solid var(--output-line);
  border-radius:8px;padding:4px 8px;background:var(--output-paper);
  color:var(--output-ink);}
.jv-xr .xr-array-wrap,.jv-xr .xr-var-list{font-family:var(--mono);}

/* ---------- empty / fallback ---------- */
.rich{overflow:auto;background:var(--output-paper);color:var(--output-ink);}
/* rich OUTPUT (dataframes and friends) follows the feed-wide text
   stepper too — but not --md-size, which styles markdown cells only */
.rich table{border-collapse:collapse;
  font-size:calc(13px * var(--mdscale,1));}
.rich th,.rich td{border:1px solid var(--output-line);padding:4px 8px;}

/* ---------- focus ---------- */
a:focus-visible,button:focus-visible,.toggle:focus-visible{
  outline:2px solid var(--focus);outline-offset:2px;}

/* ---------- responsive ---------- */
@media (max-width:860px){
  .shell{grid-template-columns:1fr;}
  .rail{position:fixed;left:0;top:0;width:min(86vw,330px);z-index:60;
    transform:translateX(-102%);transition:transform .3s ease;
    box-shadow:0 0 40px #00000055;}
  .rail.open{transform:none;}
  .menubtn{display:inline-flex;align-items:center;justify-content:center;
    width:36px;height:36px;border:1px solid var(--line);background:#fff;
    border-radius:var(--rad);cursor:pointer;flex:none;}
  .menubtn span,.menubtn span::before,.menubtn span::after{content:"";
    display:block;width:16px;height:2px;background:var(--ink);position:relative;}
  .menubtn span::before{position:absolute;top:-5px;}
  .menubtn span::after{position:absolute;top:5px;}
  .scrim{position:fixed;inset:0;background:var(--overlay);z-index:55;display:none;}
  .scrim.show{display:block;}
  .content{padding:22px 18px 30vh;}
  .sectionhead h2{font-size:22px;}
  .sectionhead-l2 h2{font-size:19px;}
  .sectionhead-l3 h2{font-size:16px;}
  .section.sec-l2 .sectionhead{margin-left:8px;}
  .section.sec-l3 .sectionhead{margin-left:16px;}
}

@media (prefers-reduced-motion:reduce){
  *{transition:none!important;scroll-behavior:auto!important;}
}


/* ---- THEMES -------------------------------------------------------
   One complete token contract: a theme owns the reader, welcome page,
   rail, overlays and editor chrome together. Deck and figure colours
   are authored content and deliberately remain untouched. */
body:not(.light){
  --ink:#e7edf3;--ink-2:#c4d0da;--ink-3:#91a3b2;
  --paper:#101c28;--paper-2:#0b141d;--paper-3:#1a2a38;
  --line:#ffffff1f;
  --chrome:#11202c;--chrome-0:#0b141d;--chrome-1:#0e1926;
  --chrome-2:#162735;--chrome-3:#101c28;--chrome-4:#172838;
  --chrome-line:#ffffff1f;--chrome-ink:#d7e3ec;
  --chrome-ink-2:#a8b7c4;--chrome-ink-3:#8195a6;
  --accent:#58c4db;--accent-deep:#1f7185;--accent-soft:#8fd8ea;
  --btn-bg:#ffffff12;--btn-border:#ffffff40;--btn-ink:#d7e3ec;
  --surface-hover:#ffffff0c;--surface-active:#ffffff1a;
  --border-strong:#627484;--input-bg:#172633;
  --tooltip-bg:#0b1520;--tooltip-ink:#f2f6fa;
  --overlay:#050b11cc;--shadow:#00000099;--focus:#8fd8ea;
  --selection:#39a9c04d;--danger:#ff796a;--warning:#e0a33a;
  --success:#58bca4;--amber:#cf9a4e;--on-accent:#04222b;--on-accent-deep:#ffffff;}
body.light{
  --ink:#16202b;--ink-2:#465767;--ink-3:#596b7d;
  --paper:#fbfcfd;--paper-2:#eef2f6;--paper-3:#e2e8ee;
  --line:#d8e0e8;
  --chrome:#eef2f6;--chrome-0:#f4f7fa;--chrome-1:#eef2f6;
  --chrome-2:#ffffff;--chrome-3:#f7f9fb;--chrome-4:#e8eef4;
  --chrome-line:#0000001f;--chrome-ink:#16202b;
  --chrome-ink-2:#465767;--chrome-ink-3:#596b7d;
  --accent:#0e6174;--accent-deep:#11667a;--accent-soft:#46a9bd;
  --btn-bg:#ffffff;--btn-border:#b9c7d3;--btn-ink:#263746;
  --surface-hover:#00000008;--surface-active:#00000012;
  --border-strong:#798b9b;--input-bg:#ffffff;
  --tooltip-bg:#172330;--tooltip-ink:#f2f6fa;
  --overlay:#1020308f;--shadow:#1a263440;--focus:#17677a;
  --selection:#238aa03d;--danger:#a8352b;--warning:#7a4e06;
  --success:#1f6652;--amber:#7d5410;--on-accent:#ffffff;--on-accent-deep:#ffffff;}
body.th-forest{
  --ink:#e2f0e9;--ink-2:#bed3c8;--ink-3:#8baa9a;
  --paper:#10271f;--paper-2:#091711;--paper-3:#19352a;
  --line:#5d8a7347;
  --chrome:#0e241c;--chrome-0:#07120e;--chrome-1:#0b1d16;
  --chrome-2:#143028;--chrome-3:#10271f;--chrome-4:#18372c;
  --chrome-line:#8ac2a52e;--chrome-ink:#daf0e5;
  --chrome-ink-2:#acc4b8;--chrome-ink-3:#8eaa9c;
  --accent:#61d3a4;--accent-deep:#237a59;--accent-soft:#a9e9cf;
  --btn-bg:#41c49314;--btn-border:#41c49370;--btn-ink:#d7f2e6;
  --surface-hover:#8adab21a;--surface-active:#8adab22e;
  --border-strong:#6a8578;--input-bg:#173329;
  --tooltip-bg:#07130e;--tooltip-ink:#effaf4;
  --overlay:#04100acc;--shadow:#00000099;--focus:#a9e9cf;
  --selection:#41c49345;--danger:#ff8478;--warning:#e8b35b;
  --success:#68d2a8;--amber:#cf9a4e;--on-accent:#062219;--on-accent-deep:#ffffff;}
body.th-forestblue{
  --ink:#e3eee9;--ink-2:#bfd2c9;--ink-3:#8da99b;
  --paper:#10271f;--paper-2:#091711;--paper-3:#19352a;
  --line:#5d8a7347;
  --chrome:#0e241c;--chrome-0:#07120e;--chrome-1:#0b1d16;
  --chrome-2:#143028;--chrome-3:#10271f;--chrome-4:#18372c;
  --chrome-line:#8ac2a52e;--chrome-ink:#dcebe4;
  --chrome-ink-2:#acc4b8;--chrome-ink-3:#8eaa9c;
  --accent:#95b7ff;--accent-deep:#3b63c4;--accent-soft:#c3d6ff;
  --btn-bg:#6b9bff1f;--btn-border:#6b9bff7a;--btn-ink:#e2ebff;
  --surface-hover:#8adab21a;--surface-active:#8adab22e;
  --border-strong:#6a8578;--input-bg:#173329;
  --tooltip-bg:#07130e;--tooltip-ink:#effaf4;
  --overlay:#04100acc;--shadow:#00000099;--focus:#c3d6ff;
  --selection:#6b9bff4d;--danger:#ff8478;--warning:#e8b35b;
  --success:#68d2a8;--amber:#cf9a4e;--on-accent:#07142d;--on-accent-deep:#ffffff;}
/* High contrast means the SURFACES go too, not just the accent: near
   black behind near white, with real edges. It used to re-ink only the
   accent and the buttons, so it was the ordinary dark theme with brighter
   outlines — which is not what anyone turning on high contrast is asking
   for (2026-08-20, user: "some of the themes are not right"). */
/* ---- LIGHT re-inks the surfaces too -------------------------------
   It used to re-ink only the page and leave --chrome-0..4 at their dark
   values, so every menu, panel and popup relied on a hand-written
   `body.light .thing{background:#fff}` rule of its own. Anything added
   without one — and by August that was most of the deck editor's menus —
   came out dark-on-light or, where the override existed but carried an
   alpha byte, washed out (2026-08-20, user: "some of the menu options in
   different themes also are too transparent").
   Setting the tokens fixes every menu at once, including the ones nobody
   has written yet. */
body.light.th-lforest{
  --ink:#17261e;--ink-2:#405a4d;--ink-3:#556d60;
  --paper:#f7fbf8;--paper-2:#e9f3ec;--paper-3:#dbeae0;
  --line:#bfd6c7;
  --chrome:#eaf4ef;--chrome-0:#f2f9f5;--chrome-1:#eaf4ef;
  --chrome-2:#ffffff;--chrome-3:#f5fbf8;--chrome-4:#e0efe7;
  --chrome-line:#245c3d29;--chrome-ink:#17261e;
  --chrome-ink-2:#405a4d;--chrome-ink-3:#556d60;
  --accent:#14613f;--accent-deep:#126343;--accent-soft:#5cc9a0;
  --btn-bg:#ffffff;--btn-border:#a9cbb8;--btn-ink:#1e4734;
  --surface-hover:#1e8f660d;--surface-active:#1e8f661f;
  --border-strong:#718d7d;--input-bg:#ffffff;
  --tooltip-bg:#173b2b;--tooltip-ink:#f4fbf7;
  --overlay:#10281b8f;--shadow:#183d2b3d;--focus:#136647;
  --selection:#1e8f6638;--danger:#a3372e;--warning:#7a540c;
  --success:#176647;--amber:#7d5410;--on-accent:#ffffff;--on-accent-deep:#ffffff;}
body.th-colorful{
  --ink:#eeeaf8;--ink-2:#d1c9e3;--ink-3:#a69bbd;
  --paper:#181728;--paper-2:#0e0d19;--paper-3:#25223a;
  --line:#bba8e633;
  --chrome:#171426;--chrome-0:#0d0b16;--chrome-1:#141020;
  --chrome-2:#211c33;--chrome-3:#191528;--chrome-4:#29213d;
  --chrome-line:#cfbaff2e;--chrome-ink:#eee9fa;
  --chrome-ink-2:#bdb4cd;--chrome-ink-3:#9c91b0;
  --accent:#b69af2;--accent-deep:#7150b8;--accent-soft:#dacbff;
  --btn-bg:#a586e81f;--btn-border:#a586e875;--btn-ink:#f1ebff;
  --surface-hover:#c4aeff17;--surface-active:#c4aeff2b;
  --border-strong:#796f8b;--input-bg:#25223b;
  --tooltip-bg:#100d1a;--tooltip-ink:#f5f1fb;
  --overlay:#090711d6;--shadow:#000000a6;--focus:#dacbff;
  --selection:#a586e84d;--danger:#ff789d;--warning:#f0b458;
  --success:#63d5b8;--amber:#cf9a4e;--on-accent:#160c2b;--on-accent-deep:#ffffff;}
body.th-contrast{
  --ink:#ffffff;--ink-2:#f0f4f7;--ink-3:#c8d3dc;
  --paper:#090b0d;--paper-2:#000000;--paper-3:#151a1f;
  --line:#ffffff8f;
  --chrome:#000000;--chrome-0:#000000;--chrome-1:#080a0c;
  --chrome-2:#101418;--chrome-3:#0a0d10;--chrome-4:#141a1f;
  --chrome-line:#ffffff8f;--chrome-ink:#ffffff;
  --chrome-ink-2:#d7e0e7;--chrome-ink-3:#bac8d2;
  --accent:#6fe3ff;--accent-deep:#00647c;--accent-soft:#c8f2ff;
  --btn-bg:#ffffff1f;--btn-border:#ffffffb0;--btn-ink:#ffffff;
  --surface-hover:#ffffff1f;--surface-active:#ffffff36;
  --border-strong:#ffffff;--input-bg:#111111;
  --tooltip-bg:#ffffff;--tooltip-ink:#000000;
  --overlay:#000000e6;--shadow:#000000;--focus:#ffffff;
  --selection:#6fe3ff66;--danger:#ff9b91;--warning:#ffd06e;
  --success:#85e8c9;--amber:#e0ac5c;--on-accent:#000000;--on-accent-deep:#ffffff;}
/* T626: the browser's own controls -- a select's list, a field's
   spinner -- are drawn in the scheme it is TOLD, and nobody told it: the
   History "compare with" list was a white box in every dark scheme. On the
   controls only, not on body: a color-scheme there would also give every
   embedded output frame an opaque canvas. */
body:not(.light) :is(select,input,textarea){color-scheme:dark;}
body.light :is(select,input,textarea){color-scheme:light;}
/* The additional families change the surfaces as well as the accent. They
   repeat the whole contract on purpose: adding a token to one theme but not
   another is a test failure, not a partly-themed component (T253). */
body.light.th-warm{
  --ink:#2c241b;--ink-2:#594b3b;--ink-3:#6c5946;
  --paper:#fbf5e9;--paper-2:#ede2cd;--paper-3:#e6d8bf;
  --line:#d4c2a5;
  --chrome:#ede2cd;--chrome-0:#f2e8d7;--chrome-1:#ede2cd;
  --chrome-2:#fff9ef;--chrome-3:#f7eedf;--chrome-4:#e6d8bf;
  --chrome-line:#967e5d;--chrome-ink:#2c241b;
  --chrome-ink-2:#594b3b;--chrome-ink-3:#6c5946;
  --accent:#7f3a1a;--accent-deep:#7c381c;--accent-soft:#f1d7c6;
  --btn-bg:#fff9ef;--btn-border:#b99f7c;--btn-ink:#3c3023;
  --surface-hover:#91431f0d;--surface-active:#91431f1f;
  --border-strong:#967e5d;--input-bg:#fff9ef;
  --tooltip-bg:#2c241b;--tooltip-ink:#fbf5e9;
  --overlay:#2c241b99;--shadow:#594b3b45;--focus:#91431f;
  --selection:#91431f38;--danger:#a52f27;--warning:#735005;
  --success:#245d3c;--amber:#734d0e;--on-accent:#ffffff;--on-accent-deep:#ffffff;}
body.th-navy{
  --ink:#e7eff8;--ink-2:#a9bcd0;--ink-3:#7e96af;
  --paper:#0c1a2b;--paper-2:#07111f;--paper-3:#12243a;
  --line:#2a4561;
  --chrome:#081526;--chrome-0:#07111f;--chrome-1:#0c1a2b;
  --chrome-2:#112841;--chrome-3:#0c1a2b;--chrome-4:#142c45;
  --chrome-line:#2a4561;--chrome-ink:#e7eff8;
  --chrome-ink-2:#a9bcd0;--chrome-ink-3:#7e96af;
  --accent:#77b8ff;--accent-deep:#235e9f;--accent-soft:#b8d9ff;
  --btn-bg:#77b8ff1a;--btn-border:#77b8ff66;--btn-ink:#e7eff8;
  --surface-hover:#77b8ff1a;--surface-active:#77b8ff2e;
  --border-strong:#647e98;--input-bg:#142c45;
  --tooltip-bg:#07111f;--tooltip-ink:#e7eff8;
  --overlay:#030914d6;--shadow:#000000aa;--focus:#8ec5ff;
  --selection:#77b8ff4d;--danger:#ff8590;--warning:#f1bd63;
  --success:#70d0ae;--amber:#cf9a4e;--on-accent:#06182c;--on-accent-deep:#ffffff;}
body.th-purple{
  --ink:#f2eaf5;--ink-2:#c7b5cd;--ink-3:#9c84a6;
  --paper:#1d1426;--paper-2:#140d1b;--paper-3:#281b33;
  --line:#4b3855;
  --chrome:#180f21;--chrome-0:#140d1b;--chrome-1:#1d1426;
  --chrome-2:#2a1d36;--chrome-3:#1d1426;--chrome-4:#2e203b;
  --chrome-line:#4b3855;--chrome-ink:#f2eaf5;
  --chrome-ink-2:#c7b5cd;--chrome-ink-3:#9c84a6;
  --accent:#d39af0;--accent-deep:#81479e;--accent-soft:#e8c8f7;
  --btn-bg:#d39af01a;--btn-border:#d39af066;--btn-ink:#f2eaf5;
  --surface-hover:#d39af017;--surface-active:#d39af02b;
  --border-strong:#806c89;--input-bg:#2e203b;
  --tooltip-bg:#140d1b;--tooltip-ink:#f2eaf5;
  --overlay:#09050ed6;--shadow:#000000aa;--focus:#e0b2f5;
  --selection:#d39af04d;--danger:#ff86a1;--warning:#efb968;
  --success:#78d1ae;--amber:#cf9a4e;--on-accent:#1a0922;--on-accent-deep:#ffffff;}
body.th-dim{
  --ink:#e2e5e9;--ink-2:#b5bbc3;--ink-3:#99a2ac;
  --paper:#202328;--paper-2:#181a1d;--paper-3:#292d33;
  --line:#41474f;
  --chrome:#1b1e22;--chrome-0:#181a1d;--chrome-1:#202328;
  --chrome-2:#2b2f35;--chrome-3:#202328;--chrome-4:#30343a;
  --chrome-line:#41474f;--chrome-ink:#e2e5e9;
  --chrome-ink-2:#b5bbc3;--chrome-ink-3:#99a2ac;
  --accent:#9eb6c7;--accent-deep:#526c7d;--accent-soft:#c5d4de;
  --btn-bg:#9eb6c717;--btn-border:#9eb6c75c;--btn-ink:#e2e5e9;
  --surface-hover:#ffffff12;--surface-active:#ffffff20;
  --border-strong:#747d87;--input-bg:#30343a;
  --tooltip-bg:#181a1d;--tooltip-ink:#e2e5e9;
  --overlay:#0c0d0fd6;--shadow:#000000aa;--focus:#b2cad8;
  --selection:#9eb6c747;--danger:#f38b84;--warning:#d8b36b;
  --success:#7cc5a7;--amber:#d6a35a;--on-accent:#111417;--on-accent-deep:#ffffff;}
body.light.th-lcontrast{
  --ink:#000000;--ink-2:#222222;--ink-3:#444444;
  --paper:#ffffff;--paper-2:#f0f0f0;--paper-3:#e4e4e4;
  --line:#666666;
  --chrome:#ffffff;--chrome-0:#ffffff;--chrome-1:#f0f0f0;
  --chrome-2:#ffffff;--chrome-3:#f7f7f7;--chrome-4:#e5f4f8;
  --chrome-line:#666666;--chrome-ink:#000000;
  --chrome-ink-2:#222222;--chrome-ink-3:#444444;
  --accent:#005a73;--accent-deep:#00465a;--accent-soft:#d5f3fa;
  --btn-bg:#ffffff;--btn-border:#444444;--btn-ink:#000000;
  --surface-hover:#005a7314;--surface-active:#005a7329;
  --border-strong:#000000;--input-bg:#ffffff;
  --tooltip-bg:#000000;--tooltip-ink:#ffffff;
  --overlay:#00000099;--shadow:#00000066;--focus:#005a73;
  --selection:#005a7340;--danger:#8f1710;--warning:#6d4a00;
  --success:#075f3e;--amber:#6b4608;--on-accent:#ffffff;--on-accent-deep:#ffffff;}
/* T744: THE SITE'S OWN LOOK, AS A SCHEME (2026-11-02, owner, of the home
   page: "this is a cool theme you have on the front page. Can this also
   be a site wide theme with these colours?"). Ink and amber is the home
   page's dark -- warm ink, not navy, the logo's amber as the one accent
   -- and Paper and amber its light, with a deep amber brown for
   words and marks (the bright amber is 1.9:1 on paper). The values are
   app.css's --lp-* (THE SITE'S HOME PAGE), so the editor, the reader and
   the home page wear one palette. */
body.th-ink{
  --ink:#f4f0e6;--ink-2:#d9d3c5;--ink-3:#aaa394;
  --paper:#1e1b16;--paper-2:#15130f;--paper-3:#25221c;
  --line:#3b362d;
  --chrome:#15130f;--chrome-0:#100e0b;--chrome-1:#1a1713;
  --chrome-2:#25221c;--chrome-3:#1e1b16;--chrome-4:#2b2720;
  --chrome-line:#3b362d;--chrome-ink:#f4f0e6;
  --chrome-ink-2:#d9d3c5;--chrome-ink-3:#aaa394;
  --accent:#f2ad4b;--accent-deep:#8a5300;--accent-soft:#f8cf91;
  --btn-bg:#f4f0e612;--btn-border:#f4f0e640;--btn-ink:#f4f0e6;
  --surface-hover:#f4f0e60f;--surface-active:#f4f0e61f;
  --border-strong:#857c6c;--input-bg:#2b2720;
  --tooltip-bg:#25221c;--tooltip-ink:#f4f0e6;
  --overlay:#0a0806d6;--shadow:#000000aa;--focus:#f2ad4b;
  --selection:#ef9f2747;--danger:#ff8a7a;--warning:#f2c063;
  --success:#7fcfa6;--amber:#ef9f27;--on-accent:#1b1306;--on-accent-deep:#ffffff;}
body.light.th-paper{
  --ink:#15140f;--ink-2:#3b382f;--ink-3:#67635a;
  --paper:#fbfaf6;--paper-2:#f2f0e8;--paper-3:#e8e5da;
  --line:#d6d1c2;
  --chrome:#f2f0e8;--chrome-0:#f7f5ef;--chrome-1:#f2f0e8;
  --chrome-2:#fbfaf6;--chrome-3:#f7f5ef;--chrome-4:#e8e5da;
  --chrome-line:#cfc9b8;--chrome-ink:#15140f;
  --chrome-ink-2:#3b382f;--chrome-ink-3:#67635a;
  --accent:#7a4900;--accent-deep:#6b4000;--accent-soft:#ef9f27;
  --btn-bg:#fbfaf6;--btn-border:#cfc8b6;--btn-ink:#2a271f;
  --surface-hover:#15140f0a;--surface-active:#15140f17;
  --border-strong:#8f887a;--input-bg:#fbfaf6;
  --tooltip-bg:#15140f;--tooltip-ink:#f2f0e8;
  --overlay:#15140f8f;--shadow:#3b382f40;--focus:#7a4900;
  --selection:#ef9f2740;--danger:#a8352b;--warning:#7a4e06;
  --success:#1f6652;--amber:#7a4900;--on-accent:#ffffff;--on-accent-deep:#ffffff;}
body.th-contrast .rbn-lab,body.th-contrast .abgrp-lab{color:#e6f2fa;}
/* the bar and the tabs added on 2026-08-20 need the
   same treatment as the ribbon: real edges, near-white ink */
body.th-contrast .deck-qat,body.th-contrast .rbn-tabs{
  border-bottom-color:#ffffff66;}
body.th-contrast .rbn-tab{color:#c8dae6;}
body.th-contrast .rbn-tab[aria-selected="true"]{color:#fff;}
body.th-contrast .qat-name{color:#fff;}
body.th-contrast .qat-sep{background:#ffffff66;}
body.th-contrast .find-pop{border-color:#ffffff8a;}
body.th-contrast .jv-scheme-menu{border-color:#ffffff8a;}
body.th-contrast .edit-tools.ribbon{border-bottom-color:#ffffff66;}
body.th-contrast .rbn-grp{border-right-color:#ffffff66;}
/* DARK COLOURFUL: the buttons themselves carry their group's hue at
   REST — border, ink and a wash of background — not only on hover,
   which was invisible (2026-08-19, user: "dark colourful doesn't even
   do anything I can't tell"). Custom properties inherit, so scoping
   --accent to a group re-inks every button inside it. */
/* The group list is kept in step with the ribbon by hand, so a group
   added without a line here quietly falls back to the default accent and
   the theme looks half-applied — which is what had happened to Slides,
   Table, Animate and Page furniture (2026-08-20, user: "some of the
   themes are not right"). .rbn-file and .rbn-nbs are gone from the
   markup and gone from here with them. */
/* ONE HUE PER TAB (T205; 2026-09-02, user: "this is just chaos"). A
   group takes its TAB's colour, read from data-tab, so a tab is one
   colour and a group that moves between tabs (T204 moved four)
   changes with its new home instead of carrying the old one along.
   No list to keep in step any more. */
/* The body's data-theme-zone mirrors the ACTIVE tab (T252). Body-mounted
   dialogs and menus therefore inherit the same hue as the tab that opened
   them; a node can move out of the ribbon without falling back to cyan. The
   base colourful violet remains the deterministic hue outside the editor.
   While the slide editor covers the page the zone rides on what can be
   seen -- the editor, the rail, anything mounted on body -- rather than on
   body, which would restyle the whole document per tab (setThemeZone,
   app.js; 2026-10-09, speed), so each rule matches the attribute on body
   AND on any element under it. */
body.th-colorful[data-theme-zone="home"],
body.th-colorful [data-theme-zone="home"]{
  --accent:#f2b85b;--accent-deep:#9a5c00;}
body.th-colorful[data-theme-zone="images"],
body.th-colorful[data-theme-zone="text"],
body.th-colorful[data-theme-zone="style"],
body.th-colorful [data-theme-zone="images"],
body.th-colorful [data-theme-zone="text"],
body.th-colorful [data-theme-zone="style"]{
  --accent:#b89bf4;--accent-deep:#7150b8;}
body.th-colorful[data-theme-zone="design"],
body.th-colorful [data-theme-zone="design"]{
  --accent:#82a8ff;--accent-deep:#3b61ba;}
body.th-colorful[data-theme-zone="animation"],
body.th-colorful [data-theme-zone="animation"]{
  --accent:#65d7c0;--accent-deep:#167561;}
body.th-colorful[data-theme-zone="view"],
body.th-colorful [data-theme-zone="view"]{
  --accent:#62d49b;--accent-deep:#19764d;}
body.th-colorful[data-theme-zone="object"],
body.th-colorful [data-theme-zone="object"]{
  --accent:#eea4cc;--accent-deep:#a34276;}
body.th-colorful[data-theme-zone="present"],
body.th-colorful [data-theme-zone="present"]{
  --accent:#f18ab1;--accent-deep:#a63c68;}
/* T669: the Presentations tab, between Design's blue and Animation's
   green */
body.th-colorful[data-theme-zone="parts"],
body.th-colorful [data-theme-zone="parts"]{
  --accent:#6cc4e6;--accent-deep:#1e6c8c;}
body.th-colorful .rbn-grp[data-tab="home"],body.th-colorful .nb-filebar{
  --accent:#f2b85b;--accent-deep:#9a5c00;}
body.th-colorful .rbn-grp[data-tab="images"],
body.th-colorful .rbn-grp[data-tab="text"],
body.th-colorful .rbn-grp[data-tab="style"],
body.th-colorful .presrail{
  --accent:#b89bf4;--accent-deep:#7150b8;}
body.th-colorful .rbn-grp[data-tab="design"],body.th-colorful #ab-filters,
body.th-colorful #pt-grp,body.th-colorful #md-grp,
body.th-colorful #ck-grp,body.th-colorful #ot-grp{
  --accent:#82a8ff;--accent-deep:#3b61ba;}
body.th-colorful .rbn-grp[data-tab="animation"]{
  --accent:#65d7c0;--accent-deep:#167561;}
body.th-colorful .rbn-grp[data-tab="view"],body.th-colorful #ab-view,
body.th-colorful #ab-tree{--accent:#62d49b;--accent-deep:#19764d;}
body.th-colorful .rbn-grp[data-tab="object"]{
  --accent:#eea4cc;--accent-deep:#a34276;}
body.th-colorful .rbn-grp[data-tab="present"]{
  --accent:#f18ab1;--accent-deep:#a63c68;}
body.th-colorful .rbn-grp[data-tab="parts"]{
  --accent:#6cc4e6;--accent-deep:#1e6c8c;}
body.th-colorful .rbn-out,body.th-colorful #ab-size,
body.th-colorful #ab-scope{--accent:#f18ab1;--accent-deep:#a63c68;}
/* (T469: the panes used to be pinned green here, whatever tab opened
   them -- a Home ribbon opened a green Layers pane; the zone on body
   supplies the hue now) */
/* DIRECT rules, not --btn-* tokens: a token defined on body resolves
   its var(--accent) AT body — the same freeze the * alias exists for —
   so the per-group hue never reached the faces. A declaration on the
   button itself resolves against the accent that button inherits. */
body.th-colorful .appbar .toggle:not(.primary),
body.th-colorful .dbtn:not(.primary),
body.th-colorful .pr-btn,body.th-colorful .pr-item{
  border-color:color-mix(in srgb,var(--accent) 55%,#ffffff1a);
  background:color-mix(in srgb,var(--accent) 13%,#ffffff05);
  color:color-mix(in srgb,var(--accent) 55%,#f2f7fa);}
/* the theme picker's rows */
.jv-scheme-menu{position:fixed;z-index:300;background:var(--chrome-2);
  border:1px solid var(--chrome-line);border-radius:9px;padding:6px;
  box-shadow:0 14px 38px var(--shadow);display:flex;
  flex-direction:column;gap:2px;width:248px;max-height:min(680px,76vh);
  overflow-y:auto;}
.jv-scheme-menu[hidden]{display:none;}
/* T624: one line per row now (the family line went), so the row is the
   swatch's height: all thirteen fit unscrolled at 1280x600 */
.jv-scheme-opt{display:grid;grid-template-columns:40px minmax(0,1fr);
  align-items:center;gap:9px;width:100%;background:none;text-align:left;
  border:1px solid transparent;border-radius:7px;padding:3px 8px;
  cursor:pointer;color:var(--chrome-ink-2);font-family:var(--sans);}
.jv-scheme-opt:hover{background:color-mix(in srgb,var(--accent) 13%,
  transparent);border-color:color-mix(in srgb,var(--accent) 40%,
  transparent);}
.jv-scheme-opt[aria-checked="true"]{
  background:color-mix(in srgb,var(--accent) 20%,transparent);
  border-color:var(--accent);}
.jv-scheme-opt:focus-visible{outline:2px solid var(--focus);
  outline-offset:1px;}
/* Four cells, always in the same order: page, raised surface, text and
   accent. Two dots could only show "which accent"; this shows whether the
   whole family is light, dark, warm or high-contrast (T253). */
.jv-scheme-preview{width:40px;height:20px;display:grid;
  grid-template-columns:1fr 1fr;grid-template-rows:1fr 1fr;gap:2px;
  padding:2px;border:1px solid var(--border-strong);border-radius:5px;
  overflow:hidden;background:var(--chrome-1);}
.jv-scheme-preview i{display:block;min-width:0;min-height:0;
  border-radius:2px;border:1px solid #00000024;}
.jv-scheme-copy{min-width:0;display:flex;flex-direction:column;gap:2px;}
.jv-scheme-name{font-size:12px;color:var(--chrome-ink);line-height:1.2;}
/* ---- icon sizing where card/nav chrome swapped an emoji for a .bic
   svg (2026-08-23). These live in core.css because the widget's scoped
   bundle renders the same card chrome. ---- */
.navitem-eye .bic,.navsec-eye .bic{width:11px;height:11px;
  vertical-align:-2px;}
.navsec-hideall .bic{width:12px;height:12px;vertical-align:-2px;}
.fz-btn .bic{width:13px;height:13px;display:block;margin:0 auto;}
.htmltoggle .bic{width:10px;height:10px;vertical-align:-1px;}
.plot-trace-btn .bic,.var-trace .bic{width:11px;height:11px;vertical-align:-2px;}
.cell-eye .bic,.sec-eye .bic{display:block;}
