/* ============================================================================
   notebook2.css: v2 styles for the LearnHero Notebook.

   The whole Glass Canon visual language (tokens, header rail, flow strip, coach,
   hero, four-zone grid, cues, summary, record, dialogs, mobile stack) is REUSED
   from v1 by importing notebook.css. This file adds ONLY the rules the TipTap
   editor needs in the NOTES zone: `.nb2-editor .ProseMirror` in Glass Canon,
   Montserrat, lined-Cornell ruling (ported from v1's `.nb-composer textarea`),
   a crisp focus ring, and on-canon headings / lists / code / blockquote / the
   custom photo + sketch + cite nodes.

   Atrium calm register, navy-dominant, cyan-as-signal, all inherited unchanged.

   NOTE ON @import + the single-file build: @import "/notebook/notebook.css" works over
   http(s) and via the dev preview. The single-file (file://) build inlines BOTH
   stylesheets into one <style>, so the @import is resolved at build time, not at
   runtime, no external fetch survives into the sovereign offline artifact.
   ============================================================================ */

@import "/notebook/notebook.css";

/* GLASS CANON: no bright greens. The positive/"ok/done/in-band" tone is retoned from
   the emerald #10B981 to the cyan signal #00E5FF, so the canon stays navy-dominant with
   cyan as the single accent. (e-ink's black override is higher-specificity and still wins.) */
:root {
  --ok: #00E5FF;
  --correct: #54EFFF;
  --persistence-ok: #54EFFF;
  /* WCAG-AA RETONE: v1's error red #EF4444 composites to ~3.3:1 behind the
     save-failure chip's red wash on the rail glass — under AA for 12px chip text,
     and "NOT saved" must be legible exactly when it matters. Lifted to #FF8A8A
     (5.0:1 on the brightest composite, 8.3:1 on panel navy, 5.8:1 as a border).
     e-ink re-binds --err to ink black further down, so every theme clears AA. */
  --err: #FF8A8A;
  /* DEFINE the phantom tokens the v2 dialogs referenced via off-canon var() FALLBACKS
     (#e8eef7 / #9aa7bd / #00e5ff), so those dialogs inherit the real canon ramp instead. */
  --ink: var(--text, #F8FAFC);     /* body ink == canon text */
  --accent: var(--cyan, #00E5FF);  /* accent == the one signal */
  --field-1: rgba(10, 17, 40, .55);  /* a defined navy field, not an ad-hoc fallback */
  --field-2: rgba(15, 29, 58, .55);
  /* the one near-black ink used FOR text/glyphs that sit ON a cyan fill (cue-due
     pill, IO badge, AEIOUY letter, active find highlight). Tokenized so the
     dark-on-cyan contrast is a single, tunable value, not 4 scattered literals. */
  --on-cyan-ink: #06121f;
  /* DISPLAY-CONTROL HOOKS (UDL: multiple means of perception). The Settings
     cockpit writes these three on :root; the note-content rules below consume
     them. Defaults are IDENTITY values, so an untouched notebook renders
     exactly as it did before the hooks existed.
       --nb2-font-scale : multiplies the content font-size (1 = the 16px hero size)
       --nb2-line-space : multiplies the line-height / ruling cadence (1 = 28px)
       --nb2-font-body  : the content family (default = the canon Montserrat stack) */
  --nb2-font-scale: 1;
  --nb2-line-space: 1;
  --nb2-font-body: Montserrat, Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  /* Fluent Opening: water-like settle. Viscosity, then level. Not a bounce gag. */
  --nb-fluid: cubic-bezier(0.16, 1, 0.3, 1);
}

/* ─────────────── the TipTap editor as the Cornell notes surface ─────────────── */
/* The editor REPLACES v1's `.nb-fragments` list + `.nb-composer textarea`. It is
   the focal writing surface, so it carries the ruled-line Cornell background that
   lived on the v1 composer textarea (lines scroll with the text) and grows to
   fill the glowing notes card. */
.nb2-editor {
  /* the ONE derived ruling cadence every typeset rule shares: 28px at rest,
     stretched by the display-control hooks so text always rides the rule. */
  --nb2-rule: calc(28px * var(--nb2-font-scale, 1) * var(--nb2-line-space, 1));
  flex: 1 1 auto;
  min-height: 280px;
  border-radius: 8px;
  border: 1px solid var(--hair-strong);
  background:
    repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--nb2-rule) - 1px), rgba(159,179,200,.16) calc(var(--nb2-rule) - 1px), rgba(159,179,200,.16) var(--nb2-rule)) local,
    rgba(10,17,40,.5);
  background-position: 0 calc(var(--nb2-rule) / 2 - 1px), 0 0;
  overflow: auto;
  transition: border-color .12s ease, box-shadow .12s ease;
}
/* lines GUI toggle: hide the ruled background for plain paper (text keeps its 28px cadence).
   !important + e-ink selectors: the paper-mode sheet also sets background-image with
   !important on .nb2-editor; without this, turning lines back on leaves image:none. */
.nb2-editor.lines-off,
body.eink .nb2-editor.lines-off,
body:not(.eink-off) .nb2-editor.lines-off {
  background: rgba(10,17,40,.5) !important;
  background-image: none !important;
  background-position: 0 0 !important;
}
/* crisp focus ring when the editor (or any node inside) holds focus */
.nb2-editor:focus-within {
  border-color: var(--glass-edge);
  box-shadow: 0 0 0 2px rgba(0,229,255,.18), inset 0 0 18px rgba(84,239,255,.05);
}

/* the ProseMirror contenteditable surface itself. Family / size / leading all ride
   the display-control hooks (:root), so the cockpit can retype the working view;
   at the identity defaults this computes to the same Montserrat 16px/28px as ever. */
.nb2-editor .ProseMirror {
  font-family: var(--nb2-font-body, Montserrat, Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif);
  color: var(--text);
  font-size: calc(16px * var(--nb2-font-scale, 1));   /* the writing surface is the hero: the most generous copy on screen */
  line-height: var(--nb2-rule, 28px);                 /* matches the ruling cadence (text still rides the rule at any scale) */
  padding: 5px 13px 16px;
  min-height: 260px;
  outline: 0;                    /* the ring lives on .nb2-editor:focus-within */
  caret-color: var(--cyan);
  -webkit-font-smoothing: antialiased;
}
.nb2-editor .ProseMirror:focus { outline: 0; }

/* placeholder for the empty doc: driven by @tiptap/extension-placeholder, which
   emits `is-editor-empty` + a `data-placeholder` attr ("Type / for commands").
   The extension renders nothing visually on its own; this rule turns the attr
   into ghost text. If the attr is ever absent the rule simply shows nothing. */
.nb2-editor .ProseMirror p.is-editor-empty:first-child::before {
  content: attr(data-placeholder);
  color: var(--muted);
  float: left;
  height: 0;
  pointer-events: none;
}

/* block rhythm: paragraphs sit on the ruling, headings break it cleanly */
.nb2-editor .ProseMirror > * { margin: 0; }
.nb2-editor .ProseMirror > * + * { margin-top: 6px; }
.nb2-editor .ProseMirror p { margin: 0; }

/* headings, on-canon: cyan tick echo via weight, not a colored slab */
.nb2-editor .ProseMirror h1,
.nb2-editor .ProseMirror h2,
.nb2-editor .ProseMirror h3 {
  font-weight: 600;
  line-height: 1.3;
  margin: 10px 0 2px;
  color: var(--text);
  letter-spacing: .01em;
}
.nb2-editor .ProseMirror h1 { font-size: calc(23px * var(--nb2-font-scale, 1)); }
.nb2-editor .ProseMirror h2 { font-size: calc(19px * var(--nb2-font-scale, 1)); }
.nb2-editor .ProseMirror h3 { font-size: calc(16.5px * var(--nb2-font-scale, 1)); color: var(--cyan-glow); }

/* lists */
.nb2-editor .ProseMirror ul,
.nb2-editor .ProseMirror ol { margin: 4px 0; padding-left: 24px; }
.nb2-editor .ProseMirror li { margin: 2px 0; }
.nb2-editor .ProseMirror li > p { margin: 0; }
.nb2-editor .ProseMirror ul { list-style: none; }
.nb2-editor .ProseMirror ul > li { position: relative; }
.nb2-editor .ProseMirror ul > li::before {
  content: "•"; color: var(--cyan); position: absolute; left: -16px; top: 0;
}

/* task list (only present when the optional task-list extension is installed) */
.nb2-editor .ProseMirror ul[data-type="taskList"] { list-style: none; padding-left: 4px; }
.nb2-editor .ProseMirror ul[data-type="taskList"] > li { display: flex; gap: 9px; align-items: flex-start; }
.nb2-editor .ProseMirror ul[data-type="taskList"] > li::before { content: none; }
.nb2-editor .ProseMirror ul[data-type="taskList"] > li > label { flex: none; margin-top: 4px; }
.nb2-editor .ProseMirror ul[data-type="taskList"] input[type="checkbox"] { accent-color: var(--cyan); }
.nb2-editor .ProseMirror ul[data-type="taskList"] > li > div { flex: 1 1 auto; min-width: 0; }

/* inline code + fenced code block: on the navy ink, cyan-tinged */
.nb2-editor .ProseMirror code {
  font-family: ui-monospace, "Cascadia Code", "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: calc(12.5px * var(--nb2-font-scale, 1));
  background: rgba(0,229,255,.08);
  border: 1px solid var(--hair);
  border-radius: 5px;
  padding: 1px 5px;
  color: var(--cyan-glow);
}
.nb2-editor .ProseMirror pre {
  background: rgba(7,15,31,.55);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 11px 13px;
  margin: 8px 0;
  overflow-x: auto;
  line-height: 1.5;
}
.nb2-editor .ProseMirror pre code {
  background: transparent; border: 0; padding: 0; color: var(--text); font-size: calc(12.5px * var(--nb2-font-scale, 1));
}

/* blockquote: matches v1's fragment blockquote (cyan left rail, faint cyan wash) */
.nb2-editor .ProseMirror blockquote {
  margin: 8px 0;
  padding: 6px 12px;
  border-left: 3px solid var(--glass-edge);
  background: rgba(0,229,255,.05);
  border-radius: 0 6px 6px 0;
  color: var(--text);
}
.nb2-editor .ProseMirror blockquote p { margin: 0; }
.nb2-editor .ProseMirror cite[data-cite] {
  display: inline; color: var(--muted); font-size: calc(12px * var(--nb2-font-scale, 1)); font-style: normal;
}

/* links */
.nb2-editor .ProseMirror a { color: var(--cyan); text-decoration: underline; text-underline-offset: 2px; }

/* horizontal rule */
.nb2-editor .ProseMirror hr {
  border: 0; height: 1px; background: var(--hair-strong); margin: 12px 0;
}

/* marks */
.nb2-editor .ProseMirror strong { font-weight: 700; }
.nb2-editor .ProseMirror em { font-style: italic; }
.nb2-editor .ProseMirror s { text-decoration: line-through; color: var(--muted); }

/* custom capture nodes: photo + sketch (atomic blocks) */
.nb2-editor .ProseMirror figure.nb2-photo,
.nb2-editor .ProseMirror div.nb2-sketch {
  margin: 10px 0;
  border: 1px solid var(--hair);
  border-radius: 9px;
  background: rgba(10,17,40,.32);
  padding: 8px;
}
.nb2-editor .ProseMirror figure.nb2-photo img,
.nb2-editor .ProseMirror div.nb2-sketch svg {
  max-width: 100%; display: block; border-radius: 6px; margin: 0 auto;
}
.nb2-editor .ProseMirror figure.nb2-photo figcaption {
  color: var(--muted); font-size: calc(12px * var(--nb2-font-scale, 1)); margin-top: 6px; text-align: center;
}
.nb2-editor .ProseMirror figure.nb2-photo figcaption:empty { display: none; }

/* video embed: a block the note literally wraps around (16:9, responsive). The note
   text flows above and below it; the player streams from the provider, the notes stay local. */
.nb2-editor .ProseMirror figure.nb2-video { margin: 12px 0; max-width: 640px; }
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-frame {
  position: relative; width: 100%; aspect-ratio: 16 / 9;
  background: #000; border: 1px solid var(--hair); border-radius: 10px; overflow: hidden;
}
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-frame iframe {
  position: absolute; inset: 0; width: 100%; height: 100%; border: 0; display: block;
}
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-cap { margin-top: 6px; font-size: calc(12px * var(--nb2-font-scale, 1)); color: var(--muted); display: flex; gap: 14px; align-items: center; justify-content: center; flex-wrap: wrap; }
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-cap a { color: var(--muted); text-decoration: none; }
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-cap a:hover { color: var(--cyan-glow); }
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-transcript-btn,
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-watch-btn {
  font: inherit; font-size: calc(12px * var(--nb2-font-scale, 1)); color: var(--muted); background: none;
  border: 1px solid var(--hair); border-radius: 6px; padding: 2px 8px; cursor: pointer; margin-left: 6px;
}
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-transcript-btn:hover,
.nb2-editor .ProseMirror figure.nb2-video .nb2-video-watch-btn:hover { color: var(--text); border-color: var(--cyan-glow); }

/* Watch & Note: the currently-playing transcript line: a calm cyan "you are here" RAIL (the ONE
   signal), never a slab. This is a transient node decoration (nb2-watch-active), never serialized. */
.nb2-editor .ProseMirror > .nb2-watch-active {
  border-left: 2px solid var(--cyan-glow); margin-left: -12px; padding-left: 10px;
  background: linear-gradient(90deg, rgba(0, 229, 255, .07), transparent 62%);
  border-radius: 3px; transition: background .2s ease, border-color .2s ease;
}
/* "⌖ Jump to live": appears after you scroll away from the playing line; click re-engages follow. */
.nb2-watch-jump {
  position: fixed; bottom: 22px; right: 26px; z-index: 50;
  font: inherit; font-size: 12px; color: var(--cyan-glow);
  background: rgba(10, 17, 40, .94); border: 1px solid var(--cyan-glow);
  border-radius: 999px; padding: 6px 13px; cursor: pointer; box-shadow: 0 3px 12px rgba(0, 0, 0, .45);
}
.nb2-watch-jump:hover { color: var(--text); }
.nb2-watch-jump:focus-visible { outline: 2px solid var(--cyan-glow); outline-offset: 2px; }
body.eink .nb2-editor .ProseMirror > .nb2-watch-active { border-left-color: #000; background: rgba(0, 0, 0, .05); }
body.eink .nb2-watch-jump { color: #000; border-color: #000; background: #fff; box-shadow: none; }

/* ── SOURCE PANE: the watched video + its live transcript live HERE (a SOURCE you watch), kept OUT of
   the notepad. Shown only while watching; the editor beside it stays a clean Cornell surface. Click a
   transcript line to drop it into your notes. */
.nb2-source-pane { display: flex; flex-direction: column; min-height: 0; border: 1px solid var(--hair); border-radius: 10px; background: var(--navy-panel, var(--navy-deep, #0a1128)); overflow: hidden; }
.nb2-source-pane[hidden] { display: none; }
.nb2-src-head { display: flex; align-items: center; justify-content: space-between; padding: 6px 10px; border-bottom: 1px solid var(--hair); flex: none; }
.nb2-src-title { font-weight: 600; font-size: .82rem; letter-spacing: .02em; color: var(--muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.nb2-src-close { border: 1px solid var(--hair); background: transparent; color: var(--muted); border-radius: 6px; cursor: pointer; min-width: 44px; min-height: 44px; width: auto; height: auto; line-height: 1; flex: none; box-sizing: border-box; }
.nb2-src-close:hover { color: var(--text); border-color: var(--hair-strong); }
.nb2-src-fs { margin-left: auto; margin-right: 6px; border: 1px solid var(--hair); background: transparent; color: var(--muted); border-radius: 6px; cursor: pointer; padding: 3px 9px; font-size: .76rem; line-height: 1.3; white-space: nowrap; flex: none; }
.nb2-src-fs:hover, .nb2-src-fs[aria-pressed="true"] { color: var(--cyan); border-color: var(--cyan); }

/* FULL-SCREEN SOURCE (Zoom/YouTube-style, browser Fullscreen API — zero install): the source pane
   fills the screen, the video goes large, the transcript becomes a scrollable side rail. The
   click-to-cue / shift-click-to-note gestures keep working since the transcript is in the pane. */
#nb2-source-pane:fullscreen { background: #06121f; display: grid; grid-template-columns: 1fr minmax(300px, 32%); grid-template-rows: auto 1fr; grid-template-areas: "head head" "video transcript"; gap: 0; padding: 0; margin: 0; max-height: none; height: 100vh; width: 100vw; }
#nb2-source-pane:fullscreen .nb2-src-head { grid-area: head; padding: 12px 18px; background: rgba(0, 0, 0, .45); border-bottom: 1px solid var(--hair-strong); }
#nb2-source-pane:fullscreen .nb2-src-title { font-size: 1rem; color: var(--text); }
#nb2-source-pane:fullscreen .nb2-src-title::after { content: "  ·  click a transcript line → cue · shift-click → note"; color: var(--muted); font-weight: 400; }
#nb2-source-pane:fullscreen #nb2-src-video { grid-area: video; display: flex; align-items: center; justify-content: center; padding: 14px; background: #000; }
#nb2-source-pane:fullscreen #nb2-src-video iframe { width: 100%; height: auto; aspect-ratio: 16 / 9; max-height: calc(100vh - 80px); }
#nb2-source-pane:fullscreen #nb2-src-transcript { grid-area: transcript; max-height: none; height: 100%; overflow: auto; border-left: 1px solid var(--hair-strong); padding: 12px; }
.nb2-src-video { flex: none; background: #000; }
.nb2-src-video iframe { display: block; width: 100%; aspect-ratio: 16 / 9; border: 0; }
.nb2-source-pane--transcript-only .nb2-src-video { display: none !important; }
#nb2-source-pane:fullscreen.nb2-source-pane--transcript-only { grid-template-columns: 1fr; grid-template-areas: "head" "transcript"; }
#nb2-source-pane:fullscreen.nb2-source-pane--transcript-only #nb2-src-transcript { border-left: 0; }
.nb2-src-transcript { flex: 1 1 auto; overflow-y: auto; padding: 8px 6px; min-height: 0; overflow-anchor: none; }
.nb2-src-line { display: flex; gap: 8px; padding: 5px 8px; border-radius: 7px; cursor: pointer; color: var(--text); transition: background .12s ease; }
.nb2-src-line:hover { background: rgba(0, 229, 255, .06); }
.nb2-src-line .nb2-src-ts { flex: none; color: var(--cyan); font-variant-numeric: tabular-nums; font-size: .8rem; padding-top: .1em; }
.nb2-src-line .nb2-src-tx { flex: 1 1 auto; line-height: 1.45; }
.nb2-src-line.is-active { background: rgba(0, 229, 255, .12); box-shadow: inset 2px 0 0 var(--cyan); }
.nb2-src-line.is-active .nb2-src-tx { font-weight: 600; }   /* WCAG 1.4.1: weight as a redundant cue alongside the stripe */
/* a line left-clicked INTO the cues column: a persistent ✓ + a brief flash so the tag registers. */
.nb2-src-line.is-cued .nb2-src-tx::after { content: " ✓"; color: var(--cyan); font-weight: 600; }
.nb2-src-line.is-noted .nb2-src-tx::before { content: "✎ "; color: var(--muted); font-weight: 600; }
.nb2-src-line.just-cued { animation: nb2-src-cued-flash .75s ease; }
@keyframes nb2-src-cued-flash { from { background: rgba(0, 229, 255, .30); } to { background: transparent; } }

/* right-click-a-note-selection menu: ◆ Send to cue / ❡ Send to summary */
.nb2-ctx-menu { position: fixed; z-index: 2147483600; display: flex; flex-direction: column; min-width: 172px; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 9px; box-shadow: 0 10px 32px rgba(0, 0, 0, .45); padding: 5px; }
.nb2-ctx-item { display: flex; align-items: center; width: 100%; text-align: left; background: transparent; border: 0; color: var(--text); padding: 8px 12px; border-radius: 6px; font-size: 13.5px; cursor: pointer; }
.nb2-ctx-item:hover, .nb2-ctx-item:focus { background: rgba(0, 229, 255, .10); outline: none; }
.nb2-ctx-glyph { display: inline-block; width: 1.5em; text-align: center; color: var(--cyan); font-weight: 700; margin-right: 6px; }
/* own-cue TYPE accents: ? open question · + needs elaboration · ★ key/favorite · 🐕 feynman */
.nb-cue--question .nb-cue-mark { color: var(--cyan); font-weight: 700; }
.nb-cue--elaborate .nb-cue-mark { color: var(--acronym, #FFD93D); font-weight: 700; }
.nb-cue--key .nb-cue-mark { color: var(--cyan-glow); font-weight: 700; }
.nb-cue--feynman .nb-cue-mark { filter: saturate(1.1); }
/* FADING CUES (the Back-to-the-Future effect): a cue's opacity tracks its FSRS retrievability — as
   the memory fades, the cue fades. Hover/focus reveals a faded cue so it's always readable + clickable;
   a faded cue gets a dashed edge so "ghost" reads as a state, not a render bug. */
.nb-cue { transition: opacity 1.4s ease; }
.nb-cue--fading:hover, .nb-cue--fading:focus-within { opacity: 1 !important; }

/* SELECTION BUBBLE — the floating "make a cue from what you wrote" toolbar (Medium/Notion-style).
   A compact pill of glyph buttons that floats above a text selection in the editor. */
.nb2-sel-bubble { position: fixed; z-index: 2147483601; display: flex; gap: 2px; padding: 4px; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 10px; box-shadow: 0 8px 26px rgba(0, 0, 0, .5); animation: nb2-sel-pop .12s ease-out; }
@keyframes nb2-sel-pop { from { opacity: 0; transform: translateY(3px) scale(.96); } to { opacity: 1; transform: none; } }
.nb2-sel-btn { display: inline-flex; align-items: center; justify-content: center; width: 30px; height: 30px; background: transparent; border: 0; border-radius: 7px; color: var(--cyan); font-size: 15px; font-weight: 700; line-height: 1; cursor: pointer; transition: background .1s, transform .1s; }
.nb2-sel-btn:hover, .nb2-sel-btn:focus { background: rgba(0, 229, 255, .14); outline: none; transform: translateY(-1px); }
.nb2-sel-btn:active { transform: translateY(0); }

/* COVER & RECITE (Cue Mode): the cover sits over the notes and blurs them behind it via
   backdrop-filter — read your cues, recite from memory, click to reveal. */
body.nb2-cue-mode .nb-notes { position: relative; }
.nb2-cue-cover { position: absolute; inset: 0; z-index: 6; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px; text-align: center; padding: 24px; cursor: pointer; border-radius: 12px; backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px); background: rgba(13, 24, 46, .44); border: 1px dashed var(--hair-strong, #2a3f6b); animation: nb2-sel-pop .14s ease-out; }
.nb2-cue-cover:hover, .nb2-cue-cover:focus { background: rgba(13, 24, 46, .34); outline: none; }
.nb2-cue-cover-icon { font-size: 30px; line-height: 1; }
.nb2-cue-cover-hint { font-size: 16px; font-weight: 700; color: var(--text); }
.nb2-cue-cover-sub { font-size: 12.5px; color: var(--muted); max-width: 320px; line-height: 1.5; }

/* CONNECT CANVAS (Chunk) — draggable cue/note nodes wired with labeled relationship edges. */
.nb2-board-seg { display: inline-flex; gap: 2px; padding: 3px; margin-bottom: 8px; background: rgba(10, 18, 38, .5); border: 1px solid var(--hair, #1d2f55); border-radius: 9px; }
.nb2-board-segbtn { background: transparent; border: 0; color: var(--muted); font-size: 12.5px; font-weight: 600; padding: 5px 14px; border-radius: 6px; cursor: pointer; }
.nb2-board-segbtn.is-on { background: rgba(0, 229, 255, .14); color: var(--cyan); }
.nb2-connect-host { position: relative; overflow: auto; max-height: 56vh; background: rgba(10, 18, 38, .4); border: 1px solid var(--hair, #1d2f55); border-radius: 12px; }
.nb2-cnode--page { border-left-color: #9ED8A6; }
.nb2-cnode--page.is-active { box-shadow: 0 0 0 2px var(--cyan, #54efff), 0 4px 14px rgba(0, 0, 0, .32); }
.nb2-connect { position: relative; }
.nb2-connect-edges { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; overflow: visible; z-index: 1; }
.nb2-cedge { fill: none; stroke: var(--cyan, #54efff); stroke-width: 2; opacity: .55; }
.nb2-cedge--rubber { stroke-dasharray: 5 4; opacity: .85; }
.nb2-cnode { position: absolute; z-index: 2; width: 168px; min-height: 46px; padding: 9px 11px; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-left: 3px solid var(--cyan, #54efff); border-radius: 9px; box-shadow: 0 4px 14px rgba(0, 0, 0, .32); cursor: grab; user-select: none; touch-action: none; }
.nb2-cnode.is-dragging { cursor: grabbing; box-shadow: 0 8px 22px rgba(0, 0, 0, .5); z-index: 4; }
.nb2-cnode-text { font-size: 12.5px; line-height: 1.4; color: var(--text); pointer-events: none; }
.nb2-cnode-handle { position: absolute; right: -9px; top: 50%; transform: translateY(-50%); width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; border-radius: 50%; background: var(--cyan, #54efff); color: #06121f; font-size: 10px; cursor: crosshair; box-shadow: 0 1px 4px rgba(0, 0, 0, .4); }
.nb2-cnode--elaborate { border-left-color: var(--acronym, #FFD93D); }
.nb2-cnode--key { border-left-color: var(--cyan-glow, #aef3ff); }
.nb2-cnode--feynman { border-left-color: #FF9EC4; }
/* Visual notes on the canvas: a picture/drawing renders as a thumbnail; the collapse toggle shrinks
   it back to a compact title chip so a big image never dominates the board. The thumb is
   pointer-events:none so dragging the picture moves the card (the toggle re-enables its own clicks). */
.nb2-cnode--visual { padding-top: 8px; }
.nb2-cnode-thumb { width: 100%; height: 104px; margin: 0 0 6px; border-radius: 7px; overflow: hidden; background: rgba(8, 18, 31, .5); border: 1px solid var(--hair-strong, #2a3f6b); display: flex; align-items: center; justify-content: center; pointer-events: none; }
.nb2-cnode-thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.nb2-cnode-thumb--svg { background: #fff; }
.nb2-cnode-thumb--svg img { object-fit: contain; padding: 4px; }
.nb2-cnode.is-collapsed { min-height: 0; }
.nb2-cnode.is-collapsed .nb2-cnode-text { font-size: 12px; opacity: .92; padding-right: 18px; }
.nb2-cnode-collapse { position: absolute; top: 4px; right: 6px; width: 18px; height: 18px; display: flex; align-items: center; justify-content: center; padding: 0; border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 5px; background: var(--navy-panel, #13254a); color: var(--cyan, #54efff); font-size: 10px; line-height: 1; cursor: pointer; pointer-events: auto; z-index: 3; }
.nb2-cnode-collapse:hover { background: rgba(0, 229, 255, .14); }
/* Expose panel: commit a note to a trusted LearnSuite destination (trusted sites/classes gate). */
.nb2-expose-lede { font-size: 13px; line-height: 1.5; color: var(--text-dim, #9fb2d6); margin: 0 0 12px; }
.nb2-expose-empty { font-size: 13px; line-height: 1.5; color: var(--text-dim, #9fb2d6); padding: 12px; border: 1px dashed var(--hair-strong, #2a3f6b); border-radius: 8px; }
.nb2-expose-badge { display: inline-block; font-size: 12px; color: var(--correct, #54EFFF); background: rgba(84, 239, 255, .08); border: 1px solid rgba(84, 239, 255, .28); border-radius: 8px; padding: 4px 9px; margin: 0 0 12px; }
.nb2-expose-row { display: flex; align-items: center; gap: 10px; margin: 0 0 10px; }
.nb2-expose-lbl { width: 84px; font-size: 12.5px; color: var(--text-dim, #9fb2d6); }
.nb2-expose-sel { flex: 1; padding: 7px 9px; font-size: 13px; color: var(--text); background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 7px; }
.nb2-expose-msg { font-size: 12.5px; line-height: 1.45; color: var(--acronym, #FFD93D); min-height: 18px; margin: 4px 0 10px; }
.nb2-expose-commit.is-armed { background: var(--acronym, #FFD93D); color: #1a1400; border-color: var(--acronym, #FFD93D); }
.nb2-expose-prior { margin-top: 16px; padding-top: 12px; border-top: 1px solid var(--hair-strong, #2a3f6b); }
.nb2-expose-prior-h { font-size: 11px; text-transform: uppercase; letter-spacing: .04em; color: var(--text-dim, #9fb2d6); margin: 0 0 6px; }
.nb2-expose-prior-row { font-size: 12.5px; color: var(--correct, #54EFFF); padding: 2px 0; }
.nb2-cedge-label { position: absolute; z-index: 3; transform: translate(-50%, -50%); padding: 2px 8px; font-size: 11px; font-weight: 600; color: var(--cyan); background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 10px; cursor: pointer; white-space: nowrap; }
.nb2-cedge-label:hover { background: rgba(0, 229, 255, .14); }

/* Cue ELABORATION drawer — a dynamic cue's context: note + link + image embed. */
.nb2-cue-elab { margin-top: 8px; padding: 8px; background: rgba(10, 18, 38, .45); border: 1px solid var(--hair, #1d2f55); border-radius: 8px; display: flex; flex-direction: column; gap: 6px; }
.nb2-cue-elab-note { width: 100%; resize: vertical; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 6px; color: var(--text); font: inherit; font-size: 12.5px; padding: 6px 8px; box-sizing: border-box; }
.nb2-cue-elab-row { display: flex; gap: 6px; align-items: center; }
.nb2-cue-elab-link { flex: 1; min-width: 0; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 6px; color: var(--text); font: inherit; font-size: 12px; padding: 5px 8px; box-sizing: border-box; }
.nb2-cue-elab-img { position: relative; margin-top: 2px; }
.nb2-cue-elab-img img { max-width: 100%; max-height: 160px; border-radius: 6px; display: block; }
.nb2-cue-elab-imgrm { position: absolute; top: 4px; right: 4px; width: 20px; height: 20px; border: 0; border-radius: 50%; background: rgba(0, 0, 0, .6); color: #fff; cursor: pointer; font-size: 11px; line-height: 1; }
.nb-cue-act.is-on { background: rgba(0, 229, 255, .16); }

/* CAPABILITY TIERS panel ("bring your own chromium") — Core / Hear / See-Control cards with a
   status badge + opt-in. */
.nb2-caps-list { display: flex; flex-direction: column; gap: 10px; margin-top: 6px; }
.nb2-caps-card { padding: 11px 12px; background: rgba(10, 18, 38, .5); border: 1px solid var(--hair, #1d2f55); border-radius: 10px; }
.nb2-caps-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; }
.nb2-caps-title { font-weight: 700; font-size: 13.5px; color: var(--text); }
.nb2-caps-badge { flex: none; font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 20px; border: 1px solid var(--hair-strong, #2a3f6b); color: var(--muted); }
.nb2-caps--ok { color: var(--correct, #54EFFF); border-color: var(--correct, #54EFFF); }
.nb2-caps--ready { color: var(--cyan, #54efff); border-color: var(--cyan, #54efff); }
.nb2-caps--probing { color: var(--muted); }
.nb2-caps--off { color: var(--muted); }
.nb2-caps-status { font-size: 12px; color: var(--text); margin-top: 5px; }
.nb2-caps-blurb { font-size: 11.5px; color: var(--muted); line-height: 1.45; margin-top: 4px; }
.nb2-caps-act { margin-top: 9px; }
.nb2-caps-cmd { display: inline-block; margin-top: 8px; padding: 4px 8px; background: rgba(0, 0, 0, .35); border: 1px solid var(--hair, #1d2f55); border-radius: 6px; font-family: var(--mono, monospace); font-size: 11px; color: var(--cyan, #54efff); user-select: all; }
.nb2-caps-recheck { margin-top: 9px; margin-left: 8px; }

/* LIVE hear + see control (the flagship, inside the 🎧 Hear capability card).
   The button text + the honest state line carry the meaning — color is never the
   only signal (WCAG 1.4.1): the "on" state also flips the button label to Stop and
   the badge text to "Live". */
.nb2-livelisten { margin-top: 10px; padding-top: 9px; border-top: 1px solid var(--hair, #1d2f55); }
.nb2-livelisten-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.nb2-livelisten-btn.nb2-livelisten--on { border-color: var(--cyan, #54efff); color: var(--cyan, #54efff); }
.nb2-livelisten-badge { font-size: 11px; font-weight: 700; padding: 2px 9px; border-radius: 20px; border: 1px solid var(--hair-strong, #2a3f6b); color: var(--muted); }
.nb2-livelisten-badge[data-on="true"] { color: var(--cyan, #54efff); border-color: var(--cyan, #54efff); }
.nb2-livelisten-badge[data-on="true"]::before { content: "● "; }   /* redundant non-color cue for "live" */
.nb2-livelisten-state { margin-top: 7px; }
.nb2-livelisten-see { display: flex; align-items: flex-start; gap: 7px; margin-top: 9px; font-size: 11.5px; color: var(--muted); line-height: 1.45; cursor: pointer; }
.nb2-livelisten-see input { margin-top: 2px; accent-color: var(--cyan, #54efff); flex: none; }
.nb2-livelisten-mic { margin-top: 9px; }

/* RESOURCES + light-crawl panel — paste a page → discovered resources → pull them in. */
.nb2-res { max-width: 560px; width: min(560px, 92vw); }
.nb2-res-input { width: 100%; box-sizing: border-box; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 8px; color: var(--text); font: inherit; font-size: 12.5px; padding: 8px 10px; resize: vertical; margin: 4px 0 8px; }
.nb2-res-found { margin: 8px 0; }
.nb2-res-foundh { font-size: 12px; color: var(--muted); margin-bottom: 6px; font-weight: 600; }
.nb2-res-row { display: flex; align-items: center; gap: 8px; padding: 5px 4px; font-size: 12.5px; cursor: pointer; border-radius: 6px; }
.nb2-res-row:hover { background: rgba(0, 229, 255, .06); }
.nb2-res-ic { flex: none; }
.nb2-res-tx { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--text); }
.nb2-res-add { margin-top: 8px; }
.nb2-res-h { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted, #9FB3C8); margin: 16px 0 8px; padding-bottom: 5px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.08)); }
.nb2-res-list { display: flex; flex-direction: column; gap: 4px; }
.nb2-res-item { display: flex; align-items: center; gap: 8px; }
.nb2-res-link { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--cyan, #54efff); text-decoration: none; font-size: 12.5px; padding: 5px 0; }
.nb2-res-link:hover { text-decoration: underline; }
.nb2-res-rm { flex: none; width: 22px; height: 22px; border: 0; border-radius: 6px; background: transparent; color: var(--muted, #9FB3C8); cursor: pointer; }
.nb2-res-rm:hover { background: rgba(255, 107, 107, .15); color: var(--incorrect, #FF6B6B); }
.nb2-res-static { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 12.5px; color: var(--text, #F8FAFC); padding: 5px 0; }
.nb2-res-copy { flex: none; }
.nb2-res-bcrawl { padding: 9px 10px; margin-bottom: 10px; background: rgba(0, 229, 255, .05); border: 1px solid var(--cyan, #54efff); border-radius: 9px; }
.nb2-res-act { margin-top: 5px; }

/* PAGE NAVIGATION (pager) — the notebook's notes are its titled pages; this bar flips through them. */
.nb-notes-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, auto);
  grid-template-areas: "pager cues protect" "caps caps caps";
  gap: 8px 10px;
  align-items: center;
  min-width: 0;
}
#nb2-pager { grid-area: pager; }
#nb-cues-door { grid-area: cues; }
.nb2-notes-heading { grid-area: protect; justify-self: end; min-width: 0; }
.nb-notes-head .nb-capture-bar { grid-area: caps; min-width: 0; }
.nb2-pager { position: relative; display: flex; align-items: center; gap: 6px; padding: 2px 4px; margin-bottom: 0; background: transparent; border: 1px solid var(--hair, #1d2f55); border-radius: 9px; font-size: 12.5px; min-width: 0; }
.nb2-pager-caret { color: var(--muted, #9FB3C8); font-size: 9px; flex: none; transition: color .15s ease; }
.nb2-pager-mid:hover .nb2-pager-caret, .nb2-pager-mid[aria-expanded="true"] .nb2-pager-caret { color: var(--cyan, #54efff); }
/* the page quick-switcher dropdown (title + content lookup → jump straight to a page) */
.nb2-pagejump { position: absolute; z-index: 60; top: calc(100% + 5px); left: 8px; right: 8px; max-width: 460px; background: var(--navy-panel, #13254a); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 11px; box-shadow: 0 18px 44px -12px rgba(0, 0, 0, .66); padding: 8px; }
.nb2-pagejump-input { width: 100%; box-sizing: border-box; font: inherit; font-size: 13px; color: var(--text, #F8FAFC); background: rgba(10, 17, 40, .6); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 8px; padding: 8px 10px; margin-bottom: 6px; }
.nb2-pagejump-input:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 1px; border-color: var(--cyan, #54efff); }
.nb2-pagejump-list { display: flex; flex-direction: column; gap: 2px; max-height: 46vh; overflow-y: auto; }
.nb2-pagejump-row { display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: transparent; border: 0; border-radius: 8px; padding: 7px 9px; cursor: pointer; color: var(--text, #F8FAFC); }
.nb2-pagejump-row.is-sel { background: rgba(0, 229, 255, .1); }
.nb2-pagejump-row.is-active .nb2-pagejump-title { color: var(--cyan, #54efff); }
.nb2-pagejump-num { flex: none; width: 20px; text-align: center; font-size: 11px; color: var(--muted, #9FB3C8); border: 1px solid var(--hair, #24365f); border-radius: 5px; padding: 1px 0; }
.nb2-pagejump-textwrap { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.nb2-pagejump-title { font-size: 13px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-pagejump-snip { font-size: 11px; color: var(--muted, #9FB3C8); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-pagejump-here { flex: none; font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; color: var(--cyan, #54efff); }
.nb2-pagejump-empty { padding: 10px; font-size: 12px; color: var(--muted, #9FB3C8); text-align: center; }
.nb2-pager-nav { flex: none; width: 44px; height: 44px; border: 1px solid var(--hair-strong, #2a3f6b); background: transparent; color: var(--text, #F8FAFC); border-radius: 6px; cursor: pointer; line-height: 1; }
.nb2-pager-nav:hover:not(:disabled) { border-color: var(--cyan, #54efff); color: var(--cyan, #54efff); }
.nb2-pager-nav:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 2px; }
.nb2-pager-nav:disabled { opacity: .32; cursor: default; }
.nb2-pager-mid { display: flex; align-items: center; gap: 6px; flex: none; min-width: 0; min-height: 44px; background: transparent; border: 0; color: inherit; font: inherit; text-align: left; cursor: pointer; padding: 4px 6px; }
.nb2-pager-count { font-weight: 700; color: var(--text, #F8FAFC); white-space: nowrap; }
.nb2-page-title-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 44px; align-items: center; gap: 4px; flex: 1 1 180px; min-width: 120px; height: 44px; }
.nb2-pager-title,
.nb2-page-title-input { width: 100%; height: 44px; min-width: 0; box-sizing: border-box; border: 1px solid transparent; border-radius: 5px; padding: 4px 7px; background: transparent; color: var(--text, #F8FAFC); font: inherit; font-weight: 650; text-align: left; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-pager-title { cursor: text; }
.nb2-pager-title:hover { border-color: var(--hair-strong, #2a3f6b); color: var(--cyan, #54efff); }
.nb2-pager-title:focus-visible,
.nb2-page-title-input:focus-visible,
.nb2-page-title-edit:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 1px; }
.nb2-page-title-input { border-color: var(--cyan, #54efff); background: rgba(10, 17, 40, .62); }
.nb2-page-title-edit { width: 44px; height: 44px; padding: 0; border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 5px; background: transparent; color: var(--muted, #9FB3C8); font: inherit; font-size: 14px; cursor: pointer; }
.nb2-page-title-edit:hover { border-color: var(--cyan, #54efff); color: var(--cyan, #54efff); }
.nb2-pager-add { flex: none; min-height: 44px; border: 1px solid var(--cyan, #54efff); background: transparent; color: var(--cyan, #54efff); border-radius: 7px; padding: 6px 12px; font-size: 12px; font-weight: 600; cursor: pointer; white-space: nowrap; }
.nb2-pager-add:hover { background: rgba(0, 229, 255, .12); }
.nb2-pager-add:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 2px; }
@media (max-width: 560px) {
  .nb-notes-head {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "pager" "cues" "protect" "caps";
    align-items: stretch;
  }
  .nb2-notes-heading { justify-self: stretch; }
  .nb2-pager { flex-wrap: wrap; }
  .nb2-page-title-wrap { order: 5; flex-basis: 100%; min-width: 0; }
}
@media (pointer: coarse) {
  .nb2-page-title-wrap { grid-template-columns: minmax(0, 1fr) 44px; height: 44px; }
  .nb2-pager-title, .nb2-page-title-input, .nb2-page-title-edit { height: 44px; }
  .nb2-page-title-edit { width: 44px; }
  .nb2-pager-nav { width: 44px; height: 44px; }
  .nb2-pager-mid { min-height: 44px; }
  .nb2-pager-add { min-height: 44px; }
}

/* KNOWLEDGE TTL — the retention-degradation clock at the top of the cues column: a decay ring +
   state + nudge. Fresh (cyan) -> Fading (amber) -> Cold (red) -> Locked in (ice-cyan). */
.nb2-ttl-chip { display: flex; align-items: center; gap: 9px; padding: 7px 9px; margin: 6px 0 8px; background: rgba(10, 18, 38, .5); border: 1px solid var(--hair, #1d2f55); border-left: 3px solid var(--cyan, #54efff); border-radius: 9px; }
.nb2-ttl--fading { border-left-color: var(--acronym, #FFD93D); }
.nb2-ttl--cold { border-left-color: var(--incorrect, #FF6B6B); }
.nb2-ttl--synth { border-left-color: var(--correct, #54EFFF); }
.nb2-ttl-ring { width: 26px; height: 26px; flex: none; }
.nb2-ttl-ring-bg { fill: none; stroke: rgba(159, 179, 200, .22); stroke-width: 3; }
.nb2-ttl-ring-fg { fill: none; stroke-width: 3; stroke-linecap: round; transition: stroke-dashoffset .5s ease; }
.nb2-ttl-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.nb2-ttl-label { font-size: 12px; font-weight: 700; letter-spacing: .01em; }
.nb2-ttl-sub { font-size: 11px; color: var(--muted); line-height: 1.35; }
.nb2-ttl-act { flex: none; align-self: center; background: transparent; border: 1px solid var(--cyan, #54efff); color: var(--cyan, #54efff); border-radius: 7px; font-size: 11px; font-weight: 600; padding: 4px 8px; cursor: pointer; white-space: nowrap; }
.nb2-ttl-act:hover { background: rgba(0, 229, 255, .12); }

/* NO CLANKER — the proud AI-free stance. The AI study partner rail is hidden entirely (renderPartner
   also hides it; this is belt-and-suspenders so it never flashes on boot). */
body.nb2-no-clanker #nb2-partner { display: none !important; }
.nb2-noclanker { border: 1px solid var(--cyan, #54efff); border-radius: 9px; background: rgba(0, 229, 255, .06); padding: 10px; margin-bottom: 4px; }
.nb2-noclanker .nb2-ai-opt-title { color: var(--cyan); font-weight: 700; }

/* CLANKER MODE spectrum — No / Local / Cloud, the headline AI choice. */
.nb2-clanker-seg { display: flex; gap: 5px; margin: 8px 0 4px; flex-wrap: wrap; }
.nb2-clanker-btn { flex: 1; min-width: 112px; padding: 10px; background: rgba(10, 18, 38, .5); border: 1px solid var(--hair-strong, #2a3f6b); border-radius: 9px; color: var(--text); font-size: 13px; font-weight: 600; cursor: pointer; text-align: center; }
.nb2-clanker-btn:hover { border-color: var(--cyan, #54efff); }
.nb2-clanker-btn.is-on { background: rgba(0, 229, 255, .12); border-color: var(--cyan, #54efff); color: var(--cyan, #54efff); }
.nb2-clanker-blurb { margin-bottom: 8px; }
.nb2-src-empty { color: var(--muted); padding: 14px 10px; font-size: .85rem; line-height: 1.5; }
body.eink .nb2-src-line.is-active { background: rgba(0, 0, 0, .06); box-shadow: inset 2px 0 0 #000; }
body.eink .nb2-src-line .nb2-src-ts { color: #000; }

/* ── LearnOS class ATTACH: consent banner (a class wants to attach) + the "attached" badge ── */
.nb2-attach-consent { position: fixed; top: 14px; left: 50%; transform: translateX(-50%); z-index: 200; display: flex; align-items: center; gap: 14px; max-width: 560px; padding: 10px 14px; border: 1px solid var(--cyan); border-radius: 10px; background: var(--navy-panel, var(--navy-deep, #0a1128)); box-shadow: 0 6px 24px rgba(0,0,0,.5), 0 0 14px rgba(0,229,255,.18); color: var(--text); font-size: .9rem; }
.nb2-attach-msg { flex: 1 1 auto; line-height: 1.4; }
.nb2-attach-acts { flex: none; display: flex; gap: 8px; }
.nb2-attach-allow, .nb2-attach-deny { font: inherit; border-radius: 7px; padding: 6px 14px; cursor: pointer; border: 1px solid var(--hair); background: transparent; color: var(--text); }
.nb2-attach-allow { border-color: var(--cyan); background: rgba(0,229,255,.10); font-weight: 600; }
.nb2-attach-allow:hover { background: rgba(0,229,255,.18); }
.nb2-attach-deny:hover { border-color: var(--hair-strong); }
.nb2-attach-badge { position: fixed; bottom: 22px; left: 26px; z-index: 50; font: inherit; font-size: 12px; color: var(--cyan-glow); background: rgba(10,17,40,.94); border: 1px solid var(--cyan-glow); border-radius: 999px; padding: 6px 13px; cursor: pointer; box-shadow: 0 3px 12px rgba(0,0,0,.45); }
.nb2-attach-badge:hover { color: var(--text); }
body.eink .nb2-attach-consent { background: #fff; color: #000; border-color: #000; box-shadow: none; }
body.eink .nb2-attach-badge { color: #000; background: #fff; border-color: #000; box-shadow: none; }

/* ── CHILD-SAFETY: neutral age screen + parental-consent modal (nb_consent) ── */
.nb2-consent-overlay { position: fixed; inset: 0; z-index: 400; display: flex; align-items: center; justify-content: center; padding: 20px; background: rgba(4,8,20,.42); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.nb2-consent-card { width: 100%; max-width: 460px; max-height: calc(100vh - 40px); overflow-y: auto; display: flex; flex-direction: column; gap: 12px; padding: 22px 22px 18px; border: 1px solid var(--hair); border-left: 3px solid var(--cyan); border-radius: 14px; background: color-mix(in srgb, var(--navy-panel, var(--navy-deep, #0a1128)) 72%, transparent); backdrop-filter: blur(10px) saturate(1.06); -webkit-backdrop-filter: blur(10px) saturate(1.06); box-shadow: inset 0 1px 0 var(--hair); color: var(--text); font-size: .92rem; }
.nb2-consent-title { margin: 0; font-size: 1.15rem; font-weight: 700; color: var(--text); }
.nb2-consent-lede { margin: 0; line-height: 1.5; color: var(--text-soft, var(--text)); }
.nb2-consent-field { display: flex; flex-direction: column; gap: 5px; }
.nb2-consent-flabel { font-size: .86rem; font-weight: 600; color: var(--text); }
.nb2-consent-input { font: inherit; min-height: 44px; padding: 10px 12px; border: 1px solid var(--hair, rgba(255,255,255,.2)); border-radius: 8px; background: rgba(0,0,0,.22); color: var(--text); box-sizing: border-box; }
.nb2-consent-input:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; border-color: var(--cyan); }
.nb2-consent-disclosure { padding: 11px 13px; border: 1px solid var(--hair, rgba(255,255,255,.16)); border-left: 3px solid var(--cyan); border-radius: 8px; background: transparent; line-height: 1.5; }
.nb2-consent-dhead { display: block; margin-bottom: 4px; }
.nb2-consent-list { margin: 4px 0 6px; padding-left: 20px; }
.nb2-consent-list li { margin: 2px 0; }
.nb2-consent-fine { margin: 6px 0 0; font-size: .82rem; color: var(--text-mute, var(--text-soft, #9fb0d0)); line-height: 1.45; }
.nb2-consent-check { display: flex; gap: 9px; align-items: flex-start; line-height: 1.45; cursor: pointer; min-height: 44px; }
.nb2-consent-check input { margin-top: 3px; flex: none; min-width: 20px; min-height: 20px; }
.nb2-consent-err { margin: 0; color: var(--incorrect, #FF6B6B); font-size: .86rem; font-weight: 600; }
.nb2-consent-acts { display: flex; justify-content: flex-end; gap: 9px; margin-top: 4px; flex-wrap: wrap; }
.nb2-consent-acts .nb-btn,
.nb2-consent-firstrun-acts .nb-btn {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}
.nb2-consent-skip { opacity: .9; }
/* one-time first-run notice — receded atrium glass, never a cyan flood */
.nb2-consent-firstrun { position: static; z-index: 2; display: flex; align-items: center; gap: 16px; max-width: 520px; width: 100%; margin: 32px auto 0; padding: 12px 14px; border: 1px solid var(--hair); border-left: 3px solid var(--cyan); border-radius: var(--radius); background: color-mix(in srgb, var(--navy-panel, #0F1D3A) 62%, transparent); backdrop-filter: blur(10px) saturate(1.08); -webkit-backdrop-filter: blur(10px) saturate(1.08); box-shadow: inset 0 1px 0 var(--hair); color: var(--text); font-size: 14px; }
.nb2-consent-firstrun-msg { flex: 1 1 auto; line-height: 1.45; color: var(--muted); }
.nb2-consent-firstrun-acts { flex: none; display: flex; gap: 10px; }
.nb2-consent-firstrun.is-min { max-width: max-content; width: auto; gap: 0; margin-top: 20px; padding: 4px 6px 4px 10px; min-height: 44px; cursor: pointer; }
.nb2-consent-firstrun.is-min .nb2-consent-firstrun-msg { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.nb2-consent-firstrun.is-min .nb2-consent-later { display: none; }
.nb2-consent-firstrun.is-min .nb2-consent-firstrun-acts { gap: 0; }
.nb2-consent-firstrun.is-min:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
@media (max-width: 480px) { .nb2-consent-firstrun { flex-direction: column; align-items: stretch; } .nb2-consent-firstrun-acts { justify-content: flex-end; } .nb2-consent-firstrun.is-min { flex-direction: row; align-items: center; width: auto; } }
@media (prefers-reduced-motion: reduce) {
  .nb2-consent-overlay, .nb2-consent-card, .nb2-consent-firstrun {
    backdrop-filter: none; -webkit-backdrop-filter: none;
  }
}
body.eink .nb2-consent-overlay { background: rgba(255,255,255,.85); backdrop-filter: none; -webkit-backdrop-filter: none; }
body.eink .nb2-consent-card, body.eink .nb2-consent-firstrun { background: #fff; color: #000; border-color: #000; box-shadow: none; backdrop-filter: none; -webkit-backdrop-filter: none; }
body.eink .nb2-consent-firstrun { backdrop-filter: none; -webkit-backdrop-filter: none; }
body.eink .nb2-consent-input { background: #fff; color: #000; border-color: #000; }
body.eink .nb2-consent-disclosure { background: #f4f4f4; border-color: #000; border-left-color: #000; }

/* Watch owns an explicit nested notes grid. The outer workspace grid keeps
   Pages/Cues/Summary tracks; this inner grid keeps persistence/capture, source,
   editor/transcript, and View-owned details out of implicit rows. */
body.nb2-watching .nb-notes {
  grid-area: notes;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(250px, 32%);
  grid-template-areas:
    "pager pager"
    "workspacehead workspacehead"
    "vhead vhead"
    "video video"
    "notes transcript"
    "status status"
    "desk desk";
  grid-template-rows: auto auto auto auto minmax(220px, 50vh) auto auto;
  gap: 12px;
  min-width: 0;
  max-height: none;
}
body.nb2-watching.nb-view-note-details-hidden .nb-notes {
  grid-template-areas: "pager pager" "workspacehead workspacehead" "vhead vhead" "video video" "notes transcript" "desk desk";
  grid-template-rows: auto auto auto auto minmax(220px, 50vh) auto;
}
body.nb2-watching #nb2-pager { grid-area: pager; margin-bottom: 0; }
body.nb2-watching #nb2-source-pane { display: contents; }
body.nb2-watching .nb2-source-pane { border: 0; background: transparent; overflow: visible; }
body.nb2-watching .nb-notes-head { grid-area: workspacehead; display: grid; }
body.nb2-watching .nb2-status-bar { grid-area: status; }
body.nb2-watching #nb-desk-substrate { grid-area: desk; margin-top: 0; }
body.nb2-watching .nb2-src-head { grid-area: vhead; display: flex; align-items: center; justify-content: space-between; padding: 2px 6px; }
body.nb2-watching #nb2-src-video { grid-area: video; display: flex; justify-content: center; align-items: center; background: transparent; padding: 4px 0; min-height: 0; }
body.nb2-watching #nb2-src-video iframe { width: auto; max-width: 100%; height: min(34vh, 42vw); aspect-ratio: 16 / 9; border-radius: 10px; }
body.nb2-watching #nb2-editor { grid-area: notes; min-height: 0; }
body.nb2-watching #nb2-src-transcript { grid-area: transcript; min-height: 0; max-height: none; border: 1px solid var(--hair); border-radius: 10px; }
body.nb2-watching .nb-cues { min-height: 0; overflow-y: auto; }
body.nb2-watching .nb2-search, body.nb2-watching .nb2-editor-hint { display: none; }
body.nb2-watching #nb2-editor figure.nb2-video { display: none; }   /* the source pane is THE video while watching */
@media (max-width: 760px) {
  body.nb2-watching .nb-notes {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "pager" "workspacehead" "vhead" "video" "notes" "transcript" "status" "desk";
    grid-template-rows: auto auto auto auto auto minmax(200px, 40vh) auto auto;
  }
  body.nb2-watching.nb-view-note-details-hidden .nb-notes {
    grid-template-areas: "pager" "workspacehead" "vhead" "video" "notes" "transcript" "desk";
    grid-template-rows: auto auto auto auto auto minmax(200px, 40vh) auto;
  }
  body.nb2-watching #nb2-src-video iframe { height: auto; width: 100%; }
}
.nb2-watch-jump.is-frozen { color: var(--muted); border-color: var(--hair-strong); }

/* paste-a-transcript dialog: bring notes to Udemy/Pluralsight/anywhere */
.nb2-paste-dialog { width: min(680px, 92vw); }
.nb2-paste-lede { color: var(--muted); font-size: 13px; line-height: 1.5; margin: 0 0 12px; }
.nb2-paste-src, .nb2-paste-text {
  width: 100%; box-sizing: border-box; color: var(--text);
  background: rgba(10,17,40,.4); border: 1px solid var(--hair); border-radius: 8px; padding: 8px 10px;
}
.nb2-paste-src { margin-bottom: 8px; font: inherit; }
.nb2-paste-text { min-height: 220px; resize: vertical; font: 13px/1.5 ui-monospace, "Cascadia Code", Consolas, monospace; }
.nb2-paste-src:focus-visible, .nb2-paste-text:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; border-color: var(--cyan); }
.nb2-paste-acts { display: flex; gap: 8px; justify-content: flex-end; margin-top: 12px; }

/* RESIZABLE + DRAGGABLE media: a corner grip for live drag-resize; grab cursor for
   repositioning (the node is draggable). The img/svg fills the (resizable) figure so
   the stored width scales it both ways. */
.nb2-editor .ProseMirror figure.nb2-photo.nb2-resizable,
.nb2-editor .ProseMirror div.nb2-sketch.nb2-resizable { position: relative; cursor: grab; }
.nb2-editor .ProseMirror figure.nb2-photo.nb2-resizable:active,
.nb2-editor .ProseMirror div.nb2-sketch.nb2-resizable:active { cursor: grabbing; }
.nb2-editor .ProseMirror figure.nb2-photo img,
.nb2-editor .ProseMirror div.nb2-sketch svg { width: 100%; }
.nb2-editor .ProseMirror .nb2-resize-grip {
  position: absolute; right: 4px; bottom: 4px; width: 16px; height: 16px;
  border-radius: 4px; cursor: nwse-resize; z-index: 3; touch-action: none;
  background: var(--cyan, #00E5FF); opacity: 0; transition: opacity .12s ease;
  box-shadow: 0 0 0 2px var(--navy-panel, #0F1D3A);
}
.nb2-editor .ProseMirror figure.nb2-photo:hover .nb2-resize-grip,
.nb2-editor .ProseMirror div.nb2-sketch:hover .nb2-resize-grip { opacity: .95; }

/* selected-node ring for the atomic capture nodes */
.nb2-editor .ProseMirror .ProseMirror-selectednode {
  outline: 2px solid var(--cyan); outline-offset: 2px; border-radius: 9px;
}

/* the hint under the editor */
.nb2-editor-hint { margin-top: 2px; }
.nb2-editor-hint code {
  font-family: ui-monospace, "Cascadia Code", "SFMono-Regular", Menlo, Consolas, monospace;
  background: rgba(159,179,200,.1); border-radius: 4px; padding: 0 4px; font-size: 11.5px;
}

/* gapcursor (StarterKit): keep it visible on the dark canvas */
.nb2-editor .ProseMirror-gapcursor:after {
  border-top: 1px solid var(--cyan);
}

/* ═══════════════════════ v2 SHELL FEATURES (focus · search · status) ═══════════════════════ */
/* All Glass Canon Atrium: navy-dominant, cyan-as-signal, calm. These chrome pieces
   sit AROUND the editor; none of them touch the ProseMirror document. */

/* ── focus-mode header toggle ── */
.nb2-focus-toggle { display: inline-flex; align-items: center; gap: 6px; }
.nb2-focus-toggle .nb2-focus-icon { color: var(--muted); font-size: 13px; line-height: 1; }
.nb2-focus-toggle[aria-pressed="true"],
.nb2-focus-toggle.nb-seg--on {
  background: rgba(0,229,255,.14);
  border-color: var(--glass-edge);
  color: var(--text);
}
.nb2-focus-toggle[aria-pressed="true"] .nb2-focus-icon { color: var(--cyan); text-shadow: 0 0 8px rgba(0,229,255,.5); }

/* ── e-ink mode toggle (paper view for e-readers) ── */
.nb2-eink-toggle { display: inline-flex; align-items: center; gap: 6px; }
.nb2-eink-icon { color: var(--muted); font-size: 13px; line-height: 1; }
.nb2-eink-toggle[aria-pressed="true"] { background: rgba(0,229,255,.14); border-color: var(--glass-edge); color: var(--text); }
.nb2-eink-toggle[aria-pressed="true"] .nb2-eink-icon { color: var(--cyan); }

/* ── "⋯ More" DISCLOSURE: UDL extraneous-load fix (Glass Canon Atrium) ──
   The secondary rail actions (Focus / Sync / Import / Export / Pair-phone) are
   relocated by mountMoreMenu() into a calm floating panel so the rail keeps only
   the two learning-first primaries (Mode + Search). Navy-dominant field, --hair
   separators, cyan = the single signal (focus ring); no new color tokens. */
.nb2-more { position: relative; display: inline-flex; }
/* ── Persistent Knowledge-Galaxy rail button (operator ruling 2026-08-02) ──────
   The galaxy previously existed only inside the ⋯ overflow menu, which the
   operator could not find in his own product. This is the always-visible door.

   The idle animation is deliberately near-subliminal: a ~6s breath on the ICON
   ONLY (never the button box, which would make the rail jitter), amplitude small
   enough to read as "alive" rather than as a notification. It must never compete
   with real state — nothing here is asking to be clicked. Disabled outright under
   prefers-reduced-motion, and inert in e-ink mode where motion is forbidden. */
.nb2-galaxy-rail-btn {
  display: inline-flex; align-items: center; gap: 6px;
  line-height: 1; letter-spacing: .01em;
}
.nb2-galaxy-rail-ico { flex: 0 0 auto; transform-origin: 50% 50%; }
.nb2-galaxy-rail-label { font-size: 12px; }
.nb2-galaxy-rail-btn { min-height: 44px; }
.nb2-more-btn { min-height: 44px; min-width: 44px; }
.nb2-galaxy-rail-btn:hover .nb2-galaxy-rail-ico,
.nb2-galaxy-rail-btn:focus-visible .nb2-galaxy-rail-ico { color: var(--cyan); }
.nb2-galaxy-rail-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

@keyframes nb2-galaxy-breath {
  0%, 100% { opacity: .78; transform: scale(1); }
  50%      { opacity: 1;   transform: scale(1.045); }
}
.nb2-galaxy-rail-ico { animation: nb2-galaxy-breath 6s ease-in-out infinite; }
/* Stop breathing while the panel is open — the thing it points at is already
   on screen, so continuing to shimmer would be noise. */
.nb2-galaxy-rail-btn[aria-expanded="true"] .nb2-galaxy-rail-ico { animation: none; opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  .nb2-galaxy-rail-ico { animation: none; opacity: .9; }
}

/* ── Quiet catch-up / Visual Replay ─────────────────────────────────────── */
.nb-vr-dialog {
  width: min(1100px, calc(100vw - 28px)); max-width: none; max-height: min(92vh, 900px);
  padding: 18px; overflow: auto; color: var(--text, #eef7ff);
  border: 1px solid rgba(84,239,255,.45); border-radius: 16px;
  background: linear-gradient(145deg, rgba(8,18,43,.98), rgba(17,38,76,.97));
  box-shadow: 0 28px 80px rgba(0,0,0,.62), inset 0 0 48px rgba(0,229,255,.05);
}
.nb-vr-dialog::backdrop { background: rgba(3,8,22,.72); backdrop-filter: blur(4px); }
.nb-vr-head, .nb-vr-head-actions, .nb-vr-state-row, .nb-vr-save-row { display: flex; align-items: center; gap: 9px; }
.nb-vr-head { justify-content: space-between; margin-bottom: 8px; }
.nb-vr-head-actions { flex-wrap: wrap; justify-content: flex-end; }
.nb-vr-title { display: grid; gap: 2px; }
.nb-vr-title strong { font: 650 clamp(17px, 2.5vw, 23px)/1.2 "Montserrat", system-ui, sans-serif; }
.nb-vr-kicker { color: var(--muted, #a9bed3); font-size: 11px; font-weight: 650; letter-spacing: .08em; text-transform: uppercase; }
.nb-vr-guidance, .nb-vr-sync-copy { margin: 0 0 12px; color: var(--muted, #a9bed3); font-size: 13px; line-height: 1.45; }
.nb-vr-stage { position: relative; display: grid; place-items: center; min-height: 220px; overflow: hidden; border: 1px solid rgba(113,174,235,.28); border-radius: 12px; background: rgba(3,10,28,.62); }
.nb-vr-image { display: block; width: 100%; max-height: min(53vh, 560px); object-fit: contain; }
.nb-vr-ink { position: absolute; inset: 0; width: 100%; height: 100%; touch-action: none; cursor: crosshair; }
.nb-vr-ink-kind { position: absolute; top: 10px; right: 10px; z-index: 2; padding: 6px 8px; color: var(--text, #eef7ff); border: 1px solid rgba(84,239,255,.42); border-radius: 7px; background: rgba(6,16,38,.86); }
.nb-vr-empty { padding: 36px 20px; color: var(--muted, #a9bed3); text-align: center; }
.nb-vr-state-row { flex-wrap: wrap; justify-content: space-between; margin: 11px 0; }
.nb-vr-live-state { flex: 1 1 240px; color: var(--text, #eef7ff); font-size: 13px; }
.nb-vr-filmstrip { display: flex; gap: 8px; min-height: 92px; overflow-x: auto; padding: 3px 2px 9px; scrollbar-color: rgba(84,239,255,.45) transparent; }
.nb-vr-thumb { display: grid; grid-template-rows: 62px auto; flex: 0 0 106px; gap: 3px; overflow: hidden; padding: 3px; color: var(--muted, #a9bed3); border: 1px solid rgba(113,174,235,.24); border-radius: 8px; background: rgba(7,20,46,.65); cursor: pointer; }
.nb-vr-thumb:hover, .nb-vr-thumb.is-selected { color: var(--text, #eef7ff); border-color: var(--hair-strong, #2a3f6b); box-shadow: none; }
.nb-vr-thumb:focus-visible, .nb-vr-share input:focus-visible, .nb-vr-caption:focus-visible { outline: 2px solid var(--cyan, #00e5ff); outline-offset: 2px; }
.nb-vr-thumb img { width: 100%; height: 62px; object-fit: cover; border-radius: 5px; }
.nb-vr-thumb small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 10px; }
.nb-vr-save-row { margin-top: 2px; }
.nb-vr-caption { flex: 1 1 230px; min-width: 0; padding: 8px 10px; color: var(--text, #eef7ff); border: 1px solid rgba(113,174,235,.36); border-radius: 8px; background: rgba(5,16,37,.64); }
.nb-vr-share { display: flex; align-items: flex-start; gap: 8px; margin-top: 12px; color: var(--text, #eef7ff); font-size: 12px; line-height: 1.4; cursor: pointer; }
.nb-vr-share input { margin-top: 2px; accent-color: var(--cyan, #00e5ff); }
@media (max-width: 620px) {
  .nb-vr-dialog { width: calc(100vw - 12px); padding: 12px; }
  .nb-vr-head { align-items: flex-start; }
  .nb-vr-head-actions { justify-content: flex-start; }
  .nb-vr-thumb { flex-basis: 88px; grid-template-rows: 54px auto; }
  .nb-vr-thumb img { height: 54px; }
}
body.nb2-eink .nb2-galaxy-rail-ico { animation: none; opacity: 1; }

/* Placeholder disclosure inside the galaxy panel. Deliberately readable, NOT
   alarming: a placeholder is a legitimate state, not an error. Warm sand (the
   same "NOT red = care" choice the self-report layer makes), left rule, no icon. */
.nb2-galaxy-placeholder {
  margin: 6px 0 2px; padding: 7px 10px;
  border-left: 3px solid var(--ct-acronym, #FFD93D);
  background: rgba(255, 217, 61, .07);
  border-radius: 0 6px 6px 0; font-size: 12.5px; line-height: 1.45;
}

/* Galaxy switcher (operator ruling 2026-08-02: "you should be able to toggle
   between them ... you're moving between galaxies often hourly"). Rendered only
   when two or more skies exist; a one-option select is furniture. */
.nb2-galaxy-switch {
  margin-left: auto; margin-right: 8px;
  background: var(--navy-panel); color: inherit;
  border: 1px solid var(--hairline, rgba(255,255,255,.18));
  border-radius: 6px; padding: 3px 6px; font: inherit; font-size: 12px;
  max-width: 42%;
}
.nb2-galaxy-switch:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

.nb2-more-btn { line-height: 1; font-size: 15px; letter-spacing: .04em; }
.nb2-more-btn[aria-expanded="true"] {
  background: rgba(0,229,255,.14);
  border-color: var(--glass-edge);
  color: var(--text);
}
.nb2-more-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

/* the popover: a small navy panel anchored under the button, a column of
   full-width secondary actions. [hidden] keeps it out of layout until opened. */
/* The fan-out: a screen-filling, GROUPED popover (not a tall column that runs off the bottom). Anchored
   under the ⋯ button, it widens into a responsive grid of titled groups and caps to the viewport. */
#nb2-more-menu {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 90;
  width: min(680px, calc(100vw - 32px));
  padding: 16px 16px 14px;
  background: var(--navy-panel);
  border: 1px solid var(--hair);
  border-radius: 14px;
  box-shadow: 0 22px 60px rgba(0,0,0,.5), 0 0 0 1px rgba(84,239,255,.06);
  max-height: calc(100vh - 24px);
  overflow-y: auto;
  overscroll-behavior: contain;
  transform-origin: top right;
}
#nb2-more-menu[hidden] { display: none; }
/* mild fan-out on open — re-runs each time the menu un-hides (display none→block). */
#nb2-more-menu:not([hidden]) { animation: nb2-more-in 160ms cubic-bezier(.2,.8,.25,1) both; }
@keyframes nb2-more-in {
  from { opacity: 0; transform: translateY(-8px) scale(.985); }
  to   { opacity: 1; transform: none; }
}
/* responsive group grid — columns fill the width instead of stacking off-screen */
.nb2-more-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(185px, 1fr));
  gap: 14px 20px;
  align-items: start;
}
.nb2-more-group { min-width: 0; animation: nb2-more-group-in 240ms ease-out both; }
.nb2-more-group:nth-child(2) { animation-delay: 35ms; }
.nb2-more-group:nth-child(3) { animation-delay: 70ms; }
.nb2-more-group:nth-child(4) { animation-delay: 105ms; }
.nb2-more-group:nth-child(5) { animation-delay: 140ms; }
@keyframes nb2-more-group-in { from { opacity: 0; transform: translateY(7px); } to { opacity: 1; transform: none; } }
/* group header: Montserrat, quiet, under a thin cyan instrument-line (Glass Canon: cyan is a light, not a fill) */
.nb2-more-group-h {
  margin: 0 0 8px;
  padding-bottom: 5px;
  font: 600 11px/1.2 "Montserrat", system-ui, sans-serif;
  letter-spacing: .07em;
  text-transform: uppercase;
  color: var(--text-dim, #9fb2d6);
  border-bottom: 1px solid rgba(84,239,255,.18);
}
.nb2-more-group-items { display: flex; flex-direction: column; gap: 2px; }
/* each action: a calm, full-width, left-aligned row that lights up gently on hover/focus */
.nb2-more-lead {
  margin: 0 0 10px;
  color: var(--muted);
  font-size: 12.5px;
  line-height: 1.4;
}
.nb2-more-group-items .nb-btn,
.nb2-more-group-items .nb2-focus-toggle,
.nb2-more-group-items .nb2-eink-toggle {
  width: 100%;
  justify-content: flex-start;
  text-align: left;
  border: 1px solid transparent;
  background: transparent;
  min-height: 44px;
  padding: 8px 10px;
  border-radius: 8px;
  font-size: 13px;
  white-space: normal;
  display: flex;
  align-items: center;
  gap: 8px;
  box-sizing: border-box;
  transition: background .12s ease, border-color .12s ease;
}
/* UDL recognition icon: a muted line glyph, one per action, that brightens to cyan with the row on
   hover/focus — a second (visual) channel of meaning beside the label, never a color-loud fill. */
.nb2-more-icon { width: 15px; height: 15px; flex: none; opacity: .42; transition: opacity .12s ease, color .12s ease; }
.nb2-more-group-items .nb-btn:hover .nb2-more-icon,
.nb2-more-group-items .nb-btn:focus-visible .nb2-more-icon,
.nb2-more-group-items .nb2-focus-toggle:hover .nb2-more-icon,
.nb2-more-group-items .nb2-focus-toggle:focus-visible .nb2-more-icon,
.nb2-more-group-items .nb2-eink-toggle:hover .nb2-more-icon,
.nb2-more-group-items .nb2-eink-toggle:focus-visible .nb2-more-icon { opacity: .85; color: var(--cyan); }
.nb2-more-group-items .nb-btn:hover,
.nb2-more-group-items .nb-btn:focus-visible,
.nb2-more-group-items .nb2-focus-toggle:hover,
.nb2-more-group-items .nb2-focus-toggle:focus-visible,
.nb2-more-group-items .nb2-eink-toggle:hover,
.nb2-more-group-items .nb2-eink-toggle:focus-visible {
  background: rgba(84,239,255,.08);
  border-color: rgba(84,239,255,.22);
}
/* keep the Back-up "primary" from being a loud filled button inside the calm panel */
.nb2-more-group-items .nb-btn--primary { background: transparent; color: var(--text); }
.nb2-more-group-items .nb-btn--primary:hover { background: rgba(84,239,255,.08); }
/* the pair-phone chip + the hidden file input ride along, out of the grid flow */
.nb2-more-carry { display: block; margin-top: 10px; }
.nb2-more-carry .nb2-pair-chip { display: inline-flex; }
.nb2-more-carry input[type="file"] { display: none; }
@media (prefers-reduced-motion: reduce) {
  #nb2-more-menu:not([hidden]), .nb2-more-group { animation: none !important; }
}

/* ── FOCUS / TYPEWRITER MODE ── */
/* When body.nb2-focus is set: dim the surrounding chrome (cues, summary, record,
   flow strip, coach) so the notes card is the calm center of attention; the active
   line is lifted, everything else in the editor softens. */
body.nb2-focus .nb-flow,
body.nb2-focus .nb-coach,
body.nb2-focus .nb-cues,
body.nb2-focus .nb-summary,
body.nb2-focus .nb-record {
  opacity: .34;
  filter: saturate(.7);
  transition: opacity .2s ease, filter .2s ease;
}
body.nb2-focus .nb-cues:focus-within,
body.nb2-focus .nb-summary:focus-within,
body.nb2-focus .nb-record:focus-within {
  opacity: 1;            /* restore full clarity when the user deliberately engages a zone */
  filter: none;
}
/* the notes card itself stays bright and gains a calmer, deeper field */
body.nb2-focus .nb-notes { opacity: 1; }
body.nb2-focus .nb2-editor {
  min-height: 60vh;
  box-shadow: 0 0 0 1px var(--glass-edge), inset 0 0 60px rgba(7,15,31,.55);
}
/* dim every block except the active line; lift the active one */
body.nb2-focus .nb2-editor .ProseMirror > * { opacity: .38; transition: opacity .18s ease; }
body.nb2-focus .nb2-editor .ProseMirror > .nb2-active-line {
  opacity: 1;
  text-shadow: 0 0 18px rgba(84,239,255,.06);
}

/* ── IN-NOTE SEARCH bar (Cycle 5: recede glow; 44px nav; honest empty query) ── */
.nb2-search {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 4px 0 8px;
  padding: 4px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 9px;
  background: rgba(10,17,40,.5);
  box-shadow: none;
}
.nb2-search[hidden] { display: none; }
.nb2-search-icon { color: var(--muted); font-size: 15px; line-height: 1; flex: none; text-shadow: none; }
.nb2-search-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--text);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 14px;
  padding: 2px 0;
}
.nb2-search-input::placeholder { color: var(--muted); }
.nb2-search-count {
  flex: none;
  color: var(--muted);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  min-width: 0;
  max-width: 18em;
  text-align: right;
  white-space: nowrap;
}
.nb2-search-nav {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  border: 1px solid var(--hair);
  color: var(--muted);
  border-radius: 6px;
  min-width: 44px;
  min-height: 44px;
  width: 44px;
  height: 44px;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  transition: color .12s ease, border-color .12s ease, background .12s ease;
}
.nb2-search-nav:hover { color: var(--text); border-color: var(--glass-edge); background: rgba(0,229,255,.08); }
.nb2-search-nav:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }

/* search match highlights via the CSS Custom Highlight API (no DOM mutation) */
::highlight(nb2-find) {
  background: rgba(0,229,255,.22);
  color: var(--text);
}
::highlight(nb2-find-active) {
  background: rgba(0,229,255,.55);
  color: var(--on-cyan-ink);
}

/* ── STATUS BAR ── */
.nb2-status-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-top: 8px;
  padding: 6px 11px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: rgba(10,17,40,.35);
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.3;
  flex-wrap: wrap;
}
.nb2-status-item { color: var(--text); font-variant-numeric: tabular-nums; }
.nb2-status-sep { color: var(--hair-strong); }
.nb2-status-spacer { flex: 1 1 auto; }
.nb2-status-hint { color: var(--muted); opacity: .85; }
.nb2-status-hint kbd {
  font-family: ui-monospace, "Cascadia Code", "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 10.5px;
  background: rgba(159,179,200,.12);
  border: 1px solid var(--hair);
  border-radius: 4px;
  padding: 0 4px;
  color: var(--text);
}

/* ── ATTENTION-BUDGET METER (nb_attention): a calm cognitive-load chip that
   lives inside the status bar. Glass Canon: navy-dominant, the status dot is the
   single signal (cyan/calm → amber/full → red/overloaded), Montserrat inherited,
   WCAG-AA text, cyan focus ring. Progressive disclosure: the recommendation row
   appears only when the note is overloaded AND the learner opens the chip. ── */
.nb2-attention { position: relative; display: inline-flex; align-items: center; }

.nb2-attention-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 1px 8px;
  font: inherit;
  font-size: 10.5px;
  line-height: 1.4;
  color: var(--muted);
  background: rgba(10,17,40,.45);
  border: 1px solid var(--hair);
  border-radius: 999px;
  cursor: default;
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.nb2-attention-label { color: var(--text); font-variant-numeric: tabular-nums; }
.nb2-attention-dot {
  width: 7px; height: 7px; flex: none;
  border-radius: 50%;
  background: var(--ok);                         /* calm = cyan (default) */
  box-shadow: 0 0 6px rgba(0,229,255,.45);
}

/* level signal lives on the wrap's data-level (set by renderAttention). */
.nb2-attention[data-level="full"] .nb2-attention-dot {
  background: var(--warn); box-shadow: 0 0 6px rgba(245,158,11,.5);
}
.nb2-attention[data-level="overloaded"] .nb2-attention-dot {
  background: var(--err); box-shadow: 0 0 7px rgba(255,138,138,.55);
}
/* only the OVERLOADED chip invites a click (it has a recommendation to disclose) */
.nb2-attention[data-level="overloaded"] .nb2-attention-chip {
  cursor: pointer;
  color: var(--text);
  border-color: var(--glass-edge, var(--cyan));
}
.nb2-attention[data-level="overloaded"] .nb2-attention-chip:hover {
  background: rgba(0,229,255,.08);
}
.nb2-attention-chip:focus-visible {
  outline: 2px solid var(--cyan, #00E5FF);
  outline-offset: 2px;
}

/* the disclosed chunk recommendation: a calm popover above the chip, never a
   modal, never a nag. Only shown when overloaded + opened (JS toggles [hidden]). */
.nb2-attention-rec {
  position: absolute;
  bottom: calc(100% + 8px);
  left: 0;
  z-index: 30;
  max-width: min(340px, 70vw);
  padding: 9px 12px;
  font-size: 11.5px;
  line-height: 1.45;
  color: var(--text);
  background: var(--navy-panel, var(--navy-deep, #0A1128));
  border: 1px solid var(--glass-edge, var(--cyan));
  border-radius: 8px;
  box-shadow: 0 6px 22px rgba(4,8,20,.5), inset 0 0 40px rgba(7,15,31,.4);
}
.nb2-attention-rec[hidden] { display: none; }

@media (max-width: 720px) {
  /* on the mobile stack the chip rides its own status-bar line; the popover
     anchors to the viewport edge so it never overflows. */
  .nb2-attention-rec { max-width: 88vw; }
}

/* ── WORRYPLATE (Glass Canon light register) ── */
.nb2-worryplate { position: relative; display: inline-flex; align-items: center; margin-left: 8px; }
.nb2-worryplate-chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 3px 10px; border-radius: 8px;
  border: 1px solid rgba(84,239,255,.28);
  background: linear-gradient(135deg, rgba(37,67,113,.55), rgba(22,42,77,.42));
  color: var(--text); font: 500 12px/1.2 "Montserrat", system-ui, sans-serif;
  cursor: pointer;
}
.nb2-worryplate-chip[aria-expanded="true"] {
  border-color: rgba(84,239,255,.45);
  box-shadow: 0 0 12px rgba(84,239,255,.12);
}
.nb2-worryplate-chip:focus-visible { outline: 2px solid #00E5FF; outline-offset: 2px; }
.nb2-worryplate-badge {
  min-width: 16px; padding: 0 5px; border-radius: 999px;
  background: rgba(0,229,255,.18); color: #00E5FF;
  font-size: 11px; font-variant-numeric: tabular-nums; text-align: center;
}
.nb2-worryplate-menu {
  position: absolute; bottom: calc(100% + 8px); left: 0; z-index: 45;
  width: min(360px, calc(100vw - 24px));
  padding: 12px;
  border: 1px solid rgba(84,239,255,.4);
  border-radius: 8px;
  background:
    linear-gradient(135deg, rgba(37,67,113,.92), rgba(22,42,77,.78)),
    radial-gradient(circle at 22% 0%, rgba(84,239,255,.14), transparent 38%);
  box-shadow: 0 0 36px rgba(84,239,255,.16), inset 0 0 20px rgba(84,239,255,.06);
  backdrop-filter: blur(8px);
}
.nb2-worryplate-menu[hidden] { display: none; }
.nb2-worryplate-head { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-bottom: 10px; }
.nb2-worryplate-summary { color: var(--muted, #9FB3C8); font-size: 11px; flex: 1 1 auto; }
.nb2-worryplate-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.nb2-worryplate-cat, .nb2-worryplate-sub {
  padding: 8px 10px; border-radius: 8px; border: 1px solid rgba(84,239,255,.22);
  background: rgba(15,29,58,.35); color: var(--text); text-align: left;
  font: 500 12px/1.25 "Montserrat", system-ui, sans-serif; cursor: pointer;
}
.nb2-worryplate-cat:hover, .nb2-worryplate-sub:hover {
  border-color: rgba(0,229,255,.55);
}
/* Glass Canon: the #00E5FF focus ring is non-negotiable — never outline:none */
.nb2-worryplate-cat:focus-visible, .nb2-worryplate-sub:focus-visible {
  border-color: rgba(0,229,255,.55);
  outline: 2px solid #00E5FF; outline-offset: 1px;
}
.nb2-worryplate-subtypes { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.nb2-worryplate-slot-input {
  width: 100%; margin: 8px 0; padding: 8px 10px; border-radius: 8px;
  border: 1px solid rgba(84,239,255,.35); background: rgba(10,17,40,.5); color: var(--text);
}
.nb2-worryplate-slot-input:focus-visible { outline: 2px solid #00E5FF; outline-offset: 1px; }
.nb2-worryplate-drawer {
  margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(84,239,255,.18);
  max-height: 220px; overflow-y: auto;
}
.nb2-worryplate-drawer[hidden] { display: none; }
.nb2-worryplate-row { padding: 6px 0; border-bottom: 1px solid rgba(84,239,255,.1); }
.nb2-worryplate-row-label { display: block; margin-bottom: 4px; color: var(--text); font-size: 13px; }
.nb2-worryplate-row-acts { display: flex; flex-wrap: wrap; gap: 4px; }
.nb2-worryplate-empty { color: var(--muted, #9FB3C8); font-size: 12px; padding: 6px 0; }

@media (max-width: 720px) {
  .nb2-worryplate-menu { left: auto; right: 0; width: min(340px, calc(100vw - 16px)); }
}

@media (prefers-reduced-motion: reduce) {
  .nb2-worryplate-menu { animation: none !important; }
  .nb2-editor { transition: none !important; }
  .nb2-editor .ProseMirror > .nb2-watch-active { transition: none !important; }   /* Watch & Note rail: no fade for reduced-motion */
  body.nb2-focus .nb-flow,
  body.nb2-focus .nb-coach,
  body.nb2-focus .nb-cues,
  body.nb2-focus .nb-summary,
  body.nb2-focus .nb-record,
  body.nb2-focus .nb2-editor .ProseMirror > * { transition: none !important; }
}

/* ============================================================================
   PHASE 2: slash palette · drag-handle · collapsible toggle · callout · link
   The extensions are functionally inert without these rules (the popup, the
   gutter grip, the disclosure collapse, and the callout box are all CSS-driven).
   On-canon: navy-dominant glass, cyan-as-signal, Montserrat.
   ============================================================================ */

/* ── SLASH COMMAND PALETTE (self-rendered popup, appended to document.body) ── */
.nb2-slash-popup {
  position: absolute;
  z-index: 9999;
  min-width: 232px;
  max-width: 320px;
  max-height: 320px;
  overflow-y: auto;
  background: rgba(10, 17, 40, 0.96);
  border: 1px solid var(--hair-strong, rgba(159,179,200,.28));
  border-radius: 10px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.38);
  padding: 5px;
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, -apple-system, "Segoe UI", sans-serif;
  -webkit-font-smoothing: antialiased;
}
.nb2-slash-item {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  width: 100%;
  text-align: left;
  min-height: 44px;
  padding: 8px 11px;
  border: 0;
  background: transparent;
  cursor: pointer;
  border-radius: 7px;
  color: var(--text, #e7eef7);
  font-size: 13px;
  line-height: 1.3;
  box-sizing: border-box;
  transition: background 0.1s ease;
}
.nb2-slash-item.is-selected,
.nb2-slash-item:hover {
  background: rgba(159, 179, 200, 0.10);
}
.nb2-slash-item:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.nb2-slash-title { font-weight: 600; }
.nb2-slash-desc {
  font-size: 11px;
  color: var(--muted, #9aa7bd);
  font-weight: 400;
}
.nb2-slash-empty {
  padding: 9px 11px;
  color: var(--muted, #9aa7bd);
  font-size: 12.5px;
}

/* ── BLOCK DRAG-HANDLE (left-gutter grip; widget decoration at block start) ── */
.nb2-editor .ProseMirror { position: relative; padding-left: 1.55rem; }
.pm-drag-handle {
  position: absolute;
  left: -1.35rem;
  transform: translateY(0.12em);
  cursor: grab;
  opacity: 0;
  user-select: none;
  color: var(--muted, #8a93a8);
  font-size: 0.85em;
  line-height: 1;
  transition: opacity 0.12s ease, color 0.12s ease;
}
.nb2-editor .ProseMirror:hover .pm-drag-handle { opacity: 0.5; }
.pm-drag-handle:hover { opacity: 1; color: var(--cyan, #00e5ff); }
.pm-drag-handle:active { cursor: grabbing; }

/* ── COLLAPSIBLE TOGGLE (Node.create + NodeView; persisted `open` attr) ── */
.nb2-toggle-block { display: block; margin: 6px 0; }
.nb2-toggle-header { display: flex; align-items: flex-start; gap: 0.4rem; }
.nb2-toggle-triangle {
  border: 0;
  background: transparent;
  cursor: pointer;
  font-size: 0.8em;
  line-height: 1.5;
  padding: 0;
  color: var(--muted, #8a93a8);
  transition: color 0.12s ease;
  flex: 0 0 auto;
}
.nb2-toggle-triangle:hover { color: var(--cyan, #00e5ff); }
.nb2-toggle-content {
  flex: 1 1 auto;
  border-left: 2px solid var(--hair, rgba(159, 179, 200, 0.16));
  padding-left: 0.6rem;
  margin-left: 0.1rem;
}
/* collapse the content when closed: `open` lives in node attrs (persisted) */
.nb2-toggle-block[data-open="false"] > .nb2-toggle-content { display: none; }
/* native <details> export fallback: collapses with no JS */
details[data-type="toggle"][data-open="false"] > .nb2-toggle-content { display: none; }
details[data-type="toggle"] > summary.nb2-toggle-summary { cursor: pointer; color: var(--muted, #8a93a8); }

/* ── CALLOUT (a blockquote tagged with data-callout by the slash "Callout" item) ── */
.nb2-editor .ProseMirror blockquote[data-callout] {
  border-left: 3px solid var(--cyan, #00e5ff);
  background: rgba(0, 229, 255, 0.07);
  border-radius: 6px;
  padding: 8px 12px;
  margin: 8px 0;
}

/* ── LINK (in-editor: caret on click, cyan signal) ── */
.nb2-editor .ProseMirror a {
  color: var(--cyan, #00e5ff);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: text; /* openOnClick:false: click places the caret, not navigate */
}

@media (prefers-reduced-motion: reduce) {
  .nb2-slash-item,
  .pm-drag-handle,
  .nb2-toggle-triangle { transition: none !important; }
}

/* ============================================================================
   PHASE 3: per-notebook TAGS · code-block (hljs) theme
   On-canon Glass Canon Atrium: navy-dominant, cyan-as-signal, Montserrat. The tag
   chips sit in the cue column; the hljs theme + code-block shell are for the editor
   agent's CodeBlockLowlight NodeView (coordinated via the contract).
   ============================================================================ */

/* ── PER-NOTEBOOK TAGS (chip strip + add form, in the cue column) ── */
.nb2-tags {
  display: flex;
  flex-direction: column;
  gap: 7px;
  margin: 4px 0 10px;
}
.nb2-tag-add {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px 4px 9px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: rgba(10, 17, 40, .35);
  transition: border-color .12s ease, box-shadow .12s ease;
}
.nb2-tag-add:focus-within {
  border-color: var(--glass-edge);
  box-shadow: inset 0 0 12px rgba(84, 239, 255, .05);
}
.nb2-tag-hash { color: var(--cyan); font-size: 13px; line-height: 1; flex: none; }
.nb2-tag-add { min-height: 44px; box-sizing: border-box; }
.nb2-tag-add .nb-btn { min-height: 44px; min-width: 44px; box-sizing: border-box; }
.nb2-tag-input {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  background: transparent;
  border: 0;
  outline: 0;
  color: var(--text);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 12.5px;
  padding: 2px 0;
}
.nb2-tag-input::placeholder { color: var(--muted); }

.nb2-tag-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
.nb2-tag-empty { font-size: 13px; }
.nb2-tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  border: 1px solid var(--hair-strong);
  border-radius: 999px;
  background: rgba(10, 17, 40, .42);
  padding: 1px 3px 1px 2px;
  min-height: 44px;
  box-sizing: border-box;
  transition: border-color .12s ease, background .12s ease;
}
.nb2-tag-chip.is-on {
  border-color: var(--glass-edge);
  background: rgba(0, 229, 255, .14);   /* cyan = signal (active filter) */
  box-shadow: inset 2px 0 0 var(--cyan);   /* WCAG 1.4.1: non-color cue for the active filter */
}
.nb2-tag-label {
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--muted);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
  padding: 2px 10px;
  min-height: 44px;
  box-sizing: border-box;
  border-radius: 999px;
  transition: color .12s ease;
}
.nb2-tag-chip.is-on .nb2-tag-label { color: var(--cyan-glow); }
.nb2-tag-label:hover { color: var(--text); }
.nb2-tag-x {
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  padding: 3px 5px;
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
  border-radius: 999px;
  transition: color .12s ease, background .12s ease;
}
.nb2-tag-x:hover { color: var(--err, #FF8A8A); background: rgba(255, 138, 138, .12); }

/* ── CODE-BLOCK shell (for the editor agent's CodeBlockLowlight NodeView) ──
   The editor agent renders a `.nb2-codeblock-wrap > [copy button] + <pre><code>`
   (per the CODE+TABLES recipe). These rules style that shell on-canon: the <pre>
   owns the navy field, the cyan copy button is the only signal. Scoped under
   .nb2-editor so they never leak. (If the editor still emits a plain <pre> with the
   `nb2-codeblock` HTMLAttribute, the existing .ProseMirror pre rules above still
   apply, these are additive, not a replacement.) */
.nb2-editor .ProseMirror .nb2-codeblock-wrap { position: relative; }
.nb2-editor .ProseMirror .nb2-codeblock-wrap > pre {
  background: var(--navy-deep, #0a1128);   /* canon navy (tokyo-night #1a1b26 nudged to canon) */
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 14px 16px;
  margin: 8px 0;
  overflow-x: auto;
  line-height: 1.5;
}
.nb2-editor .ProseMirror .nb2-codeblock-wrap > pre code.hljs,
.nb2-editor .ProseMirror .nb2-codeblock-wrap > pre code {
  background: transparent;   /* let the <pre> own the field */
  border: 0;
  padding: 0;
  font-size: 12.5px;
}
.nb2-editor .ProseMirror .nb2-codeblock-copy {
  position: absolute;
  top: 8px; right: 8px;
  font: 600 11px/1 Montserrat, system-ui, sans-serif;
  color: var(--cyan-glow, #54efff);          /* cyan = signal */
  background: rgba(125, 207, 255, .10);
  border: 1px solid var(--glass-edge, rgba(84, 239, 255, .22));
  border-radius: 6px;
  padding: 4px 8px;
  cursor: pointer;
  transition: background .12s ease, color .12s ease;
}
.nb2-editor .ProseMirror .nb2-codeblock-copy:hover { background: rgba(125, 207, 255, .18); color: var(--text); }

/* ── DARK highlight.js theme: tokyo-night-dark (on-canon navy/cyan register) ──
   The editor agent's CodeBlockLowlight applies `hljs-*` classes as ProseMirror
   inline decorations; this is the color map for them. Inlined verbatim from
   node_modules/highlight.js/styles/tokyo-night-dark.css (BSD-3-Clause, permissive),
   SCOPED under `.nb2-editor .ProseMirror` so the theme can't leak into the rest of
   the Glass Canon shell. The `.hljs` background is dropped (the `<pre>` owns the
   field above); only the syntax colors are kept. tokyo-night-dark is the closest
   match to "navy dominates, cyan = signal": deep navy field, cyan/blue/violet ink. */
.nb2-editor .ProseMirror .hljs-meta,
.nb2-editor .ProseMirror .hljs-comment { color: #565f89; }
.nb2-editor .ProseMirror .hljs-tag,
.nb2-editor .ProseMirror .hljs-doctag,
.nb2-editor .ProseMirror .hljs-selector-id,
.nb2-editor .ProseMirror .hljs-selector-class,
.nb2-editor .ProseMirror .hljs-regexp,
.nb2-editor .ProseMirror .hljs-template-tag,
.nb2-editor .ProseMirror .hljs-selector-pseudo,
.nb2-editor .ProseMirror .hljs-selector-attr,
.nb2-editor .ProseMirror .hljs-variable.language_,
.nb2-editor .ProseMirror .hljs-deletion { color: #9FB3C8; }
.nb2-editor .ProseMirror .hljs-variable,
.nb2-editor .ProseMirror .hljs-template-variable,
.nb2-editor .ProseMirror .hljs-number,
.nb2-editor .ProseMirror .hljs-literal,
.nb2-editor .ProseMirror .hljs-type,
.nb2-editor .ProseMirror .hljs-params,
.nb2-editor .ProseMirror .hljs-link { color: #9FB3C8; }
.nb2-editor .ProseMirror .hljs-built_in,
.nb2-editor .ProseMirror .hljs-attribute { color: #F59E0B; }
.nb2-editor .ProseMirror .hljs-selector-tag { color: #2ac3de; }
.nb2-editor .ProseMirror .hljs-keyword,
.nb2-editor .ProseMirror .hljs-title.function_,
.nb2-editor .ProseMirror .hljs-title,
.nb2-editor .ProseMirror .hljs-title.class_,
.nb2-editor .ProseMirror .hljs-title.class_.inherited__,
.nb2-editor .ProseMirror .hljs-subst,
.nb2-editor .ProseMirror .hljs-property { color: #7dcfff; }
.nb2-editor .ProseMirror .hljs-quote,
.nb2-editor .ProseMirror .hljs-string,
.nb2-editor .ProseMirror .hljs-symbol,
.nb2-editor .ProseMirror .hljs-bullet,
.nb2-editor .ProseMirror .hljs-addition { color: #54EFFF; }
.nb2-editor .ProseMirror .hljs-code,
.nb2-editor .ProseMirror .hljs-formula,
.nb2-editor .ProseMirror .hljs-section { color: #7aa2f7; }
.nb2-editor .ProseMirror .hljs-name,
.nb2-editor .ProseMirror .hljs-operator,
.nb2-editor .ProseMirror .hljs-char.escape_,
.nb2-editor .ProseMirror .hljs-attr { color: #9FB3C8; }
.nb2-editor .ProseMirror .hljs-punctuation { color: #c0caf5; }
.nb2-editor .ProseMirror .hljs-emphasis { font-style: italic; }
.nb2-editor .ProseMirror .hljs-strong { font-weight: bold; }

/* ============================================================================
   PAIRING + SYNC: "Pair phone" button, live chip, QR dialog
   On-canon Glass Canon Atrium: navy-dominant, cyan-as-signal, Montserrat. The
   button + chip are mounted into the header rail by notebook2.js (pairing lane);
   the dialog is built lazily in JS. These styles are the visual layer for them.
   ============================================================================ */

/* the live "phone pairing" chip (idle until the launcher is found, then cyan) */
.nb2-pair-chip { gap: 6px; }
.nb2-pair-chip[hidden] { display: none; }
.nb2-pair-chip[data-live="true"] {
  border-color: var(--glass-edge);
  background: rgba(0, 229, 255, .12);
}
.nb2-pair-chip[data-live="true"] .nb-dot {
  background: var(--cyan);
  box-shadow: 0 0 8px rgba(0, 229, 255, .6);
}
.nb2-pair-chip-text { color: var(--text); font-size: 11.5px; }

/* LearnNav persistent course-connection chip (top status bar) */
.nb2-learnnav-chip { gap: 6px; cursor: pointer; }
.nb2-learnnav-chip[hidden] { display: none; }
.nb2-learnnav-chip.is-requesting,
.nb2-learnnav-chip.is-waiting {
  border-color: rgba(255, 193, 7, .45);
  background: rgba(255, 193, 7, .1);
}
.nb2-learnnav-chip.is-admitted {
  border-color: rgba(0, 229, 255, .45);
  background: rgba(0, 229, 255, .12);
}
.nb2-learnnav-chip.is-live {
  border-color: rgba(74, 222, 128, .45);
  background: rgba(74, 222, 128, .12);
}
.nb2-learnnav-chip.is-waiting .nb-dot,
.nb2-learnnav-chip.is-requesting .nb-dot {
  background: #ffc107;
  box-shadow: 0 0 8px rgba(255, 193, 7, .55);
}
.nb2-learnnav-chip.is-admitted .nb-dot {
  background: var(--cyan);
  box-shadow: 0 0 8px rgba(0, 229, 255, .6);
}
.nb2-learnnav-chip.is-live .nb-dot {
  background: #4ade80;
  box-shadow: 0 0 8px rgba(74, 222, 128, .6);
}
.nb2-learnnav-chip-text { color: var(--text); font-size: 11.5px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* §16b Nav-mode chrome: persistent chip naming the Nav + steer-my-own-sky.
   Live = admission-poll-verified; offline = verified bundle apply. */
.nb2-navmode { display: inline-flex; align-items: center; }
.nb2-navmode[hidden] { display: none; }
.nb2-navmode-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 6px 2px 10px;
  border: 1px solid var(--glass-edge);
  border-radius: 999px;
}
.nb2-navmode-chip.is-live {
  border-color: rgba(0, 229, 255, .45);
  background: rgba(0, 229, 255, .1);
}
.nb2-navmode-chip.is-live .nb-dot {
  background: var(--cyan);
  box-shadow: 0 0 8px rgba(0, 229, 255, .6);
}
.nb2-navmode-chip.is-offline {
  border-color: rgba(167, 139, 250, .45);
  background: rgba(167, 139, 250, .1);
}
.nb2-navmode-chip.is-offline .nb-dot {
  background: #a78bfa;
  box-shadow: 0 0 8px rgba(167, 139, 250, .55);
}
.nb2-navmode-chip-text {
  color: var(--text);
  font-size: 11.5px;
  max-width: 200px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nb2-navmode-override { font-size: 11px; }
.nb2-navmode-override.is-on {
  border-color: rgba(255, 193, 7, .5);
  background: rgba(255, 193, 7, .12);
}

/* §16c connection doctor: the three-step ladder (each step verified or an
   honest checking/unknown), remedy copy, one-tap rejoin. */
.nb2-doctor { display: grid; gap: 8px; }
.nb2-doctor-ladder {
  display: grid;
  gap: 4px;
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: doctor-step;
}
.nb2-doctor-step {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text);
}
.nb2-doctor-step::before {
  counter-increment: doctor-step;
  content: counter(doctor-step);
  font-size: 10.5px;
  color: var(--muted);
  min-width: 12px;
  text-align: right;
}
.nb2-doctor-step-state { color: var(--muted); font-size: 11.5px; margin-left: auto; }
.nb2-doctor-step.is-ok .nb-dot { background: #4ade80; box-shadow: 0 0 8px rgba(74, 222, 128, .6); }
.nb2-doctor-step.is-ok .nb2-doctor-step-state { color: #4ade80; }
.nb2-doctor-step.is-checking .nb-dot { background: #ffc107; box-shadow: 0 0 8px rgba(255, 193, 7, .55); }
.nb2-doctor-step.is-checking .nb2-doctor-step-state { color: #ffc107; }
.nb2-doctor-step.is-failed .nb-dot { background: #ff6b6b; box-shadow: 0 0 8px rgba(255, 107, 107, .55); }
.nb2-doctor-step.is-failed .nb2-doctor-step-state { color: #ff6b6b; }
.nb2-doctor-step.is-off .nb-dot { background: transparent; border: 1px solid var(--muted); box-shadow: none; }
.nb2-doctor-step.is-offline .nb-dot { background: #a78bfa; box-shadow: 0 0 8px rgba(167, 139, 250, .55); }
.nb2-doctor-step.is-offline .nb2-doctor-step-state { color: #a78bfa; }
.nb2-doctor-remedy {
  margin: 0;
  font-size: 12px;
  line-height: 1.45;
  color: var(--muted);
  border-left: 2px solid var(--glass-edge);
  padding-left: 8px;
}

/* ── WP-NET-10 — CP3 two-step fabric UX (attach-first + browse) + the fabric
   chip. Token-driven so BOTH themes (dark navy default + body.eink paper) work
   with no per-theme fork. Every state color reuses the existing doctor palette;
   only the fabric-specific 'empty' + 'live' availability states are added. ── */
.nb2-fabric-steps { display: grid; gap: 12px; margin: 12px 0; }
.nb2-fabric-connect,
.nb2-fabric-browse,
.nb2-fabric-doctor {
  display: grid;
  gap: 8px;
  padding: 12px;
  border: 1px solid var(--glass-edge);
  border-radius: 10px;
  background: rgba(10, 17, 40, .35);
}
.nb2-fabric-state { display: flex; align-items: center; gap: 8px; }
.nb2-fabric-label { margin: 0; font-size: 13px; }
/* The dot's verified liveness (data-live from the probe, never a stale paint). */
.nb2-fabric-state .nb-dot[data-live="up"] { background: #4ade80; box-shadow: 0 0 8px rgba(74, 222, 128, .6); }
.nb2-fabric-state .nb-dot[data-live="down"] { background: #ff6b6b; box-shadow: 0 0 8px rgba(255, 107, 107, .55); }
.nb2-fabric-state .nb-dot[data-live="unknown"] { background: transparent; border: 1px solid var(--muted); box-shadow: none; }
.nb2-fabric-origin { width: 100%; padding: 8px 10px; border-radius: 8px; border: 1px solid var(--glass-edge); background: rgba(0, 0, 0, .2); color: var(--text); }

/* Browse list + the HONEST empty state (a REAL empty availability answer). */
.nb2-fabric-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 6px; }
.nb2-fabric-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; border-radius: 8px;
  border: 1px solid var(--hair);
  background: var(--navy-panel, rgba(8, 18, 32, .45));
}
.nb2-fabric-row-title { font-size: 13px; color: var(--text); flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-fabric-row-mode { font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted); }
.nb2-fabric-optin.is-on { border-color: var(--cyan); color: var(--cyan); }
.nb2-fabric-empty { margin: 0; font-size: 13px; color: var(--muted); }
.nb2-fabric-browse[data-browse="empty"] { border-style: dashed; }

/* Fabric availability doctor rung states not already in the shared palette. */
.nb2-doctor-step.is-empty .nb-dot { background: var(--muted); box-shadow: none; }
.nb2-doctor-step.is-empty .nb2-doctor-step-state { color: var(--muted); }
.nb2-doctor-step.is-live .nb-dot { background: #4ade80; box-shadow: 0 0 8px rgba(74, 222, 128, .6); }
.nb2-doctor-step.is-live .nb2-doctor-step-state { color: #4ade80; }

/* Legacy room-direct join demoted to an "advanced" disclosure (still first-class
   + reachable; fabric-less/offline path untouched). */
.nb2-fabric-advanced { margin: 4px 0 0; }
.nb2-fabric-advanced > .nb2-fabric-advanced-summary {
  cursor: pointer; font-size: 12px; color: var(--muted);
  padding: 6px 0; list-style: revert;
}
.nb2-fabric-advanced[open] > .nb2-fabric-advanced-summary { color: var(--text); }

/* The DISTINCT fabric-plane chip — separate from the engagement (learnnav) chip,
   so fabric-vs-engagement state reads distinctly (no-theater: data-fabric-state
   + a probe-verified dot). */
.nb2-learnnet-fabric-chip { gap: 6px; cursor: pointer; }
.nb2-learnnet-fabric-chip[hidden] { display: none; }
.nb2-learnnet-fabric-chip-text { color: var(--text); font-size: 11.5px; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-learnnet-fabric-chip.is-attaching .nb-dot { background: #ffc107; box-shadow: 0 0 8px rgba(255, 193, 7, .55); }
.nb2-learnnet-fabric-chip.is-attached .nb-dot { background: #4ade80; box-shadow: 0 0 8px rgba(74, 222, 128, .6); }
.nb2-learnnet-fabric-chip.is-attached-empty .nb-dot { background: var(--cyan); box-shadow: 0 0 8px rgba(0, 229, 255, .5); }
.nb2-learnnet-fabric-chip.is-unreachable .nb-dot { background: #ff6b6b; box-shadow: 0 0 8px rgba(255, 107, 107, .55); }
.nb2-learnnet-fabric-chip .nb-dot[data-live="unknown"] { background: transparent; border: 1px solid var(--muted); box-shadow: none; }

/* CP3 header connection pill (#nb-connect-chip): the ALWAYS-visible connect-in
   affordance next to "Local autosave". Same state-color language as the fabric
   chip, but never hidden — a first-run learner sees local-only + how to connect,
   the class once connected, and a one-tap Fix when a Nav can't be reached.
   color-never-alone: the text label carries the state in words; dot + icon are
   supplementary. CT canon: cyan is an instrument light (hairline, never a fill). */
.nb-chip--connect { gap: 6px; cursor: pointer; }
.nb-chip--connect .nb-connect-icon { font-size: 12px; line-height: 1; opacity: .85; }
#nb-connect-text { font-size: 11.5px; max-width: 230px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* detached — calm but discoverable: an inviting cyan hairline, never a badge/pulse */
.nb-chip--connect.is-detached { border-color: rgba(0, 229, 255, .45); color: var(--cyan-glow); }
.nb-chip--connect.is-detached .nb-dot { background: transparent; border: 1px solid var(--cyan); box-shadow: none; }
.nb-chip--connect.is-detached:hover,
.nb-chip--connect.is-detached:focus-visible { border-color: var(--cyan); background: rgba(0, 229, 255, .08); }
/* attaching */
.nb-chip--connect.is-attaching .nb-dot { background: #ffc107; box-shadow: 0 0 8px rgba(255, 193, 7, .55); }
/* connected — distinct green (the experience changes) */
.nb-chip--connect.is-attached { border-color: rgba(74, 222, 128, .5); }
.nb-chip--connect.is-attached .nb-dot { background: #4ade80; box-shadow: 0 0 8px rgba(74, 222, 128, .6); }
/* connected, nothing live yet — connected cyan, honest */
.nb-chip--connect.is-attached-empty { border-color: rgba(0, 229, 255, .4); }
.nb-chip--connect.is-attached-empty .nb-dot { background: var(--cyan); box-shadow: 0 0 8px rgba(0, 229, 255, .5); }
/* unreachable — needs a fix (the word "Fix" is in the label; red is supplementary) */
.nb-chip--connect.is-unreachable { border-color: rgba(255, 107, 107, .55); color: #ffb3b3; }
.nb-chip--connect.is-unreachable .nb-dot { background: #ff6b6b; box-shadow: 0 0 8px rgba(255, 107, 107, .55); }
.nb-chip--connect:focus-visible { outline: 2px solid var(--cyan-glow); outline-offset: 2px; }

/* Wave 3 §14: the learner-pulled "coming next" line inside the galaxy panel
   (GD-BIND-06: never a plate, never a popup — one calm line). */
.nb2-galaxy-comingnext {
  margin: 0 0 6px;
  font-size: 12.5px;
  color: var(--muted);
  border-left: 2px solid rgba(0, 229, 255, .45);
  padding-left: 8px;
}

/* Channel: LearnNet + LearnNav join panels */
.nb2-chan-learnnet,
.nb2-chan-learnnav {
  display: grid;
  gap: 10px;
  margin: 12px 0;
  padding: 12px;
  border: 1px solid var(--glass-edge);
  border-radius: 10px;
  background: rgba(10, 17, 40, .35);
}
.nb2-chan-learnnet-hint,
.nb2-chan-learnnav-hint { margin: 0; font-size: 12.5px; opacity: .88; }
.nb2-chan-learnnet-input,
.nb2-chan-learnnav-input {
  width: 100%;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--glass-edge);
  background: rgba(0, 0, 0, .2);
  color: var(--text);
}
.nb2-chan-learnnet-actions,
.nb2-chan-learnnav-identity { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }

/* the Pair-phone dialog (navy panel, centered QR) */
.nb2-pair-dialog { min-width: min(320px, 90vw); }
.nb2-pair-body {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 16px;
  text-align: center;
}
.nb2-pair-qr {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 232px;
  min-width: 232px;
  max-width: 100%;
  padding: 10px;
  border-radius: 12px;
  background: #fff;                 /* white quiet zone so the camera locks the code */
  border: 1px solid var(--hair-strong);
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .04);
}
.nb2-pair-qr:empty { background: transparent; border-style: dashed; }
.nb2-pair-qr-img { display: block; width: 232px; height: 232px; max-width: 100%; image-rendering: pixelated; }
.nb2-pair-url {
  font-family: ui-monospace, "Cascadia Code", "SFMono-Regular", Menlo, Consolas, monospace;
  font-size: 12.5px;
  color: var(--cyan-glow);
  word-break: break-all;
  user-select: all;                 /* one click selects the whole URL to type/copy */
  background: rgba(0, 229, 255, .06);
  border: 1px solid var(--hair);
  border-radius: 6px;
  padding: 6px 10px;
  max-width: 100%;
}
.nb2-pair-url:empty { display: none; }
.nb2-pair-hint { font-size: 12px; line-height: 1.45; max-width: 280px; }

/* ============================================================================
   MOBILE: usable capture surface + editor at ~380px (phone over the LAN)
   The v1 notebook.css @media (max-width:760px) already stacks the four-zone grid
   to one column (notes first). These rules tune the phone surface tighter so the
   busy header rail wraps cleanly, the capture toolbar stays tappable, and the
   editor + dialogs fit a ~380px viewport without horizontal scroll.
   ============================================================================ */
@media (max-width: 760px) {
  /* header rail: let the many actions wrap onto a second row instead of overflowing */
  .nb-rail { flex-wrap: wrap; row-gap: 8px; }
  /* tame the sticky rail on tablets: drop the byline + motto (decorative chrome) and
     give the actions the full row so the wrapped controls don't crowd the wordmark.
     The ⋯ More disclosure (.nb2-more) is the default phone presentation for the
     secondary tools, so the rail stays a calm two-primary strip. */
  .nb-by, .nb-tag { display: none; }
  .nb-rail-actions { flex-wrap: wrap; gap: 6px; row-gap: 6px; width: 100%; }
  /* the Pair-phone button stays prominent but compact on a phone */
  .nb2-pair-btn { order: -1; }

  /* global overflow-x guard (the editor half): no wide media element forces a
     horizontal scroll on the phone (html/body overflow-x is hidden in the base sheet). */
  .nb2-editor .ProseMirror img,
  .nb2-editor .ProseMirror svg,
  .nb2-editor .ProseMirror figure,
  .nb2-editor .ProseMirror pre,
  .nb2-editor .ProseMirror table { max-width: 100%; }

  /* collapse the inner sub-grids (Classify / Recap / IO-hub) to one column so their
     fixed-px tracks can't overflow a phone (rank 17). */
  .nb2-classify-row,
  .nb2-recap-cols,
  .nb2-iohub-cols { grid-template-columns: 1fr; }
}

/* the rail can stop being sticky in landscape (a short phone in landscape has little
   vertical room; a static rail returns that height to the editor). */
@media (max-width: 760px) and (orientation: landscape) {
  .nb-rail { position: static; }
}

/* ============================================================================
   TOUCH ERGONOMICS (pointer: coarse) - tablets AND phones in ONE rule.
   The max-width:420px block below only reached phones; this closes the 421-760px
   tablet touch dead-zone while preserving desktop (fine-pointer) density. The base
   sheet supplies the >=44px hit targets + the iOS no-zoom font lift; here we add the
   v2-specific surfaces (capture chips, rail actions, icon-only library/source acts,
   the drag-handle/resize-grip touch affordances, and the dialog viewport clamps).
   ============================================================================ */
@media (pointer: coarse) {
  /* capture toolbar chips: comfortable tappable size (lifted from the 420px block) */
  .nb-capture-bar .nb-cap { min-width: 92px; min-height: 44px; justify-content: center; }
  /* the rail actions take the full row so wrapped controls stay reachable (lifted) */
  .nb-rail-actions { width: 100%; justify-content: flex-start; }

  /* icon-only boxes: grow the hit area to ~40-44px, keep the glyph centered */
  .nb2-library-note-act,
  .nb2-library-folder-act,
  .nb2-src-close { min-width: 40px; min-height: 40px; display: inline-flex; align-items: center; justify-content: center; }

  /* the per-character resize-grip + drag-handle are HOVER affordances on desktop;
     on touch there is no hover, so reveal them another way (rank 13). */
  .pm-drag-handle { display: none; }   /* no hover gutter on touch; reclaim the width */
  .nb2-editor .ProseMirror { -webkit-tap-highlight-color: transparent; }
  /* cap resizable media so a stored width can't exceed the viewport on a phone */
  .nb2-editor .ProseMirror figure.nb2-photo.nb2-resizable,
  .nb2-editor .ProseMirror div.nb2-sketch.nb2-resizable { max-width: 100%; }

  /* dialogs fit the touch viewport (lifted from 420px so tablets clamp too) */
  .nb2-pair-dialog,
  .nb2-settings,
  .nb-prompt,
  .nb-draw,
  .nb-export-menu { min-width: min(340px, 94vw); max-width: 94vw; }
  /* every dialog scrolls within the viewport instead of overflowing it */
  .nb-dialog { max-height: 92vh; overflow: auto; }
  .nb2-settings-body { min-width: 0; width: min(460px, 92vw); }
  .nb-draw-canvas { height: min(380px, 50vh); }
}

/* reveal the resize-grip when its node is SELECTED (not only on :hover), so a touch
   user who taps the image can grab the grip (rank 13). */
.nb2-editor .ProseMirror .ProseMirror-selectednode .nb2-resize-grip { opacity: .95; }

@media (max-width: 420px) {
  /* ── header: tighten the rail so it doesn't dominate the phone screen ── */
  .nb-rail { padding: 9px 11px; gap: 8px; }
  .nb-rail-actions { width: 100%; justify-content: flex-start; }
  /* search box should not eat the row; let it flex to the remaining width */
  .nb-search { flex: 1 1 100%; min-height: 44px; }
  .nb-search input { width: 100%; min-height: 44px; }
  /* secondary actions stay reachable but de-emphasized; primary export stays bold */
  .nb-rail-actions .nb-btn { font-size: 12px; padding: 6px 9px; }
  #nb-cover-toggle { min-height: 44px; min-width: 44px; padding: 8px 10px; font-size: 12px; }

  /* ── capture toolbar: wrap to a tidy grid of tappable chips (>=44px hit area) ── */
  .nb-notes-head {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "pager" "protect" "caps";
    align-items: stretch;
    gap: 8px;
  }
  .nb-capture-bar,
  body[data-mode="capture"] .nb-capture-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(108px, 1fr));
    gap: 6px;
    width: 100%;
    min-width: 0;
    overflow: visible;
  }
  .nb-capture-bar .nb-cap {
    min-width: 0;
    min-height: 44px;
    justify-content: center;
    font-size: 12.5px;
  }
  /* Cycle 4: park secondary verbs behind More so the editor reaches the fold.
     Type / Highlight / Draw / Photo / Link / Listen stay on the first rows. */
  .nb-cap-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 0;
    padding: 6px 10px;
    border: 1px dashed var(--hair-strong);
    border-radius: 8px;
    background: rgba(159, 179, 200, .06);
    color: var(--muted);
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
  }
  .nb-cap-more:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="clip"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="screen"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="replay"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="video"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="transcript"] { display: none; }

  /* ── editor: full-width, comfortable line length, no min that forces scroll ── */
  .nb2-editor { min-height: 240px; padding-left: 1.1rem; }
  .nb2-editor .ProseMirror { padding: 5px 11px 14px; font-size: calc(15px * var(--nb2-font-scale, 1)); }
  /* .pm-drag-handle hides under @media(pointer:coarse) now (covers tablets too). */

  /* ── search + status bars wrap rather than overflow ── */
  .nb2-search { flex-wrap: wrap; }
  .nb2-search-input { flex: 1 1 100%; order: 2; }
  .nb2-status-bar { font-size: 11px; }
  .nb2-status-hint { flex: 1 1 100%; }   /* push the keyboard hints to their own line */

  /* ── dialogs fit the viewport; QR scales down but stays scannable ── */
  .nb2-pair-dialog,
  .nb-prompt,
  .nb-draw,
  .nb-export-menu { min-width: min(340px, 94vw); max-width: 94vw; }
  .nb2-pair-qr { min-width: 0; min-height: 0; }
  .nb2-pair-qr-img { width: min(232px, 70vw); height: min(232px, 70vw); }
  .nb-draw-canvas { height: 240px; }
}

/* ============================================================================
   CAPTURE / LEARN MODE: the friction gate's visual half
   The JS (setMode/renderCoach/renderMirror) hides the coach strip + the honest
   mirror in Capture mode via the [hidden] attribute. This rule keeps that calm
   under a reduced-motion / no-JS fallback so the friction surfaces stay settled.
   The active-segment cyan signal (.nb-seg--on) is already supplied by v1's
   notebook.css, NOT re-declared here (no duplicate rule). Glass Canon Atrium:
   navy-dominant, cyan = signal, calm.
   ============================================================================ */
body[data-mode="capture"] .nb-coach[hidden],
body[data-mode="capture"] .nb-record-mirror[hidden] { display: none; }
/* Cycle 9: Capture-calm belt — coach + LearnLoop never flash on first land. */
body[data-mode="capture"] #nb-coach,
body[data-mode="capture"] #nb-loop { display: none; }

/* ============================================================================
   LEARNLOOP strip (LS-8) — #nb-loop rides the .nb-coach visual family (same
   gradient field, glass edge, eink + focus-mode rules for free); these are
   only the deltas. The chain warning is DELIBERATELY full-width and readable
   (D-LL: the evidence line renders adjacent to the count, never buried).
   ============================================================================ */
.nb-loop { margin-top: 6px; }
.nb-loop-line { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.nb-loop-phase { font-weight: 600; font-size: 12px; color: var(--cyan); letter-spacing: .06em; text-transform: uppercase; }
.nb-loop-adherence { color: var(--muted); font-size: 12px; }

/* ============================================================================
   DRAWBRIDGE (LearnGalaxy Standard v1.8, LG-RT-07..13, LG-LENS-14) — #nb-drawbridge
   rides the SAME .nb-coach visual family as #nb-loop (no new box model, only
   deltas). The handle is a single always-visible dot (dim/warm/hot, no motion/
   sound/pulse — LG-LENS-14); the slot fills only when the governor arms.
   ============================================================================ */
.nb-drawbridge-handle { display: inline-flex; align-items: center; justify-content: center; width: 10px; height: 10px; margin: 4px 0; border: none; background: transparent; padding: 0; cursor: default; }
.nb-drawbridge-handle-dot { display: block; width: 8px; height: 8px; border-radius: 50%; background: var(--muted, #667); transition: background-color .25s ease; }
.nb-drawbridge-handle[data-state="warm"] .nb-drawbridge-handle-dot { background: var(--cyan-glow, #7CF6FF); }
.nb-drawbridge-handle[data-state="hot"] .nb-drawbridge-handle-dot { background: var(--cyan, #00E5FF); }
.nb-drawbridge-mark { margin: 4px 0; }
.nb-drawbridge-slot { display: flex; flex-direction: column; gap: 6px; }
.nb-drawbridge-card { display: flex; flex-direction: column; gap: 6px; }
.nb-drawbridge-badge { align-self: flex-start; font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--cyan); border: 1px solid var(--cyan-glow, var(--cyan)); border-radius: 999px; padding: 1px 8px; }
.nb-drawbridge-line { font-size: 13px; color: var(--text); }
.nb-drawbridge-actions { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.nb-drawbridge-grade { display: inline-flex; gap: 4px; margin-left: auto; }
.nb-drawbridge-grade-btn { border: none; background: transparent; cursor: pointer; font-size: 14px; padding: 2px 4px; opacity: .7; }
.nb-drawbridge-grade-btn:hover { opacity: 1; }
.nb-drawbridge-card--open .nb-drawbridge-line { white-space: normal; }
/* LR-SPEED 16i (LR-RT-06): the salience-born lane's honest trigger-class
   badges ("Noticed in your transcript" / "Noticed on your screen") — the
   LR-LAY-01 PRODUCT lane, deliberately QUIETER than the cyan author-staged
   pill and sentence-cased (a trigger disclosure, not a brand mark). */
.nb-lr-badge[data-badge="salience-transcript"],
.nb-lr-badge[data-badge="salience-screen"] { color: var(--muted, #8b93a7); border-color: var(--muted, #8b93a7); text-transform: none; letter-spacing: .02em; }
/* LR-SPEED 16k: the zero-valence freshness disclosure — two dates as fact,
   muted, one quiet line under the card. Rendered ONLY when a real stamp
   exists (no stamp -> the element is never created; never a placeholder). */
.nb-lr-freshness { display: block; font-size: 11px; color: var(--muted, #8b93a7); margin-top: 2px; }
.nb-loop-lamp { font-size: 11px; color: var(--cyan); }
.nb-loop-demand { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-top: 6px; }
.nb-loop-demand[hidden] { display: none; }
.nb-loop-demand-text { color: var(--text); font-size: 12px; }
.nb-loop-demand-dismiss { border: 0; background: transparent; color: var(--muted); cursor: pointer; font: inherit; min-height: 44px; min-width: 44px; padding: 8px 10px; }
.nb-loop-demand-dismiss:hover,
.nb-loop-demand-dismiss:focus-visible { color: var(--text); }
.nb-loop-chain { margin-top: 4px; font-size: 12px; color: var(--muted); line-height: 1.45; }
.nb-loop-chain-days { color: var(--text); margin-right: 8px; }
.nb-loop-chain-warning { display: block; margin-top: 2px; }

/* ============================================================================
   CAPTURE = CALM NOTE SURFACE (UDL / cognitive-load round, 2026-06-19)
   Operator: "I should feel like I'm sitting down to take notes with tools at my
   disposal. Not a wall of text explanations I have to sort."
   In Capture (the default mode) we DEFER every pedagogical / organizational
   surface to Learn mode, one toggle away in the rail (#nb-mode-learn). What
   stays at rest: the notebook list (navigation), the editor, the 6 capture tools,
   and the word count. Pure CSS gate riding document.body.dataset.mode (setMode,
   notebook2.js:3797), so render fns are untouched and a repaint can't un-hide a
   gated region. Flip to Learn and every surface returns atomically.
   ============================================================================ */
/* Capture-calm (PDCA Cycle 2): first land is the note, not a cockpit.
   7 Cs, Wait what / drawbridge, Quiz/review chips, Record, Nudges/Lite, and
   the study-partner Quiz rail recede. Recovery is Mode → Learn, View, or ⋯ More.
   Do not build Quiz/Nav/Shout here — only hide/overflow chrome.
   Cues + summary stay (Cornell working surface). Galaxy stays as a labeled door. */
body[data-mode="capture"] #nb-record,          /* Your record (mastery · takeaways · mirror) -> Learn */
body[data-mode="capture"] #nb-flow,            /* 7 Cs strip -> Learn / View */
body[data-mode="capture"] #nb-drawbridge-mark, /* Wait what? */
body[data-mode="capture"] #nb-drawbridge-handle,
body[data-mode="capture"] #nb-drawbridge,
body[data-mode="capture"] #nb-drawbridge-toggle,
body[data-mode="capture"] #nb-drawbridge-cadence,
/* Cycle 11: Calibrate invite mounts after enter (not under #nb-flow). Do not hide it here. */
body[data-mode="capture"] .nb2-review-chip,    /* Quiz / due / flashcard chips — recede, don't code Quiz */
body[data-mode="capture"] #nb2-partner,        /* Quiz me / Find my gaps rail */
body[data-mode="capture"] #nb2-connections,    /* library rail: typed-link Connections (pedagogy) */
body[data-mode="capture"] #nb2-tagtree,        /* library rail: the Tags tree (pedagogy) */
body[data-mode="capture"] #nb2-notetags,       /* library rail: "tags on this note" bar (pedagogy) */
body[data-mode="capture"] #nb2-backlinks,      /* library rail: Linked references (pedagogy) */
body[data-mode="capture"] #nb2-coca,           /* library rail: the Clanker side-ledger (COCA) -> Learn */
body[data-mode="capture"] .nb2-editor-hint,    /* the markdown cheat-sheet line under the editor */
body[data-mode="capture"] .nb2-status-hint,    /* the keybinding legend in the status bar */
body[data-mode="capture"] .nb2-c-label {       /* the 7 Cs zone sub-labels (mountSevenCsLabels) */
  display: none !important;
}
/* the library rail keeps ONLY the notebook list (pedagogy rails hide); CUES stay beside
   NOTES (Cornell), and the Summary/Record bands drop for calm, so Capture is the
   cues+notes working surface, not a bare editor. */
body[data-mode="capture"] .nb-grid {
  grid-template-columns: minmax(150px, 14%) minmax(210px, 27%) 1fr;
  grid-template-areas: "library cues notes" "library summary summary";
  grid-template-rows: 1fr auto;   /* notes fill; the synthesis box sits at the bottom (Cornell) */
  align-content: stretch;
}
body[data-mode="capture"] #nb-summary { grid-area: summary; min-width: 0; }
/* FRAME-FILL (Capture only): make the editable surface fill its grown card so the whole
   desk is writable. Scoped to Capture so Learn's editor keeps its natural height. */
body[data-mode="capture"] .nb2-editor { display: flex; flex-direction: column; }
body[data-mode="capture"] .nb2-editor .ProseMirror { flex: 1 1 auto; }

/* CUES ZONE HEADER — in the narrow Cornell cues column the base .nb-zone-h is a
   no-wrap inline-flex, so the long sub-label ("questions & flags drawn from your
   notes") + the 7 Cs c-label ("Construct · recall prompts") get crushed into a
   cramped multi-line sliver beside the title (visual_receipts: editor-*, synth-*,
   coca-*). Let THIS header wrap so the sub-label + c-label drop cleanly onto their
   own lines under "Cues & recall" — a calm two/three-line header instead of a
   squeeze. */
body[data-mode="learn"] .nb-cues .nb-zone-h,
body[data-mode="capture"] .nb-cues .nb-zone-h {
  flex-wrap: wrap; row-gap: 3px;
}
body[data-mode="learn"] .nb-cues .nb-zone-h .nb-zone-sub,
body[data-mode="learn"] .nb-cues .nb-zone-h .nb2-c-label,
body[data-mode="capture"] .nb-cues .nb-zone-h .nb-zone-sub,
body[data-mode="capture"] .nb-cues .nb-zone-h .nb2-c-label {
  flex-basis: 100%; margin-left: 0;
}

/* SYNTHESIS in Capture: a STATIC box that carries (write it, it saves on blur) plus a link out to
   Learn for the enriched, AI-assisted synthesis. The grading + teach-back machinery is a Learn-only
   affordance, so standalone LearnNote and LearnOS are one surface: Learn just adds the enrichment. */
body[data-mode="capture"] #nb2-teach-btn,
body[data-mode="capture"] #nb2-teach-speak,
body[data-mode="capture"] #nb2-teach-due,
body[data-mode="capture"] #nb2-teach-out,
body[data-mode="capture"] #nb-summary-read,
body[data-mode="capture"] #nb-summary-form button[type="submit"] { display: none; }
.nb-summary-learn-link { display: none; }
body[data-mode="capture"] .nb-summary-learn-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 8px; padding: 0; font: inherit; font-size: 13px; color: var(--cyan); background: none; border: 0; cursor: pointer; }
body[data-mode="capture"] .nb-summary-learn-link:hover { text-decoration: underline; }

/* The synthesis Learn-link (above) is Capture-only; its mirror, the back-link, is Learn-only and
   made PROMINENT (a real button, not a faint link) so leaving the enriched synthesis is always one
   obvious click back to the note. */
.nb-summary-back-link { display: none; }
body[data-mode="learn"] .nb-summary-back-link { display: inline-flex; align-items: center; gap: 6px; margin-top: 10px; padding: 7px 14px; font: inherit; font-size: 13px; font-weight: 600; color: var(--cyan); background: rgba(0, 229, 255, .10); border: 1px solid var(--cyan); border-radius: 8px; cursor: pointer; }
body[data-mode="learn"] .nb-summary-back-link:hover { background: rgba(0, 229, 255, .18); }
body.eink .nb-summary-back-link { color: #000 !important; border-color: #000 !important; background: #fff !important; }

/* Capture toolbar balanced reflow (refine5 studio nit #1). In the working/learn
   view the notes column is narrower than capture mode, so the 10 flex chips wrap
   a ragged 7+3. A grid of equal auto-fit tracks reflows them into aligned, balanced
   rows at whatever width the column allows — calm, no tools hidden (Tenet VII; the
   transcript chip stays visible, which the cross-surface e2e requires). Scoped to
   non-capture surfaces (capture mode already fits one row) and to >=421px so the
   phone's own <=420px flex block is untouched. */
@media (min-width: 421px) {
  body:not([data-mode="capture"]) .nb-capture-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(94px, 1fr));
    gap: 6px;
    align-items: stretch;
  }
  body:not([data-mode="capture"]) .nb-capture-bar .nb-cap { justify-content: center; }
}
.nb-cap-more { display: none; }
@media (max-width: 480px) {
  .nb-notes { min-width: 0; overflow-x: visible; }
  .nb-notes-head { min-width: 0; overflow: visible; }
  .nb-capture-bar,
  body[data-mode="capture"] .nb-capture-bar {
    display: grid !important;
    grid-template-columns: repeat(auto-fit, minmax(108px, 1fr));
    width: 100%;
    min-width: 0;
    overflow: visible;
  }
  .nb-capture-bar .nb-cap,
  body[data-mode="capture"] .nb-capture-bar .nb-cap {
    min-width: 0;
    min-height: 44px;
    justify-content: center;
  }
  .nb-cap-more {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 44px;
    min-width: 0;
    padding: 6px 10px;
    border: 1px dashed var(--hair-strong);
    border-radius: 8px;
    background: rgba(159, 179, 200, .06);
    color: var(--muted);
    font: inherit;
    font-size: 12.5px;
    cursor: pointer;
  }
  .nb-cap-more:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="clip"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="screen"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="replay"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="video"],
  .nb-capture-bar:not(.is-more-open) .nb-cap[data-cap="transcript"] { display: none; }
}

/* LearnNote wordmark: brand shield (navy field, cyan ascent peak) + name + byline + motto. */
.nb-brand { display: inline-flex; align-items: center; }
.nb-shield { display: block; width: 19px; height: 22px; }
.nb-shield--hero { width: 40px; height: 47px; }   /* the welcome hero wears a larger shield than the header wordmark */
.nb-by { display: block; font-size: 10px; line-height: 1.25; color: var(--muted); letter-spacing: .02em; }
body.eink .nb-shield path { fill: #ffffff !important; stroke: #000000 !important; }
body.eink .nb-hero-mark { background: transparent !important; }   /* shield now owns the mark; drop the old filled-diamond box */

/* Calibrate invite (UDL): a calm, dismissible nudge on a new empty notebook. Encourages, never blocks. */
.nb-cal-invite { display: flex; align-items: center; justify-content: space-between; gap: 14px; margin: 6px 0 0; padding: 8px 14px; border: 1px solid var(--hair); border-radius: 8px; background: rgba(159, 179, 200, .06); color: var(--text); font-size: .88rem; }
.nb-cal-invite[hidden] { display: none; }
.nb-cal-invite-body { display: flex; align-items: center; gap: 10px; min-width: 0; }
.nb-cal-invite-icon { color: var(--cyan); font-weight: 600; flex: none; }
.nb-cal-invite-text { line-height: 1.4; }
.nb-cal-invite-acts { display: flex; align-items: center; gap: 10px; flex: none; }
.nb-cal-invite-dismiss { border: 0; background: none; color: var(--muted); cursor: pointer; font: inherit; font-size: .85rem; min-height: 44px; min-width: 44px; padding: 8px 12px; }
.nb-cal-invite-dismiss:hover { color: var(--text); }
body.eink .nb-cal-invite { background: #fff; border-color: #000; }

/* ============================================================================
   LEARNING SURFACE — the pointing UI (start-screen picker · chip · hint).
   Calm by canon (VII): hairline borders, muted rest state, cyan reserved for the
   ONE chosen card. POINTING ≠ GATING is the JS law (applySurfaceOrder reorders,
   never hides); nothing here may visually bury a tool either — no badges, no
   pulses, the chip sits as quietly as its .nb-chip siblings.
   ============================================================================ */
/* Fluent Opening: one primary door. The surface picker stays in the DOM for
   tests and later-session pointing, but recedes on the hero (body.nb-hero-open).
   Nothing here gates a tool. Type floor is 14px for chrome, 16px for titles. */
.nb-hero { max-width: 600px; }
.nb-hero-workflow { width: 100%; max-width: 560px; display: grid; grid-template-columns: minmax(0, 1fr); gap: 20px; align-items: start; margin: 8px auto 0; text-align: left; }
.nb-hero-start, .nb-surface { min-width: 0; }
.nb-hero-step-head, .nb-surface-head { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; align-items: start; margin-bottom: 12px; }
.nb-hero-step-index { display: none; }
.nb-hero-step-copy { min-width: 0; }
.nb-hero-step-title, .nb-surface-title { margin: 1px 0 0; color: var(--text); font: 650 16px/1.35 Montserrat, Inter, sans-serif; letter-spacing: 0; }
.nb-hero-step-sub, .nb-surface-sub { margin: 4px 0 0; color: var(--muted); font-size: 14px; line-height: 1.5; }
.nb-hero-start .nb-hero-actions {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  max-width: none;
  margin: 0;
  align-items: stretch;
}
.nb-hero-start .nb-hero-actions > .nb-btn {
  width: auto;
  min-width: 0;
  min-height: 44px;
}
/* Cycle 12: identity leftover — title/sub type pinned; doors recede (hairline +
   left cyan). Swell stays on .nb-hero-page only. Doors never travel. */
.nb-hero-title {
  font: 700 28px/1.2 Montserrat, Inter, sans-serif;
  letter-spacing: -0.01em;
  margin: 0;
  transform: none;
}
.nb-hero-sub {
  color: var(--muted);
  font-size: 16px;
  line-height: 1.55;
  margin: 8px 0 0;
  max-width: 36em;
  transform: none;
}
.nb-hero-door {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  min-height: 64px;
  padding: 12px 14px;
  border-radius: 8px;
  text-align: left;
  border: 1px solid var(--hair);
  border-left: 3px solid var(--cyan);
  background: color-mix(in srgb, var(--navy-panel, #0F1D3A) 55%, transparent);
  box-shadow: inset 0 1px 0 var(--hair);
  transform: none;
  transition: box-shadow 240ms var(--nb-fluid), border-color 180ms ease, background 180ms ease, filter 180ms ease;
}
.nb-hero-door:hover { transform: none; filter: brightness(1.04); }
.nb-hero-door:active { transform: none; transition-duration: 90ms; }
.nb-btn--primary.nb-hero-door {
  background: color-mix(in srgb, var(--navy-panel, #0F1D3A) 55%, transparent);
  color: var(--text);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--cyan);
  box-shadow: inset 0 1px 0 var(--hair);
}
.nb-hero-door-title { color: inherit; font: 650 16px/1.3 Montserrat, Inter, sans-serif; transform: none; }
.nb-hero-door-detail { margin-top: 4px; color: var(--muted); font-size: 14px; font-weight: 400; line-height: 1.45; transform: none; }
.nb-btn--primary .nb-hero-door-detail { color: var(--muted); }
#nb-cover-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  min-width: 44px;
  padding: 8px 12px;
  box-sizing: border-box;
  flex: 0 0 auto;
  color: var(--text);
  background: color-mix(in srgb, var(--navy-panel) 78%, transparent);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--cyan);
  border-radius: 8px;
  font: 650 12px/1.2 Montserrat, Inter, sans-serif;
  letter-spacing: .02em;
  cursor: pointer;
  transform: none;
  box-shadow: inset 0 1px 0 var(--hair);
}
#nb-cover-toggle:hover, #nb-cover-toggle:focus-visible {
  color: var(--text);
  border-color: var(--hair-strong);
  background: color-mix(in srgb, var(--navy-crest) 70%, transparent);
}
#nb-cover-toggle:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
#nb-cover-toggle[aria-pressed="true"] {
  color: var(--text);
  border-color: var(--hair-strong);
  box-shadow: inset 0 1px 0 var(--hair);
}
.nb-cover-toggle-glyph { display: inline-flex; color: var(--text); opacity: .88; transform: none; }
.nb-cover-toggle-glyph--lift { display: none; }
#nb-cover-toggle[aria-pressed="true"] .nb-cover-toggle-glyph--shut { display: none; }
#nb-cover-toggle[aria-pressed="true"] .nb-cover-toggle-glyph--lift { display: inline-flex; }
.nb-cover-toggle-word { transform: none; }
.nb-cover-narrow { display: none; }
@media (max-width: 480px) {
  .nb-hero-start .nb-hero-actions { gap: 8px; }
  .nb-hero-door { padding: 10px 11px; }
  .nb-cover-wide { display: none; }
  .nb-cover-narrow { display: inline; }
}
body.eink #nb-cover-toggle,
body.nb2-eink #nb-cover-toggle {
  background: #fff; color: #000; border-color: #000; box-shadow: none;
}
body.nb-hero-open .nb-rail,
body.nb-cover-closed .nb-rail {
  position: sticky;
  top: 0;
  z-index: 22;
}
/* Pressed = freeze in place. Only Open cover may act; Home / doors / editor stay locked.
   Dead chrome must not look clickable: recede + no hover. Not color-alone (opacity +
   cursor + flattened affordance). Open cover stays the one live 44px control. */
body.nb-cover-closed #nb-hero,
body.nb-cover-closed #nb-main,
body.nb-cover-closed #nb-flow,
body.nb-cover-closed .nb-rail-actions,
body.nb-cover-closed #nb-home,
body.nb-cover-closed #nb-hud,
body.nb-cover-closed .nb-kicker-text,
body.nb-cover-closed .nb-kicker-divider,
body.nb-cover-closed .nb2-consent-overlay,
body.nb-cover-closed .nb2-consent-firstrun {
  pointer-events: none;
}
body.nb-cover-closed .nb-rail-actions,
body.nb-cover-closed .nb-kicker-text,
body.nb-cover-closed .nb-kicker-divider {
  opacity: .38;
  filter: saturate(.55);
  cursor: default;
}
body.nb-cover-closed #nb-home {
  opacity: .58;
  filter: saturate(.7);
  cursor: not-allowed;
}
body.nb-cover-closed #nb-home:hover .nb-name,
body.nb-cover-closed #nb-home:focus-visible .nb-name { color: inherit; }
body.nb-cover-closed #nb-home:hover .nb-brand { text-shadow: none; }
body.nb-cover-closed #nb-home:focus-visible { outline: none; }
body.nb-cover-closed #nb-hud {
  cursor: default;
  box-shadow: none;
}
body.nb-cover-closed #nb-hud-status,
body.nb-cover-closed #nb-hud-mode,
body.nb-cover-closed #nb-hud-version {
  cursor: default;
  opacity: 1;
}
body.nb-cover-closed #nb-hud-setup,
body.nb-cover-closed #nb-hud-setup:disabled {
  opacity: .42;
  filter: saturate(.55);
  cursor: not-allowed;
  box-shadow: none;
}
body.nb-cover-closed #nb-hud-setup:hover,
body.nb-cover-closed #nb-hud-setup:focus-visible,
body.nb-cover-closed #nb-hud-setup:disabled:hover {
  border-color: var(--hair);
  background: transparent;
  outline: none;
}
body.nb-cover-closed .nb-kicker-text .nb-source {
  cursor: not-allowed;
}
body.nb-cover-closed .nb-rail-actions .nb-chip,
body.nb-cover-closed .nb-rail-actions .nb-btn,
body.nb-cover-closed .nb-rail-actions button {
  cursor: default;
}
/* Park first-run who-flow under the glass — do not leave a second live dialog. */
body.nb-cover-closed .nb2-consent-overlay {
  z-index: 16;
  pointer-events: none;
}
body.nb-cover-closed #nb-cover-toggle {
  pointer-events: auto;
  opacity: 1;
  filter: none;
  cursor: pointer;
}

/* Fluent Opening motion — Glass Canon is an ocean under the glass.
   Undulate ONLY #nb-hero-glass / .nb-hero-page. Ink never travels: settle is
   opacity, glyphs stay put. Swell is a continuous sine, many stops, 0%===100%
   at the zero-crossing, linear shorthand + per-keyframe linear (no ease-in-out
   seam). Door hover/active may lift the button box, not the letters. Note body
   does not undulate. Reduced-motion + e-ink: still. */
@keyframes nb-fluid-in {
  from { opacity: 0; }
  to { opacity: 1; }
}
@keyframes nb-fluid-mark {
  0% { opacity: 0; }
  68% { opacity: 1; }
  100% { opacity: 1; }
}
@keyframes nb-ocean-swell-mark {
  0%, 100% { transform: translateY(0) scale(1); animation-timing-function: linear; }
  12.5% { transform: translateY(-2.8px) scale(1); animation-timing-function: linear; }
  25% { transform: translateY(-4px) scale(1); animation-timing-function: linear; }
  37.5% { transform: translateY(-2.8px) scale(1); animation-timing-function: linear; }
  50% { transform: translateY(0) scale(1); animation-timing-function: linear; }
  62.5% { transform: translateY(2.8px) scale(1); animation-timing-function: linear; }
  75% { transform: translateY(4px) scale(1); animation-timing-function: linear; }
  87.5% { transform: translateY(2.8px) scale(1); animation-timing-function: linear; }
}
@keyframes nb-ocean-swell {
  0%, 100% { transform: translateY(0); animation-timing-function: linear; }
  12.5% { transform: translateY(-4.2px); animation-timing-function: linear; }
  25% { transform: translateY(-6px); animation-timing-function: linear; }
  37.5% { transform: translateY(-4.2px); animation-timing-function: linear; }
  50% { transform: translateY(0); animation-timing-function: linear; }
  62.5% { transform: translateY(4.2px); animation-timing-function: linear; }
  75% { transform: translateY(6px); animation-timing-function: linear; }
  87.5% { transform: translateY(4.2px); animation-timing-function: linear; }
}
@keyframes nb-ocean-swell-soft {
  0%, 100% { transform: translateY(0); animation-timing-function: linear; }
  12.5% { transform: translateY(-1.1px); animation-timing-function: linear; }
  25% { transform: translateY(-1.6px); animation-timing-function: linear; }
  37.5% { transform: translateY(-1.1px); animation-timing-function: linear; }
  50% { transform: translateY(0); animation-timing-function: linear; }
  62.5% { transform: translateY(1.1px); animation-timing-function: linear; }
  75% { transform: translateY(1.6px); animation-timing-function: linear; }
  87.5% { transform: translateY(1.1px); animation-timing-function: linear; }
}
#nb-hero-glass:not([hidden]) .nb-hero-page {
  inset: 0; /* cover sheet is still — no ocean bleed / watery sine */
}
#nb-hero.nb-hero--settle .nb-hero-mark { animation: nb-fluid-mark 640ms var(--nb-fluid) both; }
#nb-hero.nb-hero--settle .nb-hero-title { animation: nb-fluid-in 560ms var(--nb-fluid) 50ms both; }
#nb-hero.nb-hero--settle .nb-hero-sub { animation: nb-fluid-in 580ms var(--nb-fluid) 90ms both; }
#nb-hero.nb-hero--settle #nb-cover:not([hidden]) { animation: nb-fluid-in 600ms var(--nb-fluid) 120ms both; }
#nb-hero.nb-hero--settle .nb-hero-workflow { animation: nb-fluid-in 600ms var(--nb-fluid) 140ms both; }
#nb-hero.nb-hero--settle .nb2-consent-firstrun { animation: nb-fluid-in 560ms var(--nb-fluid) 200ms both; }
.nb-hero-title,
.nb-hero-sub,
.nb-hero-door,
.nb-hero-door-title,
.nb-hero-door-detail,
.nb-hero-step-title,
.nb-hero-step-sub,
.nb-hero-step-copy,
.nb2-consent-firstrun,
.nb2-consent-overlay,
.nb2-consent-card,
.nb2-editor,
.nb2-editor .ProseMirror {
  transform: none;
}
#nb-hero.nb-hero--undulate .nb-hero-door:hover,
#nb-hero.nb-hero--undulate .nb-hero-door:active,
#nb-hero.nb-hero--undulate .nb-hero-door:focus-visible { filter: brightness(1.04); }
#nb-main.nb-main--enter { animation: nb-fluid-in 420ms var(--nb-fluid) both; }
@media (prefers-reduced-motion: reduce) {
  #nb-hero.nb-hero--settle .nb-hero-mark,
  #nb-hero.nb-hero--settle .nb-hero-title,
  #nb-hero.nb-hero--settle .nb-hero-sub,
  #nb-hero.nb-hero--settle #nb-cover:not([hidden]),
  #nb-hero.nb-hero--settle .nb-hero-workflow,
  #nb-hero.nb-hero--settle .nb2-consent-firstrun,
  #nb-hero-glass:not([hidden]) .nb-hero-page,
  #nb-main.nb-main--enter { animation: none !important; }
  .nb-hero-door { transition: none; }
  .nb-hero-door:hover, .nb-hero-door:active { transform: none; }
}
body.eink #nb-hero.nb-hero--settle .nb-hero-mark,
body.eink #nb-hero.nb-hero--settle .nb-hero-title,
body.eink #nb-hero.nb-hero--settle .nb-hero-sub,
body.eink #nb-hero.nb-hero--settle #nb-cover:not([hidden]),
body.eink #nb-hero.nb-hero--settle .nb-hero-workflow,
body.eink #nb-hero.nb-hero--settle .nb2-consent-firstrun,
body.eink #nb-hero-glass:not([hidden]) .nb-hero-page,
body.eink #nb-main.nb-main--enter,
body.nb2-eink #nb-hero.nb-hero--settle .nb-hero-mark,
body.nb2-eink #nb-hero-glass:not([hidden]) .nb-hero-page,
body.nb2-eink #nb-main.nb-main--enter { animation: none !important; }
body.eink .nb-hero-door, body.nb2-eink .nb-hero-door { transition: none; }
body.eink .nb-hero-door:hover, body.eink .nb-hero-door:active,
body.nb2-eink .nb-hero-door:hover, body.nb2-eink .nb-hero-door:active { transform: none; }
.nb2-learnfloat-offer {
  width: 100%; max-width: none; margin: 0; padding: 8px 12px;
  border: 1px solid var(--hair); border-left: 3px solid var(--cyan);
  border-radius: 8px; background: rgba(159, 179, 200, .06);
  display: flex; align-items: center;
  justify-content: space-between; gap: 12px; text-align: left;
}
.nb2-learnfloat-offer[hidden] { display: none; }
.nb2-learnfloat-offer-copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.nb2-learnfloat-offer-copy strong { color: var(--text); font: 650 12.5px/1.35 Montserrat, Inter, sans-serif; }
.nb2-learnfloat-offer-copy span { color: var(--muted); font-size: 13px; line-height: 1.45; }
.nb2-learnfloat-offer-actions { display: flex; align-items: center; gap: 7px; flex: none; }
.nb2-learnfloat-offer-actions .nb-btn { min-height: 44px; }
.nb2-file-honesty {
  margin: 0; padding: 7px 12px; border: 1px dashed var(--hair-strong);
  border-radius: 8px; color: var(--muted); font-size: 12.5px; line-height: 1.45;
}
.nb2-file-honesty[hidden] { display: none; }
.nb-empty-glass {
  margin: 0 0 8px;
  padding: 10px 12px;
  border: 1px solid var(--hair);
  border-left: 3px solid rgba(84, 239, 255, .28);
  border-radius: 8px;
  background: rgba(159, 179, 200, .05);
}
.nb-empty-glass[hidden] { display: none; }
.nb-empty-lead { margin: 0 0 4px; color: var(--text); font-size: 13.5px; line-height: 1.4; font-weight: 650; }
.nb-empty-why { margin: 0 0 8px; color: var(--muted); font-size: 13px; line-height: 1.45; }
.nb-empty-glass .nb-btn { min-height: 44px; }
#nb-summary, #nb-record {
  background: rgba(159, 179, 200, .05);
  box-shadow: none;
}
#nb-summary[data-empty] .nb-summary-learn-link,
#nb-summary[data-empty] .nb-summary-form button[type="submit"] {
  color: var(--muted);
  font-weight: 500;
}
#nb-record[data-empty] .nb-record-section { display: none; }
.nb-cues[data-empty] .nb-cues-divider,
.nb-cues[data-empty] .nb-cues-seeded,
.nb-cues[data-empty] .nb-cues-own { display: none; }
.nb-cues[data-empty] .nb-cue-filters { opacity: .72; }
.nb-cues {
  background: rgba(159, 179, 200, .04);
  box-shadow: none;
}
body.eink .nb-empty-glass, body.nb2-eink .nb-empty-glass {
  border-left-color: #000; background: transparent;
}
body.eink .nb2-learnfloat-offer, body.nb2-eink .nb2-learnfloat-offer {
  border-left-color: #000; background: transparent;
}
@media (prefers-reduced-motion: reduce) {
  .nb2-learnfloat-offer { transition: none; }
}
.nb-surface { width: 100%; margin: 0; }
.nb-surface-group { display: flex; flex-direction: column; gap: 8px; }
.nb-surface-card { display: grid; grid-template-columns: 26px minmax(0, 1fr) 18px; align-items: center; gap: 10px; min-height: 52px; min-width: 0; padding: 10px 12px; border: 1px solid var(--hair-strong); border-radius: 8px; background: rgba(22,42,77,.38); color: var(--muted); font: inherit; line-height: 1.3; text-align: left; cursor: pointer; transition: border-color .15s ease, color .15s ease, background .15s ease, box-shadow .15s ease; }
.nb-surface-card:hover { color: var(--text); border-color: var(--glass-edge); background: rgba(22,42,77,.58); }
.nb-surface-card:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
/* WCAG 1.4.1: the chosen card carries a redundant non-color cue (weight + the cyan
   underline), mirroring the .nb-seg--on discipline — never the background wash alone. */
.nb-surface-card.is-on { color: var(--text); border-color: rgba(84,239,255,.48); background: rgba(84,239,255,.07); box-shadow: inset 3px 0 0 var(--cyan); }
.nb-surface-card-icon { display: inline-grid; place-items: center; width: 24px; height: 24px; color: #9fb3c8; }
.nb-surface-icon { display: block; width: 19px; height: 19px; }
.nb-surface-card.is-on .nb-surface-card-icon { color: var(--cyan); }
.nb-surface-card-label { min-width: 0; overflow-wrap: anywhere; color: inherit; font: 650 12.5px/1.35 Montserrat, Inter, sans-serif; }
.nb-surface-card-mark { display: inline-grid; place-items: center; width: 18px; height: 18px; color: var(--cyan); opacity: 0; transform: scale(.8); transition: opacity .15s ease, transform .15s ease; }
.nb-surface-card-mark .nb-surface-icon { width: 16px; height: 16px; stroke-width: 2.2; }
.nb-surface-card.is-on .nb-surface-card-mark { opacity: 1; transform: scale(1); }
.nb-surface-blurb { margin: 9px 0 0 48px; color: var(--muted); font-size: 11px; line-height: 1.5; min-height: 3em; }
.nb-surface-chip-icon { display: inline-grid; place-items: center; }
.nb-surface-chip-icon .nb-surface-icon { width: 15px; height: 15px; }
body.eink .nb-surface-card-icon, body.eink .nb-surface-card.is-on .nb-surface-card-icon, body.eink .nb-surface-card-mark { color: #000; }

@media (prefers-reduced-motion: reduce) {
  .nb-surface-card-mark { transition: none; }
}

/* VERIFIED PERSISTENCE: concise text + glyphs carry every state; color is a
   redundant Glass Canon signal. There is deliberately no pulse or animation. */
.nb2-notes-heading { display: flex; align-items: center; gap: 10px; min-width: 0; flex-wrap: wrap; }
.nb2-protection { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; inline-size: min(340px, 100%); min-width: 0; }
.nb2-persistence, .nb2-secondary { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; align-items: center; gap: 6px; inline-size: 100%; min-width: 0; min-height: 30px; box-sizing: border-box; padding: 4px 7px; border: 1px dotted var(--muted); border-radius: 6px; background: rgba(10, 17, 40, .24); color: var(--muted); font: inherit; font-size: 11.5px; line-height: 1.35; text-align: left; }
.nb2-preservation-kind { flex: none; color: var(--muted); font-size: 9.5px; font-weight: 750; text-transform: uppercase; letter-spacing: 0; }
.nb2-persistence-status { display: inline-flex; align-items: center; gap: 5px; flex: 1 1 auto; min-width: 0; max-width: 100%; white-space: nowrap; }
.nb2-persistence-icon { flex: none; min-width: 1.2em; text-align: center; font-weight: 800; }
#nb2-persistence-label { min-width: 0; overflow: visible; text-overflow: clip; white-space: normal; }
.nb2-persistence-retry { display: inline-flex; align-items: center; gap: 4px; min-height: 28px; border: 1px solid currentColor; border-radius: 5px; background: transparent; color: inherit; font: inherit; font-weight: 700; cursor: pointer; }
.nb2-persistence-retry[hidden] { display: none; }
.nb2-persistence-retry:focus-visible { outline: 2px solid currentColor; outline-offset: 2px; }
.nb2-persistence[data-state="ready"] { color: var(--muted); border-style: dotted; }
.nb2-persistence[data-state="saving"] { color: var(--warn, #F59E0B); border-style: dashed; background: rgba(245, 158, 11, .07); }
.nb2-persistence[data-state="preserved"] { color: var(--persistence-ok, #54EFFF); border-style: double; background: transparent; }
.nb2-persistence[data-state="error"] { color: var(--err, #FF8A8A); border-style: solid; background: rgba(255, 138, 138, .10); }
.nb2-secondary { grid-template-columns: auto minmax(0, 1fr); cursor: pointer; }
.nb2-secondary:hover { border-color: var(--hair-strong); color: var(--text); }
.nb2-secondary:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; }
.nb2-secondary:disabled { cursor: wait; opacity: 1; }
.nb2-secondary-status { display: inline-flex; align-items: center; gap: 5px; min-width: 0; white-space: nowrap; }
#nb2-secondary-label { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-secondary-lamp { flex: none; width: 7px; height: 7px; border: 1px solid currentColor; border-radius: 50%; background: transparent; box-sizing: border-box; }
.nb2-secondary[data-state="recovery"] { color: var(--cyan-glow, #54EFFF); border-style: dashed; }
.nb2-secondary[data-state="recovery"] .nb2-secondary-lamp { border-radius: 1px; transform: rotate(45deg); }
.nb2-secondary[data-state="attention"], .nb2-secondary[data-state="stale"], .nb2-secondary[data-state="writing"], .nb2-secondary[data-state="provider-paused"], .nb2-secondary[data-state="provider-unavailable"] { color: var(--warn, #F59E0B); border-style: dashed; background: rgba(245, 158, 11, .07); }
.nb2-secondary[data-state="connected"] { color: var(--azure, #18A7FF); border-style: dotted; }
.nb2-secondary[data-state="written"], .nb2-secondary[data-state="verified"] { color: var(--persistence-ok, #54EFFF); border-style: double; background: rgba(84, 239, 255, .04); }
.nb2-secondary[data-state="written"] .nb2-secondary-lamp, .nb2-secondary[data-state="verified"] .nb2-secondary-lamp { background: currentColor; }
.nb2-secondary[data-state="error"], .nb2-secondary[data-state="location-changed"] { color: var(--err, #FF8A8A); border-style: solid; background: rgba(255, 138, 138, .10); }
.nb2-secondary[data-state="error"] .nb2-secondary-lamp, .nb2-secondary[data-state="location-changed"] .nb2-secondary-lamp { border-radius: 1px; background: currentColor; transform: rotate(45deg); }

/* A stable 3px editor edge mirrors the cue. Dotted/dashed/double/solid geometry
   remains meaningful when color is unavailable. */
.nb-notes[data-persistence-state] .nb2-editor { border-inline-start-width: 3px; }
.nb-notes[data-persistence-state="ready"] .nb2-editor { border-inline-start-color: var(--muted); border-inline-start-style: dotted; }
.nb-notes[data-persistence-state="saving"] .nb2-editor { border-inline-start-color: var(--warn, #F59E0B); border-inline-start-style: dashed; }
.nb-notes[data-persistence-state="preserved"] .nb2-editor { border-inline-start-color: var(--persistence-ok, #54EFFF); border-inline-start-style: double; }
.nb-notes[data-persistence-state="error"] .nb2-editor { border-inline-start-color: var(--err, #FF8A8A); border-inline-start-style: solid; }

/* The unbound top chip repeats the state in words and with a distinct dot shape. */
#nb-local[data-save-state] { flex: 0 1 auto; inline-size: auto; min-width: 0; max-width: none; width: max-content; box-sizing: border-box; justify-content: flex-start; font-weight: 650; border-inline-start-width: 3px; }
#nb-local[data-save-state] #nb-local-text { min-width: 0; overflow: visible; text-overflow: clip; white-space: nowrap; }
#nb-local[data-save-state="ready"] { color: var(--muted); border-inline-start-style: dotted; }
#nb-local[data-save-state="ready"] .nb-dot { background: transparent; border: 1px solid currentColor; box-shadow: none; }
#nb-local[data-save-state="saving"] { color: var(--warn, #F59E0B); border-color: currentColor; border-inline-start-style: dashed; background: rgba(245, 158, 11, .07); }
#nb-local[data-save-state="saving"] .nb-dot { border-radius: 2px; background: currentColor; box-shadow: none; }
#nb-local[data-save-state="preserved"] { color: var(--persistence-ok, #54EFFF); border-color: currentColor; border-inline-start-style: double; background: rgba(84, 239, 255, .06); }
#nb-local[data-save-state="preserved"] .nb-dot { background: currentColor; box-shadow: none; }
#nb-local[data-save-state="error"] { border-inline-start-style: solid; }
#nb-local[data-save-state="error"] .nb-dot { border-radius: 1px; background: currentColor; box-shadow: none; transform: rotate(45deg); }

@media (max-width: 560px) {
  .nb2-notes-heading { align-items: flex-start; }
  .nb2-protection { inline-size: 100%; }
  .nb2-persistence, .nb2-secondary { inline-size: 100%; min-width: 0; }
}

@media (max-width: 720px) {
  .nb-hero-workflow { grid-template-columns: minmax(0, 1fr); gap: 24px; max-width: 520px; }
  .nb-surface-blurb { min-height: 1.5em; }
  .nb2-learnfloat-offer { max-width: none; align-items: stretch; flex-direction: column; gap: 10px; }
  .nb2-learnfloat-offer-actions { justify-content: flex-start; flex-wrap: wrap; }
}

/* the pointing chip: a BUTTON wearing the .nb-chip coat (reset the UA button skin) */
.nb-chip--surface {
  font: inherit;
  font-size: 12px;
  cursor: pointer;
  transition: border-color .15s ease, color .15s ease;
  min-height: 44px;
  padding: 6px 12px;
  white-space: nowrap;
  flex: 0 0 auto;
  max-width: none;
  box-sizing: border-box;
}
.nb-chip--surface:hover { color: var(--text); border-color: var(--glass-edge); }
.nb-chip--surface:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
#nb-surface-chip-text { overflow: visible; text-overflow: clip; white-space: nowrap; }
.nb-surface-chip-change { color: var(--muted); opacity: .75; font-size: 11px; }
.nb-chip--surface:hover .nb-surface-chip-change { color: var(--text); opacity: 1; }

/* Cycle 6: kicker source/anchor wrap — no “Untitl…” ellipsis. Beats notebook.css. */
.nb-kicker-text { min-width: 0; max-width: 100%; }
.nb-kicker-text .nb-source,
.nb-kicker-text .nb-anchor {
  white-space: normal;
  overflow: visible;
  text-overflow: clip;
  overflow-wrap: anywhere;
}
.nb-kicker-text .nb-source:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
@media (max-width: 480px) {
  .nb-kicker-text .nb-source { font-size: 13px; line-height: 1.3; }
  .nb-kicker-text .nb-anchor { font-size: 11.5px; }
}
@media (max-width: 480px) {
  /* Cycle 5: keep “Just my notes”; hide · change so the rail does not truncate into nonsense. */
  .nb-surface-chip-change { display: none; }
  .nb-chip--surface { padding: 6px 10px; }
}

/* the one-time hint line by the capture bar (mirrors .nb-cal-invite: calm, dismissible) */
.nb-surface-hint { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin: 6px 0 0; padding: 7px 12px; border: 1px solid var(--hair); border-radius: 8px; background: rgba(159,179,200,.06); color: var(--text); font-size: .85rem; }
.nb-surface-hint[hidden] { display: none; }
.nb-surface-hint-text { line-height: 1.45; }
.nb-surface-hint-x { flex: none; border: 0; background: none; color: var(--muted); cursor: pointer; font: inherit; font-size: .82rem; }
.nb-surface-hint-x:hover { color: var(--text); }

/* the chip's compact chooser dialog: same cards, left-aligned in the panel */
.nb2-surface-dlg { max-width: 560px; }
.nb2-surface-dlg .nb-surface-group { justify-content: flex-start; }
.nb2-surface-dlg .nb-surface-blurb { text-align: left; }

/* paper mode: flat ink, same geometry (the generic body.eink .nb-chip rule covers the chip) */
body.eink .nb-surface-card, body.eink .nb-surface-hint { background: #fff; border-color: #000; color: #000; }
body.eink .nb-surface-card.is-on { box-shadow: inset 0 -2px 0 #000; }

/* ============================================================================
   CYAN ONE-SIGNAL (Capture): demote ambient cyan to slate so a SINGLE anchor
   remains: the 'now' step in the 7Cs strip. Rebinds ONLY --cyan-glow/--ok/
   --glass-edge, NEVER --cyan, so :focus-visible (notebook.css:50) keeps crisp #00E5FF
   and the editor's focus-within box-shadow HALO stays cyan. (The focus-within border used
   --glass-edge, so it is intentionally demoted to the neutral hairline in Capture along
   with the rest of the ambient cyan, focus is still signalled by the cyan halo.) Placed
   BEFORE the e-ink block so e-ink's later !important rules win when both classes are set.
   ============================================================================ */
body[data-mode="capture"] {
  --cyan-glow: #9FB3C8;              /* atmosphere cyan -> muted slate */
  --ok: #6B7E99;                    /* success/'ready' cyan -> quiet slate (text still carries meaning) */
  --glass-edge: var(--hair-strong); /* translucent-cyan 'active' border -> neutral hairline */
}
/* mop up the hardcoded rgba(0,229,255,*) washes the tokens can't reach (Capture only) */
body[data-mode="capture"] .nb2-attention-dot { background: var(--muted); box-shadow: none; }
/* the "due for review" pill is cyan in Learn (a real signal); in Capture demote it to a
   quiet slate so the ONLY cyan in Capture stays the 7Cs 'now' step (one-signal discipline). */
body[data-mode="capture"] .nb-cue-due { background: var(--muted); color: var(--navy-panel); }
body[data-mode="capture"] .nb-cue--due { box-shadow: inset 3px 0 0 0 var(--muted); }
body[data-mode="capture"] .nb-seg--on { background: rgba(159,179,200,.16); }
body[data-mode="capture"] .nb-cue-filter--on { background: rgba(159,179,200,.16); }
body[data-mode="capture"] .nb-cap--on,
body[data-mode="capture"] .nb-shape--on { color: var(--text); border-color: var(--hair-strong); background: rgba(159,179,200,.14); }
body[data-mode="capture"] .nb2-library-note.is-active { background: rgba(159,179,200,.10); box-shadow: inset 3px 0 0 var(--text, #F8FAFC); }
body[data-mode="capture"] .nb2-library-note.is-active .nb2-library-note-mark { color: var(--text); font-weight: 700; text-shadow: none; }
body[data-mode="capture"] .nb-cstep.is-done { color: var(--muted); }
body[data-mode="capture"] .nb-cstep.is-done .nb-cstep-tick { color: var(--muted); }
body[data-mode="capture"] .nb-zone-h::before { background: var(--hair-strong); box-shadow: none; }
/* stragglers the token rebind can't reach: brand mark, status-dot glow, 7Cs pivot arrow */
body[data-mode="capture"] .nb-brand { color: var(--text); text-shadow: none; }
body[data-mode="capture"] .nb-chip--local .nb-dot,
body[data-mode="capture"] .nb-chip[data-synced="true"] .nb-dot { background: var(--muted); box-shadow: none; }
body[data-mode="capture"] .nb-flow-pivot { color: var(--hair-strong); }
/* cue-column stragglers: the build-prompts button + the active tag chip keep a
   hardcoded cyan border/wash that --cyan (never rebound) would otherwise preserve. */
body[data-mode="capture"] .nb2-cpc-build { border-color: var(--hair-strong); background: rgba(159,179,200,.10); }
body[data-mode="capture"] .nb2-cpc-build:hover { background: rgba(159,179,200,.16); box-shadow: 0 0 0 3px rgba(159,179,200,.10); }
body[data-mode="capture"] .nb2-tag-chip.is-on { background: rgba(159,179,200,.14); }
/* more cue-column stragglers: teach-prompt accent, the # glyph,
   the seeded-cue mark + the active star: all hardcoded var(--cyan)/rgba(0,229,255). */
/* Teach-back EXPECTANCY ("you'll teach this to a curious beginner…") is a LEARN affordance —
   it sets the expect-to-teach intention before study. It has no place on the Capture tab (here
   you just get notes + cues down), so hide it entirely in capture mode. */
body[data-mode="capture"] .nb2-teach-expectancy { display: none; }
body[data-mode="capture"] .nb2-tag-hash { color: var(--muted); }
body[data-mode="capture"] .nb-cue--seeded .nb-cue-mark { color: var(--muted); text-shadow: none; }
body[data-mode="capture"] .nb-cue-act--star.is-on { color: var(--muted); text-shadow: none; }
/* WCAG AA: --ok rebound to slate #6B7E99 fails 4.5:1 as small TEXT on the lighter navy
   panels; re-point the small --ok TEXT consumers to --muted (#9FB3C8, ~6.6-7.8:1). The
   token stays #6B7E99 for its non-text dot/border accents. */
body[data-mode="capture"] .nb2-sevencs-step.is-done .nb2-sevencs-status,
body[data-mode="capture"] .nb2-iohub-report-line.is-ok,
body[data-mode="capture"] .nb2-iohub-report-fidelity.is-lossless,
body[data-mode="capture"] .iris-focus-state.is-mastered { color: var(--muted); }

/* THE single cyan signal in Capture = the 'now' step (the obvious next action in the
   7Cs strip). Inherits the un-demoted --cyan; restated here as the one retune point;
   do NOT add a second cyan anchor. */
body[data-mode="capture"] .nb-cstep.is-now {
  color: var(--cyan); border-color: var(--cyan);
  background: rgba(0,229,255,.10);
  box-shadow: 0 0 0 1px var(--cyan), 0 0 9px rgba(0,229,255,.32);
}
/* protect the ONE signal: hovering a NON-active 7Cs chip must not paint a 2nd cyan
   (:not(.is-now) keeps the now-chip cyan on hover); and the editor caret is calm ink in
   Capture, not a blinking 2nd cyan on the empty hero. Learn keeps both cyans. */
body[data-mode="capture"] .nb-cstep:not(.is-now):hover { border-color: var(--hair-strong); color: var(--text); }
body[data-mode="capture"] .nb2-editor .ProseMirror { caret-color: var(--text); }
/* the 'Notes' zone heading labels a self-evident editor in Capture, demote it to a quiet
   uppercase eyebrow (kept in the DOM for aria-labelledby) so the editor owns its zone. */
body[data-mode="capture"] #nb-notes-h { font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
body[data-mode="capture"] #nb-notes-h::before { display: none; }

/* FSRS spaced-repetition "due for review" surfacing (Wave 2, gripe #6). A reviewed
   cue whose interval has elapsed resurfaces to the top of the column with this pill.
   Glass Canon Atrium: cyan = signal (the one accent), navy stays dominant. */
.nb-cue-due {
  display: inline-block;
  margin-top: 4px;
  padding: 1px 8px;
  border-radius: 999px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--on-cyan-ink);
  background: var(--cyan);
}
.nb-cue--due { box-shadow: inset 3px 0 0 0 var(--cyan); }

/* ============================================================================
   LOCAL SOVEREIGN STUDY PARTNER: Lane B (the notebook that ASKS)

   Glass Canon Atrium / calm register: navy-dominant field, cyan as the single
   signal accent (the ✦ mark), Montserrat, --hair borders, --muted for secondary
   copy. The card mirrors the coach's calm strip (notebook.css:122-134) so it
   reads as part of the Atrium, not a chatbot bubble. The partner is rendered
   ONLY in Learn mode (the affordance carries [hidden] in Capture, toggled by
   renderPartner()); these styles never assume capture.
   ============================================================================ */

/* ── the affordance: an inline action group sitting in the header rail ── */
.nb2-partner {
  display: inline-flex;
  align-items: center;
  gap: 7px;
}
.nb2-partner[hidden] { display: none; }

/* "Extract text": server-side OCR affordance on a SELECTED photo. Same Atrium
   register as the study-partner rail: navy ground (inherited from .nb-btn), cyan
   = the actionable signal, calm-muted when the launcher is unreachable or no
   photo is selected. Inherits .nb-btn .nb-btn--small; only the signal/disabled
   states are declared here. Hidden (display:none) unless a photo is selected. */
.nb2-ocr-btn[hidden] { display: none; }
.nb2-ocr-btn[disabled] { opacity: .5; cursor: not-allowed; }
.nb2-ocr-btn:not([disabled]) { color: var(--cyan, #00e5ff); }

.nb2-partner-label {
  color: var(--muted);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 12px;
  margin-right: 1px;
  white-space: nowrap;
}

/* ── the prompt card: a calm read-and-act panel under the editor ── */
/* Mirrors .nb-coach (notebook.css:122): same gradient field, glass edge, and
   inset glow, so it belongs to the same Atrium. It is session-only chrome: the
   QUESTION is set via textContent only and is never written into the notes. */
.nb2-partner-card {
  margin: 12px 0 0;
  padding: 13px 18px;
  border: 1px solid var(--glass-edge, rgba(84, 239, 255, .22));
  border-radius: 11px;
  background: linear-gradient(135deg, rgba(0,229,255,.08), rgba(22,42,77,.32));
  box-shadow: inset 0 0 26px rgba(0,229,255,.05);
}
.nb2-partner-card[hidden] { display: none; }
.nb2-partner-card-head {
  display: flex;
  align-items: center;
  gap: 9px;
}
.nb2-partner-mark {
  color: var(--cyan);
  font-size: 16px;
  line-height: 1;
  flex: none;
  text-shadow: 0 0 10px rgba(0,229,255,.5);   /* cyan = the single signal accent */
}
.nb2-partner-kind {
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-weight: 600;
  font-size: 13px;
  color: var(--muted);
  letter-spacing: 0.01em;
  flex: 1 1 auto;
  min-width: 0;
}
#nb2-partner-card-x { flex: none; }          /* the ✕ reuses .nb-coach-off styling */
/* the read-and-act question: primary readable weight, the focus of the card */
.nb2-partner-question {
  margin-top: 7px;
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 15px;
  line-height: 1.5;
  color: var(--text);
  font-weight: 500;
}
.nb2-partner-foot {
  margin-top: 7px;
  color: var(--muted);
  font-size: 12px;
  line-height: 1.45;
}

/* Practice surface card: compact LearnQuiz/LearnEngine loop, mounted by
   notebook2.js only as session chrome and hidden outside the Practice surface. */
.nb2-practice-card {
  margin: 12px 0 0;
  padding: 13px 16px;
  border: 1px solid var(--glass-edge, rgba(84, 239, 255, .22));
  border-radius: 10px;
  background: linear-gradient(135deg, rgba(0,229,255,.07), rgba(22,42,77,.28));
  box-shadow: inset 0 0 22px rgba(0,229,255,.045);
}
.nb2-practice-card[hidden] { display: none; }
.nb2-practice-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 7px;
}
.nb2-practice-mark {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid var(--cyan, #00e5ff);
  color: var(--cyan, #00e5ff);
  font-weight: 700;
  line-height: 1;
  flex: none;
}
.nb2-practice-kind {
  color: var(--muted);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 12.5px;
  font-weight: 600;
}
.nb2-practice-question {
  color: var(--text);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 15px;
  font-weight: 600;
  line-height: 1.45;
}
.nb2-practice-choices {
  display: grid;
  gap: 7px;
  margin-top: 10px;
}
.nb2-practice-choice {
  width: 100%;
  text-align: left;
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  background: rgba(10,17,40,.42);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.35;
  padding: 8px 10px;
  cursor: pointer;
}
.nb2-practice-choice:hover,
.nb2-practice-choice:focus-visible {
  border-color: var(--glass-edge);
  outline: none;
}
.nb2-practice-choice.is-selected {
  border-color: rgba(84,239,255,.58);
  background: rgba(84,239,255,.09);
  box-shadow: inset 3px 0 0 var(--cyan);
}
.nb2-practice-why-wrap {
  display: grid;
  gap: 6px;
  margin-top: 10px;
}
.nb2-practice-why-prompt {
  color: var(--muted);
  font-size: 12px;
  line-height: 1.4;
}
.nb2-practice-why {
  min-height: 72px;
  resize: vertical;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: rgba(7,15,31,.45);
  color: var(--text);
  font: inherit;
  font-size: 13px;
  line-height: 1.45;
  padding: 8px 10px;
}
.nb2-practice-why:focus {
  outline: 2px solid rgba(0,229,255,.25);
  border-color: var(--glass-edge);
}

/* ENC-05 exam fidelity — scaffolds & renderings step aside */
html.nb--true-conditions .nb-coach,
body.nb--true-conditions .nb-coach,
html.nb--true-conditions #nb2-partner,
body.nb--true-conditions #nb2-partner,
html.nb--true-conditions .nb2-partner-card,
body.nb--true-conditions .nb2-partner-card {
  display: none !important;
}
html.nb--true-conditions .nb2-practice-why-wrap,
body.nb--true-conditions .nb2-practice-why-wrap {
  display: none !important;
}
.nb2-practice-actions {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 10px;
}
.nb2-practice-feedback {
  flex: 1 1 180px;
  min-width: 0;
  font-size: 12px;
  line-height: 1.4;
}

/* Focus mode dims the partner card alongside the coach (it lives inside
   .nb-notes, which focus mode otherwise keeps bright). Mirrors the coach dim
   rules above (notebook2.css:213, 330). */
body.nb2-focus .nb2-partner-card {
  opacity: .34;
  filter: saturate(.7);
  transition: opacity .2s ease, filter .2s ease;
}
body.nb2-focus .nb2-partner-card:focus-within { opacity: 1; filter: none; }
@media (prefers-reduced-motion: reduce) {
  body.nb2-focus .nb2-partner-card { transition: none !important; }
}

/* ============================================================================
   QUESTION DRIFT — quiet, local learner-side question queue.
   It mounts dynamically immediately above #nb-cues-seeded.  The rail is absent
   outside a verified same-origin, live, admitted class; these rules do not add
   any standalone or offline chrome.
   ========================================================================== */
.nb-question-drift {
  display: grid;
  gap: 9px;
  margin: 12px 0 10px;
  padding: 11px;
  border: 1px solid rgba(84, 239, 255, .25);
  border-radius: 10px;
  background: linear-gradient(145deg, rgba(23, 57, 90, .34), rgba(8, 22, 46, .38));
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .035);
}
.nb-question-drift__head,
.nb-question-drift__actions {
  display: flex;
  align-items: center;
  gap: 7px;
  flex-wrap: wrap;
}
.nb-question-drift__head { justify-content: space-between; }
.nb-question-drift__title {
  margin: 0;
  color: var(--text);
  font-size: 13px;
  line-height: 1.2;
  letter-spacing: .01em;
}
.nb-question-drift__live,
.nb-question-drift__disclosure,
.nb-question-drift__retention,
.nb-question-drift__quiet,
.nb-question-drift__feedback,
.nb-question-drift__match,
.nb-question-drift__sent {
  margin: 0;
  color: var(--muted);
  font-size: 11.5px;
  line-height: 1.42;
}
.nb-question-drift__disclosure { color: rgba(219, 242, 255, .84); }
.nb-question-drift__retention { color: rgba(182, 207, 230, .82); }
.nb-question-drift__feedback[data-state="error"] { color: #ffb5b5; }
.nb-question-drift__candidate {
  display: grid;
  gap: 7px;
  padding: 9px;
  border: 1px solid rgba(150, 193, 229, .2);
  border-radius: 8px;
  background: rgba(4, 15, 34, .28);
}
.nb-question-drift__topic {
  margin: 0;
  color: var(--text);
  font-size: 12px;
  font-weight: 650;
  line-height: 1.3;
}
.nb-question-drift__label {
  display: grid;
  gap: 4px;
  color: var(--muted);
  font-size: 11px;
  line-height: 1.3;
}
.nb-question-drift__text {
  width: 100%;
  min-height: 62px;
  resize: vertical;
  box-sizing: border-box;
  border: 1px solid var(--hair);
  border-radius: 7px;
  background: rgba(5, 14, 30, .62);
  color: var(--text);
  font: inherit;
  font-size: 12px;
  line-height: 1.42;
  padding: 7px 8px;
}
.nb-question-drift__text:focus-visible,
.nb-question-drift__ask:focus-visible,
.nb-question-drift__link:focus-visible,
.nb-question-drift__pause:focus-visible,
.nb-question-drift__text-action:focus-visible {
  outline: 2px solid rgba(84, 239, 255, .75);
  outline-offset: 2px;
}
.nb-question-drift__ask,
.nb-question-drift__link,
.nb-question-drift__pause,
.nb-question-drift__text-action {
  min-height: 30px;
  border-radius: 7px;
  font: inherit;
  font-size: 11.5px;
  line-height: 1.15;
  cursor: pointer;
}
.nb-question-drift__ask,
.nb-question-drift__link {
  border: 1px solid rgba(84, 239, 255, .52);
  background: rgba(37, 132, 165, .24);
  color: #e9fbff;
  padding: 6px 9px;
}
.nb-question-drift__pause,
.nb-question-drift__text-action {
  border: 0;
  background: transparent;
  color: #b6e8f3;
  padding: 5px 2px;
  text-decoration: underline;
  text-underline-offset: 2px;
}
.nb-question-drift__sent { color: #a7f0ce; }
.nb-question-drift button:disabled {
  cursor: not-allowed;
  opacity: .55;
}
@media (max-width: 700px) {
  .nb-question-drift { margin-inline: 0; padding: 10px; }
  .nb-question-drift__ask,
  .nb-question-drift__link { flex: 1 1 140px; }
}
@media (prefers-reduced-motion: reduce) {
  .nb-question-drift,
  .nb-question-drift * { scroll-behavior: auto !important; transition: none !important; animation: none !important; }
}

/* ============================================================================
   ZONE 0: THE LIBRARY (multi-note sidebar)

   A left rail of folder groups + note rows over ONE corpus. It mounts as a NEW
   `library` grid area on .nb-grid (#nb-main), prepended before `cues`. This rule
   loads AFTER `@import "/notebook/notebook.css"` (top of this file), so it overrides the
   two-column grid there (notebook.css:149) by source order, no !important needed.

   Glass Canon Atrium: navy-dominant field, --hair separators, cyan = the single
   signal for the ACTIVE note + active-note marker; everything else navy/muted, calm.
   ============================================================================ */

/* re-declare the four-zone grid with a leading `library` rail. Mirrors the
   notebook.css base (flex/gap/padding/max-width/centering) and only ADDS the column. */
.nb-grid {
  grid-template-columns: minmax(168px, 16%) minmax(220px, 28%) 1fr;
  grid-template-areas:
    "library cues    notes"
    "library summary summary"
    "library record  record";
  /* FRAME-FILL: widen the centered measure (no floor -> no 761-1099px overflow). Width is
     GLOBAL (benign in Learn, just a wider centered grid). The VERTICAL fill (1fr rows +
     align-content:stretch) is Capture-ONLY (on body[data-mode="capture"] .nb-grid), so
     Learn's 5 zones keep their natural top-packed flow instead of summary/record being
     pushed below the fold. */
  max-width: min(1440px, 92vw);
}

.nb2-library {
  grid-area: library;
  display: flex;
  flex-direction: column;
  gap: 10px;
  padding: 14px 12px;
  min-width: 0;
  align-self: start;
  position: sticky;
  top: 12px;
  max-height: calc(100vh - 24px);
  background: linear-gradient(135deg, rgba(37,67,113,.30), rgba(22,42,77,.26));
  border: 1px solid var(--hair);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

/* header: title + the New note / New folder actions */
.nb2-library-head {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.nb2-library-title { font-size: 14px; }
.nb2-library-actions { display: flex; gap: 6px; flex-wrap: wrap; }
.nb2-library-actions .nb-btn { flex: 1 1 auto; font-size: 12.5px; padding: 8px 12px; min-height: 44px; box-sizing: border-box; }

/* the scrollable note list */
.nb2-library-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
  min-height: 0;
  padding-right: 2px;
}
.nb2-library-empty { font-size: 11.5px; }

/* a folder group: a quiet header, then its note rows */
.nb2-library-group { display: flex; flex-direction: column; gap: 3px; }
.nb2-library-notes { display: flex; flex-direction: column; gap: 3px; }   /* the per-folder role="list" of note rows */
.nb2-library-folder {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 2px 4px;
  color: var(--muted);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
}
.nb2-library-folder-mark { color: var(--hair-strong); font-size: 10px; line-height: 1; flex: none; }
.nb2-library-folder-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* the per-folder rename affordance: mirrors .nb2-library-note-acts: revealed on
   folder hover/focus-within, pushed to the trailing edge, calm. The ✎ button
   re-points every note in the folder via Library.renameFolder (atomic). */
.nb2-library-folder-acts {
  display: flex;
  gap: 2px;
  flex: none;
  margin-left: auto;                 /* push the act to the trailing edge */
  opacity: 0;
  transition: opacity .12s ease;
}
.nb2-library-folder:hover .nb2-library-folder-acts,
.nb2-library-folder:focus-within .nb2-library-folder-acts { opacity: 1; }
.nb2-library-folder-act {
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--muted);
  font-size: 10px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 5px;
  text-transform: none;              /* the folder header uppercases; the icon shouldn't inherit it */
  transition: color .12s ease, background .12s ease;
}
.nb2-library-folder-act:hover { color: var(--text); background: rgba(0,229,255,.10); }
/* WCAG AA focus ring: cyan signal. The acts row already un-hides on
   :focus-within (above), so a keyboard user tabbing to the ✎ sees both the
   revealed control and its ring. */
.nb2-library-folder-act:focus-visible {
  opacity: 1;
  color: var(--text);
  outline: 2px solid var(--cyan, #00E5FF);
  outline-offset: 2px;
  border-radius: 5px;
}

/* a note row: marker + clickable title + hover affordances */
.nb2-library-note {
  display: flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  padding: 6px 10px;
  border: 1px solid transparent;
  border-radius: 8px;
  background: rgba(10,17,40,.30);
  transition: border-color .12s ease, background .12s ease;
}
.nb2-library-note:hover { border-color: var(--hair); background: rgba(10,17,40,.45); }
.nb2-library-note.is-active {
  border-color: var(--glass-edge);
  background: rgba(0,229,255,.08);
  box-shadow: inset 3px 0 0 var(--text, #F8FAFC);  /* WCAG 1.4.1: stripe + text, not color-alone */
}
.nb2-library-note-mark { flex: none; font-size: 12px; line-height: 1.2; color: var(--muted); }
.nb2-library-note.is-active .nb2-library-note-mark {
  color: var(--text);
  font-weight: 700;
  text-shadow: none;
}
.nb2-library-note-title {
  flex: 1 1 auto;
  min-width: 0;
  min-height: 44px;
  text-align: left;
  background: transparent;
  border: 0;
  cursor: pointer;
  color: var(--text);
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  font-size: 13.5px;
  line-height: 1.3;
  padding: 0 2px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nb2-library-note-title:hover { color: var(--text); text-decoration: underline; }
.nb2-library-note-title:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 2px; border-radius: 5px; }
.nb2-library-note.is-active .nb2-library-note-title { font-weight: 700; text-decoration: underline; text-underline-offset: 3px; }
.nb2-library-note-here {
  flex: none;
  font-size: 10px;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--text);
  border: 1px solid var(--hair-strong, #2a3f6b);
  border-radius: 999px;
  padding: 4px 8px;
  white-space: nowrap;
}

/* the per-note rename / move / delete affordances: revealed on row hover, calm */
.nb2-library-note-acts {
  display: flex;
  gap: 2px;
  flex: none;
  /* Collapse to zero width when hidden so the invisible (opacity:0) actions do
     not reserve flex space and starve the note title (which was crushed to ~23px,
     rendering "My notebook" as "M..."). Expand on hover/focus. */
  max-width: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity .12s ease, max-width .12s ease;
}
.nb2-library-note:hover .nb2-library-note-acts,
.nb2-library-note:focus-within .nb2-library-note-acts { opacity: 1; max-width: 144px; }
.nb2-library-note-act {
  border: 0;
  background: transparent;
  cursor: pointer;
  color: var(--muted);
  font-size: 14px;
  line-height: 1;
  padding: 3px 4px;
  border-radius: 5px;
  transition: color .12s ease, background .12s ease;
  min-width: 44px; min-height: 44px;
  display: inline-flex; align-items: center; justify-content: center;
}
.nb2-library-note-act:hover { color: var(--text); background: rgba(0,229,255,.10); }
.nb2-library-note-del:hover:not(:disabled) { color: var(--err, #FF8A8A); background: rgba(255,138,138,.12); }
.nb2-library-note-act:disabled { opacity: .35; cursor: not-allowed; }

/* ── EPISTEMIC STATUS chip (LS-5.10-01): a small, calm pill on each note row
   naming where the note's content stands - source / mine / AI / pending. Same
   pill chrome as .nb2-inbox-tag; a quiet per-status edge tint, never a shout. */
.nb2-epi-chip {
  flex: none;
  font-size: 9.5px; line-height: 1; letter-spacing: .04em; text-transform: uppercase;
  color: var(--muted, #9FB3C8);
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 999px;
  padding: 2px 7px;
  background: transparent;
  cursor: pointer;
  transition: color .12s ease, border-color .12s ease;
}
.nb2-epi-chip:hover { color: var(--text, #e8eef7); border-color: var(--hair-strong, rgba(255,255,255,.18)); }
.nb2-epi--source-fact { color: var(--cyan-glow, #54efff); border-color: rgba(0,229,255,.35); }
.nb2-epi--llm-transform { color: #C9A7FF; border-color: rgba(201,167,255,.35); }
.nb2-epi--pending-approval { color: var(--warn, #F59E0B); border-color: rgba(245,158,11,.35); }

/* ── MOBILE: collapse the library rail INTO the one-column stack. Mirrors the v1
   notebook.css breakpoint (max-width:760px, which stacks the four zones to one
   column, notes first); the library sits at the TOP of that stack so the student
   picks a note before the editor. ── */
@media (max-width: 760px) {
  .nb-grid {
    grid-template-columns: 1fr;
    /* EDITOR-FIRST MOBILE IA: on a phone the WRITING SURFACE comes first so a
       note-taker lands on the editor, not after scrolling past the library + cues.
       (Render-truth: the editor previously sat ~814px down on a 375px viewport.)
       The library + cues stay reachable, just BELOW notes. Named grid areas place
       each child regardless of source order, so this is the area-string analog of
       CSS `order` and leaves desktop (>760px) untouched. */
    grid-template-areas: "notes" "library" "cues" "summary" "record";
    /* FRAME-FILL desktop rules go inert on the phone stack */
    max-width: 100%;
    grid-template-rows: none;
    align-content: start;
  }
  /* Capture mode carries its own .nb-grid override (notebook2.css:949) at
     specificity (0,2,1) that is NOT inside any media query, so it out-specifies
     the (0,1,0) single-column stack above and would keep the phone surface
     3-column (fixed-px minimums 150+210 overflow a ~380px viewport, real
     horizontal scroll). Re-assert the stack here at matching specificity (0,2,1),
     source-later and inside the breakpoint, so Capture stacks like Learn on a
     phone. Summary/Record are display:none in Capture (notebook2.css:935-936),
     so only library/notes/cues need areas. */
  body[data-mode="capture"] .nb-grid {
    grid-template-columns: 1fr;
    /* EDITOR-FIRST MOBILE IA (Capture): notes (the writing surface) leads; the
       notebook library + cues follow, still reachable by scrolling. */
    grid-template-areas: "notes" "library" "cues";
    grid-template-rows: none;   /* reset Capture's desktop 1fr row so the phone stack flows naturally */
  }
  /* The central View control may remove Cues entirely; otherwise it reflows here. */
  .nb2-library {
    position: static;
    max-height: none;
    flex-direction: column;
  }
  .nb2-library-list { max-height: 40vh; }
}

/* ============================================================================
   CONNECTIONS panel (typed knowledge graph): bottom of the library rail.

   Lives inside .nb2-library so it inherits the rail's sticky column + its
   max-height; only local styling is new. Glass Canon Atrium: navy field, --hair
   separators, --muted for the relation label, --cyan-glow as the single signal on
   the clickable target. Mirrors the .nb2-library-* idiom (rows, hover, reveal-on-
   hover affordance) so it reads as one rail, not a bolted-on widget.
   ============================================================================ */
.nb2-connections[data-empty] {
  opacity: .78;
  padding-top: 6px;
}
.nb2-connections[data-empty] .nb2-connections-empty { font-size: 12px; }
.nb2-connections {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding-top: 10px;
  border-top: 1px solid var(--hair);
}
.nb2-connections-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}
.nb2-connections-title { font-size: 13px; }
.nb2-conn-add { font-size: 11.5px; padding: 4px 8px; flex: none; }
.nb2-connections-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  overflow-y: auto;
  min-height: 0;
  max-height: 30vh;
  padding-right: 2px;
}
.nb2-connections-empty { font-size: 11.5px; }

.nb2-conn-row {
  display: flex;
  align-items: baseline;
  gap: 6px;
  padding: 4px 6px;
  border: 1px solid transparent;
  border-radius: 8px;
}
.nb2-conn-row:hover { border-color: var(--hair); background: rgba(10,17,40,.45); }
.nb2-conn-rel { color: var(--muted); font-size: 11px; flex: none; }   /* the relation, muted */
.nb2-conn-target {                                                     /* cyan = the clickable signal */
  color: var(--cyan-glow);
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  text-align: left;
  cursor: pointer;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.nb2-conn-target:hover { text-decoration: underline; }
.nb2-conn-target:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; border-radius: 4px; }

/* Cognitive Cache (COCA) — the Local Clanker's side-ledger in the rail. Glass-Canon: calm,
   grouped; the cyan instrument-light only on the open-count badge + the checkboxes. */
.nb2-coca {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 10px; border-top: 1px solid var(--hair);
}
.nb2-coca[hidden] { display: none; }
.nb2-coca-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.nb2-coca-title { font-size: 13px; }
.nb2-coca-badge:not(:empty) {
  font-size: 10.5px; font-weight: 700; line-height: 1;
  min-width: 16px; padding: 3px 6px; text-align: center;
  color: var(--on-cyan-ink); background: var(--cyan); border-radius: 999px; flex: none;   /* ink token so paper (eink) flips it to white on the black badge — was hardcoded #07142b = black-on-black on paper (refine 5) */
}
.nb2-coca-list {
  display: flex; flex-direction: column; gap: 3px;
  overflow-y: auto; min-height: 0; max-height: 30vh; padding-right: 2px;
}
.nb2-coca-empty { font-size: 11.5px; }
.nb2-coca-group-h {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted); margin-top: 6px;
}
.nb2-coca-group-h:first-child { margin-top: 0; }
.nb2-coca-row {
  display: flex; align-items: baseline; gap: 7px;
  padding: 4px 6px; border: 1px solid transparent; border-radius: 8px;
}
.nb2-coca-row:hover { border-color: var(--hair); background: rgba(10,17,40,.45); }
.nb2-coca-box { margin: 0; flex: none; accent-color: var(--cyan); cursor: pointer; transform: translateY(1px); }
.nb2-coca-text { font-size: 12px; color: var(--text); line-height: 1.35; }
.nb2-coca-row.is-done .nb2-coca-text { color: var(--muted); text-decoration: line-through; }

/* Synthesis invitation — Local Clanker's draft, OFFERED above the Cues board (Tenet III:
   never auto-applied). Glass-Canon: a calm cyan-edged card that slides in; the learner decides. */
@keyframes nb2-synth-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
.nb2-synth-invite {
  margin: 0 0 10px; padding: 10px 12px;
  border: 1px solid rgba(84, 239, 255, .3);
  border-left: 3px solid var(--cyan);
  border-radius: 10px;
  background: rgba(10, 17, 40, .5);
  display: flex; flex-direction: column; gap: 8px;
  animation: nb2-synth-in .22s ease-out;
}
.nb2-synth-head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.nb2-synth-badge { font-size: 11px; font-weight: 700; color: var(--cyan); flex: none; }
.nb2-synth-count { font-size: 11.5px; color: var(--muted); }
.nb2-synth-preview { margin: 0; padding-left: 18px; display: flex; flex-direction: column; gap: 2px; }
.nb2-synth-preview li { font-size: 12px; color: var(--text); line-height: 1.35; }
.nb2-synth-more { color: var(--muted); list-style: none; margin-left: -18px; font-size: 11px; }
.nb2-synth-actions { display: flex; gap: 8px; flex-wrap: wrap; }
@media (prefers-reduced-motion: reduce) { .nb2-synth-invite { animation: none; } }
.nb2-conn-x {
  margin-left: auto;
  flex: none;
  color: var(--muted);
  background: none;
  border: 0;
  cursor: pointer;
  font-size: 11px;
  line-height: 1;
  opacity: 0;
}
.nb2-conn-row:hover .nb2-conn-x,
.nb2-conn-row:focus-within .nb2-conn-x { opacity: 1; }
.nb2-conn-x:hover { color: var(--err, #FF8A8A); }
.nb2-conn-x:focus-visible { opacity: 1; outline: 2px solid var(--cyan); outline-offset: 2px; border-radius: 4px; }

/* ── +Link dialog: a target-note picker + a relation picker. Reuses the shared
   .nb-dialog / .nb-dialog-head / .nb-dialog-actions / .nb-btn chrome (notebook.css);
   only the two-field body is local. ── */
.nb2-link-dialog { min-width: 280px; max-width: 360px; }
.nb2-link-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 12px 14px 4px;
}
.nb2-link-label { color: var(--muted); font-size: 11.5px; margin-top: 4px; }
.nb2-link-select {
  width: 100%;
  font: inherit;
  font-size: 13px;
  color: var(--text, #e6edf6);
  background: rgba(10,17,40,.55);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 6px 8px;
}
.nb2-link-select:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; border-color: var(--cyan); }

/* On the mobile stack the Connections list keeps a sane cap inside the rail. */
@media (max-width: 760px) {
  .nb2-connections-list { max-height: 32vh; }
}

/* ── "Open an existing note" chooser: two big UDL doors (a synced folder / a backup
   file). Reuses .nb-dialog / .nb-dialog-head chrome; only the doors are local. Glass
   Canon: navy panel, hairline border, cyan as an instrument light on hover — not a fill. ── */
.nb2-open-existing { width: min(444px, 94vw); }
.nb2-open-existing-body { display: flex; flex-direction: column; gap: 12px; padding: 8px 16px 16px; }
.nb2-open-existing-body .nb2-setting-hint { margin: 0 2px 2px; }
.nb2-open-door {
  display: flex; align-items: flex-start; gap: 13px; width: 100%; text-align: left;
  padding: 14px 15px; border-radius: 13px;
  background: var(--navy-panel, #13254a); border: 1px solid var(--hair, #24365f);
  color: var(--text, #e6edf6); cursor: pointer;
  transition: border-color .16s ease, background .16s ease, box-shadow .16s ease, transform .1s ease;
}
.nb2-open-door:hover { border-color: rgba(84, 239, 255, .5); background: rgba(84, 239, 255, .06); box-shadow: 0 1px 10px rgba(0, 0, 0, .28); }
.nb2-open-door:active { transform: translateY(1px); }
.nb2-open-door:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 2px; }
.nb2-open-door-i { font-size: 22px; line-height: 1; flex: none; margin-top: 1px; }
.nb2-open-door-text { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.nb2-open-door-h { font-family: Montserrat, Inter, sans-serif; font-size: 14px; font-weight: 600; color: var(--text, #e6edf6); }
.nb2-open-door:hover .nb2-open-door-h { color: var(--cyan, #54efff); }
.nb2-open-door-sub { font-size: 12px; line-height: 1.45; color: var(--muted, #93a4c4); }

/* ── Clickable wordmark = "home": close the notebook back to the start screen. Reset the button
   chrome to zero so it still lays out EXACTLY like the old wordmark (no shift); a cyan hover + focus
   ring make it obviously interactive (Glass Canon: cyan is the instrument light, not a fill). ── */
.nb-home {
  display: flex; align-items: center; gap: 11px;
  background: none; border: 0; margin: 0; padding: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer; border-radius: 8px;
}
.nb-home .nb-name { transition: color .15s ease; }
.nb-home:hover .nb-name { color: var(--cyan, #54efff); }
.nb-home:hover .nb-brand { text-shadow: 0 0 16px rgba(0, 229, 255, .8); }
.nb-home:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 3px; }

/* ── NOTEBOOK COVER: the learning-weather panel on the hero/start screen. Glass Canon — a calm read
   of what's holding vs slipping; the retention meter IS the TTL, cyan/amber the instrument light. ── */
.nb-cover { width: 100%; max-width: 520px; margin: 16px auto 18px; text-align: left; border-block: 1px solid var(--hair); background: transparent; padding: 14px 0; }
.nb-return { display: grid; gap: 10px; margin: 0 0 12px; }
.nb-return-title { margin: 0; color: var(--text); font: 650 16px/1.35 Montserrat, Inter, sans-serif; }
.nb-return-dl { display: grid; gap: 8px; margin: 0; }
.nb-return-row { display: grid; grid-template-columns: minmax(7.5em, 32%) minmax(0, 1fr); gap: 10px; align-items: baseline; }
.nb-return-dt { margin: 0; color: var(--muted); font-size: 14px; font-weight: 600; }
.nb-return-dd { margin: 0; color: var(--text); font-size: 14px; line-height: 1.45; }
.nb-cover[data-minimized="true"] { margin-bottom: 14px; padding-block: 10px; }
.nb-cover-priority-head { display: flex; align-items: center; justify-content: space-between; gap: 14px; min-height: 32px; }
.nb-cover-priority-copy { display: flex; align-items: baseline; gap: 10px; min-width: 0; }
.nb-cover-priority-title { margin: 0; color: var(--text); font: 650 16px/1.35 Montserrat, Inter, sans-serif; letter-spacing: 0; }
.nb-cover-priority-sub { color: var(--muted); font-size: 14px; line-height: 1.35; }
.nb-cover-minimize { display: inline-grid; place-items: center; width: 30px; height: 30px; flex: none; border: 1px solid var(--hair); border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer; font: 500 18px/1 Inter, sans-serif; }
.nb-cover-minimize:hover { border-color: var(--hair-strong); color: var(--text); }
.nb-cover-minimize:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.nb-cover-priority-body { min-width: 0; }
.nb-cover-empty { margin: 8px 0 0; color: var(--muted); font-size: 14px; line-height: 1.45; }
.nb-cover-lead { margin: 0 0 4px; font-size: 12.5px; line-height: 1.5; color: var(--muted); }
.nb-cover-sec { display: flex; align-items: center; gap: 8px; margin: 14px 0 8px; }
.nb-cover-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; }
.nb-cover-sec-h { font-family: Montserrat, Inter, sans-serif; font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; }
.nb-cover-sec--slipping .nb-cover-sec-h { color: var(--azure); }
.nb-cover-sec--strong .nb-cover-sec-h { color: var(--cyan-glow); }
.nb-cover-meter-fill.is-slipping { background: var(--azure); }
.nb-cover-meter-fill.is-holding { background: var(--cyan-glow); }
.nb-cover-meter-fill.is-strong { background: var(--cyan); }
.nb-cover-rule { flex: 1; height: 1px; background: var(--hair); }
.nb-cover-list { display: flex; flex-direction: column; margin: 8px 0 0; padding: 0; list-style: none; }
.nb-cover-row { display: flex; align-items: center; gap: 14px; padding: 9px 0; border-bottom: 1px solid rgba(255,255,255,.05); }
.nb-cover-row:last-child { border-bottom: 0; }
.nb-cover-rank { display: inline-grid; place-items: center; width: 22px; height: 22px; flex: none; border: 1px solid var(--hair-strong); border-radius: 50%; color: var(--muted); font: 650 10px/1 Montserrat, Inter, sans-serif; }
.nb-cover-row-main { flex: 1; min-width: 0; }
.nb-cover-topic { font-size: 13px; color: var(--text, #e6edf6); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb-cover-when { font-size: 14px; color: var(--muted); opacity: .8; margin-top: 2px; }
.nb-cover-meter-wrap { width: 118px; flex: none; }
.nb-cover-meter { height: 6px; border-radius: 3px; background: rgba(255,255,255,.06); overflow: hidden; }
.nb-cover-meter-fill { height: 100%; border-radius: 3px; transition: width .3s ease; }
.nb-cover-pct { font-size: 12px; text-align: right; margin-top: 3px; color: var(--muted); }
.nb-cover-acts { display: flex; gap: 4px; flex: none; }
.nb-cover-act { font-size: 11px; color: var(--muted); background: transparent; border: 1px solid var(--hair); border-radius: 7px; padding: 4px 8px; cursor: pointer; transition: border-color .15s ease, color .15s ease, background .15s ease; }
.nb-cover-act:hover { border-color: var(--hair-strong); color: var(--text); }
.nb-cover-act:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.nb-cover-act--review { color: var(--cyan); border-color: rgba(0,229,255,.4); padding: 4px 10px; }
.nb-cover-act--review:hover { background: rgba(0,229,255,.08); border-color: var(--cyan); color: var(--cyan); }
.nb-cover-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.nb-cover-chip { font-size: 14px; color: var(--text); border: 1px solid var(--glass-edge); background: transparent; border-radius: 8px; padding: 5px 11px; }
.nb-cover-foot { display: flex; justify-content: space-between; align-items: center; gap: 10px; margin-top: 14px; padding-top: 10px; border-top: 1px solid var(--hair); }
.nb-cover-muted { font-size: 11.5px; color: var(--muted); background: transparent; border: 0; cursor: pointer; padding: 2px 0; text-decoration: underline; text-underline-offset: 2px; }
.nb-cover-muted:hover { color: var(--text); }
.nb-cover-reviewall { margin-left: auto; }

@media (max-width: 480px) {
  .nb-cover { padding-inline: 2px; }
  .nb-cover-priority-copy { align-items: flex-start; flex-direction: column; gap: 2px; }
  .nb-cover-row { flex-wrap: wrap; row-gap: 8px; }
  .nb-cover-row-main { flex-basis: 100%; }
  .nb-cover-acts { margin-left: auto; }
  .nb-cover-foot { flex-wrap: wrap; }
}

/* the re-add surface for slept/dismissed cover alerts (also reachable from ⋯ More) */
.nb2-muted-alerts { width: min(420px, 94vw); }
.nb2-muted-body { display: flex; flex-direction: column; gap: 2px; padding: 10px 14px 14px; }
.nb2-muted-row { display: flex; align-items: center; gap: 10px; padding: 8px 0; border-bottom: 1px solid var(--hair); }
.nb2-muted-row:last-child { border-bottom: 0; }
.nb2-muted-topic-wrap { flex: 1; min-width: 0; display: flex; align-items: center; gap: 8px; }
.nb2-muted-topic { font-size: 13px; color: var(--text); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-muted-tag { font-size: 9.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--muted); border: 1px solid var(--hair); border-radius: 5px; padding: 2px 6px; flex: none; }

/* ROLLING ENGAGEMENT BOARD: learner-controlled scheduling, never a required cadence. */
.nb-plan-toggle { display: inline-flex; align-items: center; gap: 6px; }
.nb-plan-toggle-icon { display: inline-grid; place-items: center; width: 17px; height: 17px; }
.nb-plan-toggle-icon .nb-surface-icon { width: 17px; height: 17px; }
.nb-plan {
  --nb-plan-axis: 56px;
  --nb-plan-day: 148px;
  --nb-plan-slot: 44px;
  --nb-plan-head-h: 48px;
  --nb-plan-board-min: 1092px;
  --nb-plan-surface: rgba(7,15,31,.52);
  --nb-plan-surface-strong: rgba(9,18,36,.96);
  --nb-plan-field-bg: rgba(10,17,40,.62);
  --nb-plan-grid-line: rgba(159,179,200,.12);
  --nb-plan-grid-line-strong: rgba(159,179,200,.2);
  width: min(1180px, calc(100vw - 32px));
  max-width: none;
  max-height: calc(100vh - 32px);
  min-width: 0;
  box-sizing: border-box;
  position: fixed;
  top: 16px;
  left: 50%;
  transform: translateX(-50%);
  margin: 0;
  padding: 18px;
  overflow: auto;
  overscroll-behavior: contain;
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  color: var(--text, #e6edf6);
  background: rgba(8,16,32,.985);
  box-shadow: 0 24px 72px rgba(0,0,0,.62), inset 0 1px 0 rgba(255,255,255,.035);
  text-align: left;
}
.nb-plan:not([open]):not([data-open="true"]) { display: none; }
.nb-plan::backdrop { background: rgba(2,7,18,.72); backdrop-filter: blur(4px); }
.nb-plan-head,
.nb-plan-tabs,
.nb-plan-panel,
.nb-plan-maintenance,
.nb-plan-tray,
.nb-plan-status { width: min(736px, 100%); margin-inline: auto; }
.nb-plan-head { margin-bottom: 12px; }
.nb-plan-title-row { display: flex; align-items: center; gap: 8px; min-width: 0; }
.nb-plan-mark { display: inline-grid; place-items: center; width: 22px; height: 22px; flex: none; color: var(--cyan); }
.nb-plan-icon { display: block; width: 17px; height: 17px; }
.nb-plan-title { margin: 0; color: var(--text); font: 700 14px/1.35 Montserrat, Inter, sans-serif; }
.nb-plan-close { display: inline-grid; place-items: center; width: 40px; height: 40px; min-width: 40px; margin-left: auto; padding: 0; border: 0; border-radius: 5px; color: var(--muted); background: transparent; cursor: pointer; }
.nb-plan-close:hover { color: var(--text); background: rgba(159,179,200,.1); }
.nb-plan-help { max-width: 660px; margin: 5px 0 0 30px; color: var(--muted); font-size: 11.5px; line-height: 1.5; }
.nb-plan-total { display: inline-flex; margin: 8px 0 0 30px; padding: 4px 8px; border: 1px solid var(--hair); border-radius: 6px; color: var(--muted); background: rgba(159,179,200,.05); font-size: 10.5px; }
.nb-plan-tabs { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 4px; margin-bottom: 12px; padding: 4px; border: 1px solid var(--hair-strong); border-radius: 7px; background: rgba(9,18,36,.3); }
.nb-plan-tab { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-width: 0; min-height: 40px; padding: 7px 10px; border: 1px solid transparent; border-radius: 5px; color: var(--muted); background: transparent; font: 600 11.5px/1.2 Montserrat, Inter, sans-serif; cursor: pointer; }
.nb-plan-tab[aria-selected="true"] { color: var(--text); border-color: var(--glass-edge); background: rgba(84,239,255,.08); box-shadow: inset 0 -2px 0 var(--cyan); }
.nb-plan-tab:hover { color: var(--text); background: rgba(159,179,200,.06); }
.nb-plan-panel[hidden] { display: none; }
.nb-plan-panel { margin-bottom: 12px; }
.nb-plan-form { display: grid; gap: 10px; align-items: end; min-width: 0; padding: 11px; border-block: 1px solid var(--hair); background: rgba(9,18,36,.18); }
.nb-plan-create-form { grid-template-columns: minmax(0, 1fr) auto; }
.nb-plan-create-form.is-direct { grid-template-columns: minmax(0, 1fr) minmax(120px, .32fr) auto auto; }
.nb-plan-plant-form { grid-template-columns: minmax(180px, 1.7fr) repeat(3, minmax(100px, 1fr)) auto; }
.nb-plan-direct-context { display: flex; align-items: center; gap: 8px; min-height: 38px; padding: 7px 11px; border-left: 2px solid var(--cyan); color: var(--text); background: rgba(84,239,255,.06); font-size: 11.5px; }
.nb-plan-field { display: flex; flex-direction: column; gap: 5px; min-width: 0; }
.nb-plan-field-label { color: var(--text); font: 650 11px/1.3 Montserrat, Inter, sans-serif; }
.nb-plan-input,
.nb-plan-select { width: 100%; height: 40px; min-width: 0; box-sizing: border-box; padding: 0 10px; border: 1px solid var(--hair); border-radius: 6px; color: var(--text); background: var(--nb-plan-field-bg); font: 500 11.5px/1.2 Montserrat, Inter, sans-serif; }
.nb-plan-input::placeholder { color: var(--muted); opacity: .78; }
.nb-plan-submit { display: inline-flex; align-items: center; justify-content: center; gap: 7px; min-height: 40px; white-space: nowrap; }
.nb-plan-section-head { display: flex; align-items: center; justify-content: space-between; gap: 10px; min-width: 0; margin-bottom: 8px; }
.nb-plan-section-title { margin: 0; color: var(--text); font: 650 11.5px/1.3 Montserrat, Inter, sans-serif; }
.nb-plan-count { color: var(--muted); font-size: 10.5px; }
.nb-plan-maintenance { margin-bottom: 14px; padding: 10px 0 12px; border-block: 1px solid var(--hair); }
.nb-plan-maintenance-help { margin: 0 0 8px; color: var(--muted); font-size: 10.5px; line-height: 1.45; }
.nb-plan-maintenance-list { display: grid; gap: 6px; }
.nb-plan-maintenance-row { display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 10px; align-items: center; min-width: 0; padding: 7px 8px; border: 1px solid var(--hair); border-radius: 6px; background: rgba(159,179,200,.035); }
.nb-plan-maintenance-copy { min-width: 0; }
.nb-plan-maintenance-topic { display: block; color: var(--text); font-size: 11.5px; line-height: 1.35; }
.nb-plan-maintenance-evidence { display: block; margin-top: 3px; color: var(--muted); font-size: 9.5px; line-height: 1.4; }
.nb-plan-maintenance-actions { display: flex; gap: 5px; }
.nb-plan-maintenance-manage { flex: none; }
.nb-plan-tray { margin-bottom: 14px; padding: 10px 0 12px; border-bottom: 1px solid var(--hair); }
.nb-plan-tray-list { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
.nb-plan-tray-item { display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; gap: 8px; align-items: center; min-width: 0; min-height: 52px; padding: 5px 6px; border: 1px solid var(--hair); border-radius: 7px; background: rgba(159,179,200,.035); }
.nb-plan-tray-copy { min-width: 0; }
.nb-plan-tray-title { display: block; overflow: hidden; color: var(--text); font-size: 11.5px; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
.nb-plan-tray-meta { display: block; margin-top: 2px; overflow: hidden; color: var(--muted); font-size: 9.5px; line-height: 1.3; text-overflow: ellipsis; white-space: nowrap; }
.nb-plan-tray-actions { display: flex; gap: 3px; }
.nb-plan-action,
.nb-plan-drag-handle,
.nb-plan-window-menu-trigger { display: inline-grid; place-items: center; width: 40px; height: 40px; min-width: 40px; min-height: 40px; padding: 0; border: 0; border-radius: 5px; color: var(--muted); background: transparent; cursor: pointer; }
.nb-plan-drag-handle { cursor: grab; }
.nb-plan-action:hover,
.nb-plan-drag-handle:hover,
.nb-plan-window-menu-trigger:hover { color: var(--text); background: rgba(159,179,200,.1); }
.nb-plan-empty { margin: 0; padding: 8px 0; color: var(--muted); font-size: 11px; line-height: 1.45; }
.nb-plan-board { width: 100%; min-width: 0; }
.nb-plan-board > .nb-plan-section-head { margin-inline: 2px; }
.nb-plan-board-scroll { width: 100%; height: min(570px, 68vh); min-height: 340px; min-width: 0; overflow: auto; overscroll-behavior-inline: contain; overscroll-behavior-block: auto; touch-action: auto; scrollbar-gutter: stable; border: 1px solid var(--hair-strong); border-radius: 8px; background: var(--nb-plan-surface); box-shadow: 0 12px 30px rgba(2,7,18,.25), inset 0 1px 0 rgba(255,255,255,.025); isolation: isolate; -webkit-overflow-scrolling: touch; }
.nb-plan-board-inner { width: 100%; min-width: var(--nb-plan-board-min); position: relative; }
.nb-plan-board-head,
.nb-plan-board-body { display: grid; grid-template-columns: var(--nb-plan-axis) repeat(7, minmax(var(--nb-plan-day), 1fr)); width: 100%; min-width: var(--nb-plan-board-min); }
.nb-plan-board-head { height: var(--nb-plan-head-h); position: sticky; top: 0; z-index: 12; border-bottom: 1px solid var(--hair-strong); background: var(--nb-plan-surface-strong); box-shadow: 0 5px 12px rgba(2,7,18,.16); }
.nb-plan-time-head,
.nb-plan-day-head { display: flex; align-items: center; justify-content: center; min-width: 0; padding: 5px 6px; overflow: hidden; border-right: 1px solid var(--hair); color: var(--text); background: var(--nb-plan-surface-strong); text-align: center; }
.nb-plan-time-head { position: sticky; left: 0; z-index: 14; color: var(--muted); font: 600 9.5px/1.2 Montserrat, Inter, sans-serif; }
.nb-plan-day-head { flex-direction: column; gap: 1px; font: 600 9.5px/1.2 Montserrat, Inter, sans-serif; }
.nb-plan-day-head strong { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb-plan-day-head > span:not(.nb-plan-today) { max-width: 100%; overflow: hidden; color: var(--muted); font-size: 9px; text-overflow: ellipsis; white-space: nowrap; }
.nb-plan-today { color: var(--cyan); font-size: 8px; line-height: 1; text-transform: uppercase; }
.nb-plan-board-body { position: relative; align-items: start; min-height: calc(33 * var(--nb-plan-slot)); }
.nb-plan-time-axis { display: grid; grid-template-rows: repeat(33, var(--nb-plan-slot)); height: calc(33 * var(--nb-plan-slot)); position: sticky; left: 0; z-index: 8; color: var(--muted); background: var(--nb-plan-surface-strong); box-shadow: 5px 0 12px rgba(2,7,18,.16); }
.nb-plan-time-tick { display: flex; align-items: flex-start; justify-content: flex-end; min-width: 0; padding: 4px 7px 0 2px; overflow: hidden; border-right: 1px solid var(--hair-strong); border-bottom: 1px solid var(--nb-plan-grid-line); font: 550 8.5px/1.1 Montserrat, Inter, sans-serif; white-space: nowrap; }
.nb-plan-time-tick:nth-child(even) { opacity: .58; }
.nb-plan-day-lane { height: calc(33 * var(--nb-plan-slot)); min-width: 0; position: relative; overflow: visible; border-right: 1px solid var(--hair); background-color: rgba(8,16,32,.26); background-image: linear-gradient(to bottom, var(--nb-plan-grid-line-strong) 1px, transparent 1px), linear-gradient(to bottom, var(--nb-plan-grid-line) 1px, transparent 1px); background-size: 100% calc(2 * var(--nb-plan-slot)), 100% var(--nb-plan-slot); }
.nb-plan-day-lane:last-child { border-right: 0; }
.nb-plan-slot-grid { height: 100%; position: absolute; inset: 0; z-index: 1; display: grid; grid-template-rows: repeat(33, var(--nb-plan-slot)); }
.nb-plan-slot { width: 100%; min-width: 0; min-height: var(--nb-plan-slot); position: relative; padding: 0; border: 0; border-bottom: 1px solid transparent; color: transparent; background: transparent; cursor: crosshair; }
.nb-plan-slot:hover { border-bottom-color: rgba(84,239,255,.34); background: rgba(84,239,255,.07); }
.nb-plan-slot:hover::after,
.nb-plan-slot:focus-visible::after { position: absolute; inset: 50% auto auto 50%; transform: translate(-50%, -50%); color: var(--cyan); content: "+"; font: 700 14px/1 Montserrat, Inter, sans-serif; }
.nb-plan-slot:focus-visible { color: var(--cyan); background: rgba(84,239,255,.1); }
.nb-plan-day-lane.is-drop-target::after { height: var(--nb-plan-slot); position: absolute; right: 3px; left: 3px; top: calc(var(--drop-slot, 0) * var(--nb-plan-slot)); z-index: 4; box-sizing: border-box; border: 1px dashed var(--cyan); background: rgba(84,239,255,.08); content: ""; pointer-events: none; }
.nb-plan-window { height: calc(var(--slot-count, 1) * var(--nb-plan-slot)); min-height: 0; box-sizing: border-box; position: absolute; right: 4px; left: 4px; top: calc(var(--start-slot, 0) * var(--nb-plan-slot)); z-index: 2; overflow: visible; border: 1px solid rgba(84,239,255,.46); border-left: 3px solid var(--cyan); border-radius: 6px; color: var(--text); background: rgba(14,43,74,.96); box-shadow: 0 2px 8px rgba(2,7,18,.3); container-type: size; }
.nb-plan-window:focus-within,
.nb-plan-window:has(.nb-plan-window-menu[open]) { z-index: 30; border-color: var(--cyan); box-shadow: 0 0 0 1px var(--cyan), 0 5px 18px rgba(2,7,18,.42); }
.nb-plan-window-top { height: 40px; min-width: 0; display: grid; grid-template-columns: 40px minmax(0, 1fr) 40px; align-items: center; }
.nb-plan-window-title { min-width: 0; overflow: hidden; color: var(--text); font-size: 10.5px; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
.nb-plan-window-meta { display: none; position: absolute; top: 40px; right: 6px; left: 6px; overflow: hidden; color: var(--muted); font-size: 8.5px; line-height: 1.2; text-overflow: ellipsis; white-space: nowrap; }
@container (min-height: 78px) { .nb-plan-window-meta { display: block; } }
.nb-plan-window-menu { width: 40px; height: 40px; position: relative; }
.nb-plan-window-menu-trigger { list-style: none; }
.nb-plan-window-menu-trigger::-webkit-details-marker { display: none; }
.nb-plan-window-menu-commands { width: 202px; position: absolute; top: 41px; right: -2px; z-index: 40; display: grid; gap: 2px; padding: 4px; border: 1px solid var(--hair-strong); border-radius: 7px; background: var(--nb-plan-surface-strong); box-shadow: 0 12px 30px rgba(0,0,0,.52); }
.nb-plan-window-menu-command { width: 100%; min-height: 40px; display: grid; grid-template-columns: 22px minmax(0, 1fr); gap: 7px; align-items: center; padding: 7px 9px; border: 0; border-radius: 5px; color: var(--text); background: transparent; font-size: 10.5px; line-height: 1.25; text-align: left; cursor: pointer; }
.nb-plan-window-menu-command:hover { background: rgba(84,239,255,.1); }
.nb-plan-window-menu-command .nb-plan-icon { width: 15px; height: 15px; color: var(--cyan); }
.nb-plan-window-segments { height: 6px; position: absolute; right: 4px; bottom: 3px; left: 4px; display: flex; gap: 1px; overflow: hidden; border-radius: 2px; pointer-events: none; }
.nb-plan-segment { min-width: 2px; flex: var(--segment-grow, 1) 1 0; overflow: hidden; color: transparent; background: rgba(84,239,255,.78); font-size: 0; }
.nb-plan-segment--break { border-inline: 1px solid rgba(255,255,255,.38); background: repeating-linear-gradient(135deg, rgba(159,179,200,.2) 0 2px, rgba(230,237,246,.82) 2px 4px); }
.nb-plan-status { min-height: 18px; margin-top: 8px; color: var(--muted); font-size: 11px; line-height: 1.45; }
.nb-plan-status[data-tone="conflict"] { color: #ffcf6b; }
.nb-plan-status[data-tone="success"] { color: #9fe0d4; }
.nb-plan :is(button, input, select, summary):focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.nb-plan-window-menu[open] > .nb-plan-window-menu-trigger { color: var(--cyan); background: rgba(84,239,255,.1); }
body.eink .nb-plan { --nb-plan-surface: #fff; --nb-plan-surface-strong: #fff; --nb-plan-field-bg: #fff; --nb-plan-grid-line: #bbb; --nb-plan-grid-line-strong: #777; border-color: #000; color: #000; }
body.eink .nb-plan :is(.nb-plan-form, .nb-plan-tabs, .nb-plan-maintenance-row, .nb-plan-tray-item, .nb-plan-board-scroll, .nb-plan-window, .nb-plan-window-menu-commands, input, select) { border-color: #000; background: #fff; color: #000; box-shadow: none; }
body.eink .nb-plan-segment { background: #000; }
body.eink .nb-plan-segment--break { border-color: #000; background: repeating-linear-gradient(135deg, #fff 0 2px, #000 2px 4px); }
@media (max-width: 980px) {
  .nb-plan-create-form.is-direct,
  .nb-plan-plant-form { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .nb-plan-create-form.is-direct .nb-plan-submit,
  .nb-plan-plant-form .nb-plan-submit { grid-column: 1 / -1; }
}
@media (max-width: 800px) {
  .nb-plan { width: auto; max-height: calc(100vh - 16px); inset: 8px; left: 8px; transform: none; padding: 14px 10px; }
  .nb-plan-board-scroll { height: min(520px, 64vh); min-height: 320px; }
}
@media (max-width: 560px) {
  .nb-plan-create-form,
  .nb-plan-create-form.is-direct,
  .nb-plan-plant-form { grid-template-columns: minmax(0, 1fr); }
  .nb-plan-create-form.is-direct .nb-plan-submit,
  .nb-plan-plant-form .nb-plan-submit { grid-column: auto; }
  .nb-plan-tray-list { grid-template-columns: minmax(0, 1fr); }
  .nb-plan-maintenance-row { grid-template-columns: minmax(0, 1fr); }
  .nb-plan-maintenance-actions { flex-wrap: wrap; }
  .nb-plan-help,
  .nb-plan-total { margin-left: 30px; }
}
@media (pointer: coarse) {
  .nb-plan { --nb-plan-slot: 48px; }
  .nb-plan-tab,
  .nb-plan-input,
  .nb-plan-select,
  .nb-plan-submit,
  .nb-plan-chip,
  .nb-plan-action,
  .nb-plan-drag-handle,
  .nb-plan-window-menu,
  .nb-plan-window-menu-trigger,
  .nb-plan-window-menu-command { min-height: 44px; }
  .nb-plan-action,
  .nb-plan-drag-handle,
  .nb-plan-window-menu,
  .nb-plan-window-menu-trigger { width: 44px; height: 44px; min-width: 44px; }
  .nb-plan-window-top { height: 44px; grid-template-columns: 44px minmax(0, 1fr) 44px; }
  .nb-plan-window-menu-commands { top: 45px; }
}
@media (prefers-contrast: more), (monochrome), (update: slow) {
  body:not(.eink-off) .nb-plan { --nb-plan-surface: #fff; --nb-plan-surface-strong: #fff; --nb-plan-field-bg: #fff; --nb-plan-grid-line: #bbb; --nb-plan-grid-line-strong: #777; }
  body:not(.eink-off) .nb-plan :is(.nb-plan-form, .nb-plan-tabs, .nb-plan-tray-item, .nb-plan-board-scroll, .nb-plan-window, .nb-plan-window-menu-commands, input, select) { border-color: #000; background: #fff; color: #000; box-shadow: none; }
}
@media (forced-colors: active) {
  .nb-plan-window,
  .nb-plan-window-menu-commands,
  .nb-plan-form,
  .nb-plan-input,
  .nb-plan-select { forced-color-adjust: none; border-color: CanvasText; background: Canvas; color: CanvasText; }
  .nb-plan-segment { background: Highlight; }
  .nb-plan-segment--break { background: repeating-linear-gradient(135deg, Canvas 0 2px, CanvasText 2px 4px); }
}
@media (prefers-reduced-motion: reduce) {
  .nb-plan *,
  .nb-plan *::before,
  .nb-plan *::after { scroll-behavior: auto !important; animation: none !important; transition: none !important; }
}

/* ============================================================================
   "YOUR DATA": the R-TRANSPARENT view (Glass Canon Atrium: navy field, --hair
   separators, cyan = the export signal, calm). Reuses .nb-dialog / .nb-export-target
   / .nb-mastery-state from the base sheet; only the panel-specific wrappers below.
   ============================================================================ */
.nb2-data { width: min(560px, 92vw); }
.nb2-data-body { display: flex; flex-direction: column; gap: 8px; max-height: 70vh; overflow: auto; }
.nb2-data-h {
  margin: 12px 0 2px; font-size: 13px; font-weight: 600; letter-spacing: .01em;
  color: var(--ink, #e8eef7);
}
.nb2-data-h:first-of-type { margin-top: 4px; }
.nb2-data-raw {
  margin: 6px 0 0; padding: 10px 12px; max-height: 38vh; overflow: auto;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 8px;
  background: var(--field-2, rgba(12, 22, 38, 0.6)); color: var(--muted, #9aa7bd);
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  font-size: 12px; line-height: 1.5; white-space: pre-wrap; word-break: break-word;
}

/* ============================================================================
   "VISUALIZE MY NOTES": the IRIS LEARNING-MAP (STORI mountain) surface.
   nb_iris_viz paints the SVG with Glass Canon tokens inline (navy depth, cyan
   signal, cyan/amber/grey mastery), so this sheet only frames the dialog + the
   focus panel chrome. Reuses .nb-dialog from the base sheet.
   ============================================================================ */
.nb2-iris { width: min(820px, 94vw); }
.nb2-iris-body { display: flex; flex-direction: column; gap: 10px; max-height: 78vh; overflow: auto; }

.nb2-galaxy-dialog { width: min(960px, 96vw); border: none; border-radius: 12px; padding: 0; background: var(--nb-glass, #0f1d3a); color: var(--nb-ink, #f8fafc); }
.nb2-galaxy-dialog::backdrop { background: rgba(10, 17, 40, 0.55); }
.nb2-galaxy-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.08)); }
.nb2-galaxy-intro { margin: 0; padding: 8px 14px 0; color: var(--nb-muted, #9fb3c8); font-size: 0.92rem; }
.nb2-galaxy-host { min-height: 420px; height: min(68vh, 640px); margin: 10px 14px 14px; border-radius: 10px; overflow: hidden; background: #0a1128; }
.nb2-chan-shout { margin: 0 0 8px; padding: 0 2px; }

/* ── LENSES — the learner-facing "how you look" control on the galaxy ──
   A quiet chip row; the active lens is lit with the cyan instrument-light
   accent (a border/glow, never a fill), so the chosen way-of-looking reads at a
   glance while the stars it surfaces do the talking. */
.nb2-galaxy-lenses { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; padding: 8px 14px 0; }
.nb2-galaxy-lens { border: 1px solid var(--hair, rgba(255,255,255,.14)); background: transparent; color: var(--nb-muted, #9fb3c8); border-radius: 999px; cursor: pointer; }
.nb2-galaxy-lens:hover { color: var(--nb-ink, #f8fafc); border-color: rgba(255,255,255,.28); }
.nb2-galaxy-lens:focus-visible { outline: 2px solid var(--accent, #00e5ff); outline-offset: 2px; }
.nb2-galaxy-lens.is-active { color: var(--nb-ink, #f8fafc); border-color: var(--cyan, #54efff); box-shadow: inset 0 0 0 1px var(--cyan, #54efff), 0 0 8px rgba(84, 239, 255, 0.28); }

/* ── LENS INTAKE vestibule (nb_intake_ui) — same glass frame as the galaxy dialog ── */
.nb2-intake-dialog { width: min(640px, 94vw); border: none; border-radius: 12px; padding: 0; background: var(--nb-glass, #0f1d3a); color: var(--nb-ink, #f8fafc); }
.nb2-intake-dialog::backdrop { background: rgba(10, 17, 40, 0.55); }
.nb2-intake-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 12px 14px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.08)); }
.nb2-intake-body { display: flex; flex-direction: column; gap: 10px; padding: 12px 14px 14px; max-height: 72vh; overflow: auto; }
.nb2-intake-framing { margin: 0; color: var(--nb-muted, #9fb3c8); font-size: 0.95rem; }
.nb2-intake-consent { display: flex; gap: 8px; align-items: flex-start; font-size: 0.9rem; color: var(--nb-muted, #9fb3c8); }
.nb2-intake-worlds { display: flex; flex-direction: column; gap: 6px; font-size: 0.9rem; }
.nb2-intake-q { margin: 0; font-size: 1rem; }
.nb2-intake-choice { text-align: left; white-space: normal; }
.nb2-intake-whywrong { margin: 0; color: var(--nb-muted, #9fb3c8); }
.nb2-intake-summary p { margin: 4px 0; }
.nb2-intake-correct-row { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; font-size: 0.9rem; }
.iris-learning-map { display: flex; flex-direction: column; gap: 10px; }
.iris-map-svg {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 10px;
  background: var(--field-2, rgba(12, 22, 38, 0.6));
}
.iris-node { cursor: pointer; }
.iris-node:focus-visible { outline: 2px solid var(--accent, #00e5ff); outline-offset: 2px; }
.iris-node-label { pointer-events: none; }
.iris-focus {
  padding: 10px 12px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 10px;
  background: var(--field-1, rgba(10, 17, 40, 0.5)); color: var(--ink, #e8eef7);
}
.iris-focus-title { margin: 0 0 4px; font-size: 14px; font-weight: 600; }
.iris-focus-state { margin: 0 0 6px; font-size: 12px; color: var(--muted, #9aa7bd); }
.iris-focus-state.is-mastered { color: var(--ok, #00E5FF); }
.iris-focus-state.is-shaky { color: var(--warn, #F59E0B); }
.iris-focus-gap-head { margin: 6px 0 2px; font-size: 12px; font-weight: 600; color: var(--err, #FF8A8A); }
.iris-focus-gaps { margin: 0; padding-left: 18px; }
.iris-focus-gap { font-size: 12px; line-height: 1.45; }
.iris-focus-cue { margin: 4px 0 0; font-size: 12px; color: var(--muted, #9aa7bd); }

/* ============================================================================
   "IMPORT / EXPORT": THE IO HUB (R-ROSETTA: one screen, both directions visible).
   Glass Canon Atrium: navy field, --hair separators, cyan = the action signal,
   calm. Reuses .nb-dialog / .nb-dialog-head / .nb-export-target / .nb-target-meta /
   .nb-mastery-state / .nb-btn from the base sheet; only the hub-specific wrappers
   below. The two halves sit side-by-side on a wide screen and stack on a narrow one,
   so import (in) and export (out) are evident at a glance.
   ============================================================================ */
.nb2-iohub { width: min(840px, 94vw); }
.nb2-iohub-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  max-height: 76vh;
  overflow: auto;
}
.nb2-iohub-col {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 12px 13px 13px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 12px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
/* the export half reads as the quieter, outbound surface (a hair deeper navy). */
.nb2-iohub-export { background: var(--field-2, rgba(12, 22, 38, 0.6)); }
.nb2-iohub-h {
  margin: 0 0 2px; font-size: 13px; font-weight: 600; letter-spacing: .01em;
  color: var(--ink, #e8eef7);
}

/* ── import: file picker ── */
.nb2-iohub-file {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  margin-top: 2px; cursor: pointer;
}
.nb2-iohub-file-btn { cursor: pointer; }
.nb2-iohub-file-hint {
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  font-size: 11px; color: var(--muted, #9aa7bd); letter-spacing: .01em;
}
/* the real <input type=file> is visually hidden but keyboard-reachable: the label
   (and its styled trigger) carry the affordance; focus-visible rings the trigger. */
.nb2-iohub-file-input {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}
.nb2-iohub-file-input:focus-visible + .nb2-iohub-file-btn,
.nb2-iohub-file:focus-within .nb2-iohub-file-btn {
  outline: 2px solid var(--cyan, var(--accent, #00e5ff)); outline-offset: 2px;
}

.nb2-iohub-or {
  font-size: 11.5px; color: var(--muted, #9aa7bd); text-transform: lowercase;
  letter-spacing: .02em; margin: 2px 0;
}

/* ── import: paste textarea ── */
.nb2-iohub-paste {
  width: 100%; box-sizing: border-box; min-height: 96px; resize: vertical;
  font: inherit; font-size: 12.5px; line-height: 1.5;
  color: var(--ink, #e8eef7);
  background: var(--field-2, rgba(12, 22, 38, 0.6));
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 9px;
  padding: 8px 10px;
}
.nb2-iohub-export .nb2-iohub-paste { background: var(--field-1, rgba(10, 17, 40, 0.5)); }
.nb2-iohub-paste:focus-visible {
  outline: 2px solid var(--cyan, var(--accent, #00e5ff)); outline-offset: 1px;
  border-color: var(--cyan, var(--accent, #00e5ff));
}
.nb2-iohub-paste-acts { display: flex; justify-content: flex-end; }

/* ── import: the HONEST fidelity report ── */
.nb2-iohub-report { display: flex; flex-direction: column; gap: 4px; margin-top: 2px; }
.nb2-iohub-report:empty { display: none; }
.nb2-iohub-report-line { font-size: 12.5px; line-height: 1.45; color: var(--ink, #e8eef7); }
.nb2-iohub-report-line.is-ok { color: var(--ok, #00E5FF); }      /* cyan = success (Glass Canon) */
.nb2-iohub-report-line.is-warn { color: var(--warn, #F59E0B); }    /* amber = couldn't import */
.nb2-iohub-report-fidelity { font-size: 11.5px; line-height: 1.4; color: var(--muted, #9aa7bd); }
.nb2-iohub-report-fidelity.is-lossless { color: var(--ok, #00E5FF); }
.nb2-iohub-report-fidelity.is-lossy { color: var(--warn, #F59E0B); }   /* names what was lost, never silent */

/* ── export: the one-click target list ── */
.nb2-iohub-targets { display: flex; flex-direction: column; gap: 8px; margin-top: 2px; }

/* stack the two halves on a narrow screen so neither direction is squeezed. */
@media (max-width: 720px) {
  .nb2-iohub-cols { grid-template-columns: 1fr; }
}

/* ============================================================================
   "CAMERA EXPORT": the AIR-GAPPED screen→phone surface (§4.2 sovereign).
   nb_camera_export.mountCameraExport builds the `.nb2-camera-export` panel and
   carries its own inline contrast tokens (white QR quiet-zone, large OCR text);
   these rules add the Glass Canon DIALOG chrome + layout/spacing so the QR and
   OCR views sit calm inside the notebook surface. Reuses .nb-dialog /
   .nb-dialog-head / .nb-mastery-state / .nb-btn from the base sheet.
   ============================================================================ */
.nb2-camera { width: min(620px, 94vw); }
.nb2-camera-body {
  display: flex; flex-direction: column; gap: 10px;
  max-height: 78vh; overflow: auto;
}

/* the mounted panel: a navy field with hairline edges, centered content. */
.nb2-camera-export {
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 14px 14px 16px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 12px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-camera-head { display: flex; flex-direction: column; gap: 4px; align-items: center; text-align: center; }
.nb2-camera-title { font-size: 14px; font-weight: 600; letter-spacing: .01em; }
.nb2-camera-label { margin: 0; }

/* ── mode toggle (QR ⇆ OCR): a calm segmented control ── */
.nb2-camera-toggle {
  display: inline-flex; gap: 4px; padding: 3px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 999px;
  background: var(--field-2, rgba(12, 22, 38, 0.6));
}
.nb2-camera-tab {
  font: inherit; font-size: 12.5px; line-height: 1; cursor: pointer;
  padding: 7px 14px; border-radius: 999px; border: 0;
  background: transparent; color: var(--muted, #9aa7bd);
}
.nb2-camera-tab[aria-selected="true"] {
  background: var(--cyan, var(--accent, #00e5ff)); color: var(--on-cyan-ink); font-weight: 600;
}
.nb2-camera-tab:focus-visible {
  outline: 2px solid var(--cyan, var(--accent, #00e5ff)); outline-offset: 2px;
}

/* ── the two mode views ── */
.nb2-camera-view {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  width: 100%;
}
.nb2-camera-view[hidden] { display: none; }

/* QR stage: the active frame is centered; the white quiet zone (set inline by the
   module) reads cleanly against the navy field. */
.nb2-camera-qr-stage {
  display: flex; align-items: center; justify-content: center;
  min-height: 220px; width: 100%;
}
.nb2-camera-qr-frame[hidden] { display: none; }
.nb2-camera-qr-svg { display: inline-flex; }
.nb2-camera-qr-svg svg { display: block; width: clamp(180px, 60vw, 300px); height: auto; }
.nb2-camera-qr-fallback {
  margin: 0; max-width: 320px;
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
}
.nb2-camera-qr-counter {
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  letter-spacing: .03em;
}
.nb2-camera-qr-controls { display: flex; justify-content: center; }
.nb2-camera-qr-play { cursor: pointer; }

/* OCR view: the module sizes the text big + high-contrast inline; we just keep it
   left-read and bounded so it wraps for the camera rather than overflowing. */
.nb2-camera-ocr-hint { margin: 0; max-width: 340px; text-align: center; }
.nb2-camera-ocr-text {
  width: 100%; box-sizing: border-box; max-height: 46vh; overflow: auto;
  white-space: pre-wrap; word-break: break-word;
}

/* ============================================================================
   "STUDY PARTNER (AI)": the CONTROLLABLE-AI surface (§4.9: pluggable /
   disable-able / UDL-honest). Provider radios, BYO endpoint fields, and the
   visible-disabled capability list. Reuses .nb-dialog + .nb-target-meta /
   .nb-mastery-state from the base sheet; only the panel-specific chrome below.
   ============================================================================ */
.nb2-ai { width: min(580px, 92vw); }
.nb2-ai-body { display: flex; flex-direction: column; gap: 10px; max-height: 76vh; overflow: auto; }
.nb2-ai-group { margin: 2px 0 0; padding: 8px 10px 10px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 10px; }
.nb2-ai-legend { padding: 0 6px; font-size: 12px; font-weight: 600; color: var(--ink, #e8eef7); }
.nb2-ai-opt {
  display: flex; gap: 10px; align-items: flex-start;
  padding: 8px 6px; border-radius: 8px; cursor: pointer;
}
.nb2-ai-opt:hover { background: var(--field-1, rgba(10, 17, 40, 0.5)); }
.nb2-ai-opt input { margin-top: 3px; accent-color: var(--accent, #00e5ff); }
.nb2-ai-opt-title { font-size: 13px; font-weight: 600; color: var(--ink, #e8eef7); }
.nb2-ai-custom {
  display: flex; flex-direction: column; gap: 6px;
  padding: 10px 12px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 10px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-ai-flabel { font-size: 12px; font-weight: 600; color: var(--muted, #9aa7bd); }
.nb2-ai-input {
  padding: 7px 10px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 8px;
  background: var(--field-2, rgba(12, 22, 38, 0.6)); color: var(--ink, #e8eef7);
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace); font-size: 12px;
}
.nb2-ai-input:focus-visible { outline: 2px solid var(--accent, #00e5ff); outline-offset: 1px; }
.nb2-ai-h { margin: 10px 0 2px; font-size: 13px; font-weight: 600; color: var(--ink, #e8eef7); }
.nb2-ai-caps { display: flex; flex-direction: column; gap: 6px; }
.nb2-ai-cap {
  display: flex; align-items: center; gap: 10px; justify-content: space-between;
  padding: 8px 10px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 8px;
}
.nb2-ai-cap.is-disabled { opacity: 0.62; }   /* evidently disabled, NEVER hidden (UDL-honest) */
.nb2-ai-badge {
  flex: none; padding: 2px 8px; border-radius: 999px; font-size: 11px; font-weight: 600;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); color: var(--muted, #9aa7bd);
}
/* Glass Canon: cyan = the one signal, no bright greens. The badge TEXT
   (Available/Off/Unreachable) is the non-color carrier, so state never rides color alone. */
.nb2-ai-badge--available { color: var(--cyan, #00E5FF); border-color: rgba(0, 229, 255, 0.5); }
.nb2-ai-badge--off { color: var(--muted, #9FB3C8); }
.nb2-ai-badge--unreachable { color: var(--warn, #F59E0B); border-color: rgba(245, 158, 11, 0.5); }

/* ============================================================================
   FEATURE 1: VERSION HISTORY (nb_history). Reuses .nb-dialog / .nb-dialog-head /
   .nb-mastery-state / .nb-btn from the base sheet; only the timeline list below.
   Glass Canon Atrium: navy field, --hair separators, cyan = the restore signal.
   ============================================================================ */
.nb2-history { width: min(580px, 92vw); }
.nb2-history-body { display: flex; flex-direction: column; gap: 10px; max-height: 74vh; overflow: auto; }
.nb2-history-list { display: flex; flex-direction: column; gap: 6px; }
.nb2-history-row {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 9px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-history-row.is-episode { background: var(--field-2, rgba(12, 22, 38, 0.6)); }
.nb2-history-meta { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.nb2-history-label { font-size: 13px; font-weight: 600; color: var(--ink, #e8eef7); }
.nb2-history-sub { font-size: 11.5px; }
.nb2-history-diff { font-size: 11.5px; color: var(--cyan-glow, #54efff); }
.nb2-history-diff:empty { display: none; }
.nb2-history-acts { flex: none; display: flex; gap: 6px; }
.nb2-history-empty { font-size: 12px; }

/* ============================================================================
   FEATURE 2: QUICK-CAPTURE box (cues column) + INBOX dialog (nb_capture).
   The quick-add box mirrors the .nb2-tag-add form; the Inbox dialog reuses the
   shared .nb-dialog chrome. Navy field, cyan = the capture/promote signal, calm.
   ============================================================================ */
.nb2-quickadd {
  display: flex; align-items: center; gap: 6px; margin-bottom: 8px;
  padding: 4px 4px 4px 8px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 9px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-quickadd:focus-within { border-color: var(--glass-edge, var(--cyan, #00e5ff)); }
.nb2-quickadd-input {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 12.5px;
  color: var(--text, #e8eef7); background: none; border: 0; outline: 0; padding: 4px 2px;
}
.nb2-quickadd-input::placeholder { color: var(--muted, #9aa7bd); }
.nb2-quickadd-btn { flex: none; }

.nb2-inbox { width: min(560px, 92vw); }
.nb2-inbox-body { display: flex; flex-direction: column; gap: 10px; max-height: 74vh; overflow: auto; }
.nb2-inbox-list { display: flex; flex-direction: column; gap: 6px; }
.nb2-inbox-row {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 9px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-inbox-meta { min-width: 0; display: flex; flex-direction: column; gap: 4px; }
.nb2-inbox-text { font-size: 13px; line-height: 1.4; color: var(--ink, #e8eef7); word-break: break-word; }
.nb2-inbox-tags { display: flex; flex-wrap: wrap; gap: 4px; }
.nb2-inbox-tag {
  font-size: 10.5px; color: var(--cyan-glow, #54efff);
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 999px; padding: 1px 7px;
}
.nb2-inbox-acts { flex: none; display: flex; gap: 6px; }
.nb2-inbox-empty { font-size: 12px; }

/* ── GENERATIVE PROMOTION GATE (LS-5.9-03): the retrieve-first dialog. Mirrors
   the inbox dialog chrome; the recall box borrows .nb2-review-recall's calm field. */
.nb2-promote { width: min(560px, 92vw); }
.nb2-promote-body { display: flex; flex-direction: column; gap: 10px; }
.nb2-promote-recall {
  width: 100%; min-height: 96px; resize: vertical;
  padding: 9px 11px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-radius: 8px;
  background: rgba(4,12,22,.55);
  color: var(--text, #F8FAFC); font: inherit; font-size: 13px;
}
.nb2-promote-recall::placeholder { color: var(--muted, #9FB3C8); }
.nb2-promote-recall:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
.nb2-promote-hint { color: var(--warn, #F59E0B); }

/* ============================================================================
   FEATURE 3: NESTED TAGS SIDEBAR + PER-NOTE TAG CHIPS (nb_tags). Sit in the
   library rail (mirroring .nb2-connections chrome): a hairline-topped section,
   navy field, cyan = the active-filter signal. Distinct from the flat
   corpus-wide .nb2-tag-* strip, these are per-note tags.
   ============================================================================ */
.nb2-tagtree {
  display: flex; flex-direction: column; gap: 6px;
  padding-top: 10px; border-top: 1px solid var(--hair);
}
.nb2-tagtree-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.nb2-tagtree-title { font-size: 13px; }
.nb2-tagtree-clear { font-size: 11px; padding: 3px 7px; flex: none; }
.nb2-tagtree-list { display: flex; flex-direction: column; gap: 1px; overflow-y: auto; min-height: 0; max-height: 26vh; padding-right: 2px; }
.nb2-tagtree-empty { font-size: 11.5px; }
.nb2-tagtree-node { display: flex; flex-direction: column; }
.nb2-tagtree-kids { display: flex; flex-direction: column; }
.nb2-tagtree-btn {
  display: flex; align-items: baseline; gap: 6px; width: 100%;
  padding: 3px 6px; border: 1px solid transparent; border-radius: 7px;
  background: none; font: inherit; text-align: left; cursor: pointer; color: var(--text, #e8eef7);
}
.nb2-tagtree-btn:hover { border-color: var(--hair); background: rgba(10,17,40,.45); }
.nb2-tagtree-btn.is-on { border-color: var(--glass-edge, var(--cyan, #00e5ff)); background: rgba(0,229,255,.10); }
.nb2-tagtree-btn.is-on .nb2-tagtree-name { color: var(--cyan-glow, #54efff); }
.nb2-tagtree-btn:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; }
.nb2-tagtree-name { font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-tagtree-count { margin-left: auto; flex: none; font-size: 10.5px; color: var(--muted, #9aa7bd); }

.nb2-notetags {
  display: flex; flex-direction: column; gap: 6px;
  padding-top: 10px; border-top: 1px solid var(--hair);
}
.nb2-notetags-add {
  display: flex; align-items: center; gap: 6px;
  padding: 3px 4px 3px 8px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 8px;
  background: var(--field-1, rgba(10, 17, 40, 0.5));
}
.nb2-notetags-add:focus-within { border-color: var(--glass-edge, var(--cyan, #00e5ff)); }
.nb2-notetags-input {
  flex: 1 1 auto; min-width: 0; font: inherit; font-size: 12px;
  color: var(--text, #e8eef7); background: none; border: 0; outline: 0; padding: 3px 2px;
}
.nb2-notetags-input::placeholder { color: var(--muted, #9aa7bd); }
.nb2-notetags-btn { flex: none; font-size: 11px; padding: 4px 8px; }
.nb2-notetags-chips { display: flex; flex-wrap: wrap; gap: 4px; }
.nb2-notetags-empty { font-size: 11.5px; }
.nb2-notetags-chip {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 2px 4px 2px 8px; border-radius: 999px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); background: rgba(10,17,40,.4);
}
.nb2-notetags-chip.is-on { border-color: var(--glass-edge, var(--cyan, #00e5ff)); }
.nb2-notetags-label { font-size: 11px; color: var(--muted, #9aa7bd); }
.nb2-notetags-chip.is-on .nb2-notetags-label { color: var(--cyan-glow, #54efff); }
.nb2-notetags-x {
  flex: none; color: var(--muted, #9aa7bd); background: none; border: 0; cursor: pointer;
  font-size: 10px; line-height: 1; padding: 2px;
}
.nb2-notetags-x:hover { color: var(--err, #FF8A8A); background: rgba(255, 138, 138, .12); border-radius: 999px; }
.nb2-notetags-x:focus-visible { outline: 2px solid var(--cyan); outline-offset: 1px; border-radius: 999px; }

/* ============================================================================
   COMMAND PALETTE (Ctrl+K): a quiet "do anything" dialog over nb_palette.js.
   Glass Canon Atrium: navy field, --hair separators, cyan = the selected-row +
   focus-ring signal, Montserrat. Reuses .nb-dialog / .nb-dialog-head from the base
   sheet; only the input + results-list wrappers below are new.
   ============================================================================ */
.nb2-palette { width: min(560px, 94vw); }
.nb2-palette-body { display: flex; flex-direction: column; gap: 8px; padding: 10px 12px 12px; }
.nb2-palette-input {
  width: 100%; box-sizing: border-box; font: inherit; font-size: 14px;
  font-family: Montserrat, Inter, ui-sans-serif, system-ui, sans-serif;
  color: var(--text, #e8eef7); background: var(--field-1, rgba(10, 17, 40, 0.5));
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 9px;
  padding: 9px 11px;
}
.nb2-palette-input::placeholder { color: var(--muted, #9aa7bd); }
.nb2-palette-input:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; border-color: var(--cyan, #00E5FF); }
.nb2-palette-list {
  display: flex; flex-direction: column; gap: 2px;
  max-height: 52vh; overflow-y: auto; min-height: 0; padding-right: 2px;
}
.nb2-palette-empty { font-size: 12px; padding: 8px 6px; }
.nb2-palette-row {
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  padding: 8px 10px; border: 1px solid transparent; border-radius: 9px;
  background: none; color: var(--text, #e8eef7); cursor: pointer; font: inherit;
}
.nb2-palette-row:hover { border-color: var(--hair, rgba(159, 179, 200, 0.16)); background: rgba(10,17,40,.45); }
.nb2-palette-row.is-sel { border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.10); }
.nb2-palette-row:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
.nb2-palette-row-main { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1 1 auto; }
.nb2-palette-row-title { font-size: 13.5px; line-height: 1.25; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-palette-row-hint { font-size: 11.5px; color: var(--muted, #9aa7bd); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-palette-kbd {
  flex: none; font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  font-size: 11px; line-height: 1; color: var(--muted, #9aa7bd);
  padding: 3px 6px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 6px;
  background: rgba(10,17,40,.55); white-space: nowrap;
}
.nb2-palette-row.is-sel .nb2-palette-kbd { color: var(--cyan-glow, #54efff); border-color: rgba(0,229,255,.4); }
.nb2-palette-badge {
  flex: none; font-size: 10px; line-height: 1; letter-spacing: .03em; text-transform: uppercase;
  color: var(--cyan-glow, #54efff); padding: 3px 7px; border-radius: 999px;
  border: 1px solid rgba(0,229,255,.3); background: rgba(0,229,255,.08);
}

/* ============================================================================
   KEYBOARD SHORTCUTS cheat-sheet ("?" / "Keyboard shortcuts"): the truthful list
   over nb_palette.groupShortcuts(). Glass Canon Atrium: navy field, --hair rules,
   <kbd> styled as the signal. Reuses .nb-dialog / .nb-dialog-head / .nb-mastery-state.
   ============================================================================ */
.nb2-shortcuts { width: min(520px, 92vw); }
.nb2-shortcuts-body { display: flex; flex-direction: column; gap: 12px; max-height: 70vh; overflow: auto; padding: 4px 2px 2px; }
.nb2-shortcuts-section { display: flex; flex-direction: column; gap: 5px; }
.nb2-shortcuts-h {
  margin: 6px 0 2px; font-size: 12px; font-weight: 600; letter-spacing: .03em; text-transform: uppercase;
  color: var(--cyan-glow, #54efff);
}
.nb2-shortcuts-rows { display: flex; flex-direction: column; gap: 2px; }
.nb2-shortcuts-row {
  display: flex; align-items: baseline; gap: 12px;
  padding: 5px 6px; border-radius: 8px;
}
.nb2-shortcuts-row:hover { background: rgba(10,17,40,.45); }
.nb2-shortcuts-kbd {
  flex: none; min-width: 92px;
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  font-size: 11.5px; line-height: 1.4; color: var(--cyan-glow, #54efff);
  padding: 3px 7px; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16)); border-radius: 6px;
  background: rgba(10,17,40,.55); text-align: center; white-space: nowrap;
}
.nb2-shortcuts-label { font-size: 13px; line-height: 1.4; color: var(--text, #e8eef7); }

/* ============================================================================
   LINKED REFERENCES: wiki-link backlinks panel (nb_backlinks.js). Lives inside
   .nb2-library beneath Connections, so it inherits the rail's sticky column. Glass
   Canon Atrium: navy field, --hair separators, --muted for snippets/missing names,
   --cyan-glow as the single signal on a clickable target. Mirrors the .nb2-conn-*
   idiom so it reads as one rail, not a bolted-on widget.
   ============================================================================ */
.nb2-backlinks {
  display: flex; flex-direction: column; gap: 8px;
  padding-top: 10px; border-top: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
}
.nb2-backlinks-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.nb2-backlinks-title { font-size: 13px; }
.nb2-backlinks-body { display: flex; flex-direction: column; gap: 10px; overflow-y: auto; min-height: 0; max-height: 30vh; padding-right: 2px; }
.nb2-backlinks-empty { font-size: 11.5px; }
.nb2-backlinks-group { display: flex; flex-direction: column; gap: 4px; }
.nb2-backlinks-grouphead { font-size: 10.5px; letter-spacing: .03em; text-transform: uppercase; color: var(--muted, #9aa7bd); }
.nb2-backlinks-list { display: flex; flex-direction: column; gap: 4px; }
.nb2-backlinks-row {
  display: flex; flex-direction: column; gap: 2px;
  padding: 5px 6px; border: 1px solid transparent; border-radius: 8px;
}
.nb2-backlinks-row.nb2-backlinks-out { flex-direction: row; align-items: baseline; gap: 6px; }
.nb2-backlinks-row:hover { border-color: var(--hair, rgba(159, 179, 200, 0.16)); background: rgba(10,17,40,.45); }
.nb2-backlinks-arrow { flex: none; color: var(--muted, #9aa7bd); font-size: 11px; }
.nb2-backlinks-target {
  color: var(--cyan-glow, #54efff); background: none; border: 0; padding: 0; font: inherit;
  text-align: left; cursor: pointer; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.nb2-backlinks-target:hover { text-decoration: underline; }
.nb2-backlinks-target:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; border-radius: 4px; }
.nb2-backlinks-snippet { font-size: 11px; line-height: 1.4; color: var(--muted, #9aa7bd); }
.nb2-backlinks-missing { color: var(--muted, #9aa7bd); font-size: 12px; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-backlinks-create {
  margin-left: auto; flex: none;
  color: var(--cyan-glow, #54efff); background: none; border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 999px; padding: 2px 8px; font: inherit; font-size: 11px; line-height: 1.3; cursor: pointer;
}
.nb2-backlinks-create:hover { border-color: rgba(0,229,255,.4); background: rgba(0,229,255,.08); }
.nb2-backlinks-create:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }

/* Inline [[wiki-link]] in rendered read-only contexts (cue text, summary read,
   backlink snippets). Resolved -> cyan clickable; unresolved -> muted plain text. */
.nb2-wikilink {
  color: var(--cyan-glow, #54efff); background: none; border: 0; padding: 0; font: inherit;
  cursor: pointer; text-decoration: underline; text-underline-offset: 2px;
}
.nb2-wikilink:hover { color: var(--cyan, #00E5FF); }
.nb2-wikilink:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; border-radius: 3px; }
.nb2-wikilink--unresolved { color: var(--muted, #9aa7bd); cursor: default; text-decoration: none; }
.nb2-wikilink--unresolved:hover { color: var(--muted, #9aa7bd); }

/* On the mobile stack the Linked-references list keeps a sane cap inside the rail. */
@media (max-width: 760px) {
  .nb2-backlinks-body { max-height: 32vh; }
}

/* ============================================================================
   THE 7 Cs OF NOTES, APPARENT (WIRE 1)  +  INTERLEAVED SPACED REVIEW (WIRE 2)

   Glass Canon Atrium throughout: navy-dominant field, cyan = the single signal,
   Montserrat (inherited), --hair separators, --muted for secondary copy. Calm and
   encouraging, never a nag, never a points/streak dopamine surface. WCAG AA
   contrast; focus rings #00E5FF. Reuses .nb-dialog / .nb-dialog-head / .nb-btn /
   .nb-mastery-state from the base sheet; only the panel-specific chrome below.
   ============================================================================ */

/* ── WIRE 1a: the C zone sub-labels (Construct / Capture / Consolidate). Reuses
   .nb-zone-sub (muted, calm) from the base sheet; this only marks it for tests +
   a hair of breathing room so the C reads as a quiet badge, not a second title. */
.nb2-c-label { white-space: nowrap; }

/* ── WIRE 1c: the CpC indicator: one calm line under "Cues & recall". A status
   strip, not a button: muted by default, a quiet cyan when the 4-7 band is met,
   a quiet amber nudge when under/over. Cyan stays the dominant zone signal. */
.nb2-cpc {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 4px 8px;
  margin: 6px 0 8px;
  padding: 6px 9px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.55));
  font-size: 11.5px;
  line-height: 1.4;
  color: var(--muted, #9FB3C8);
}
.nb2-cpc[hidden] { display: none; }
.nb2-cpc-dot { font-size: 10px; line-height: 1; flex: none; color: var(--muted, #9FB3C8); }
.nb2-cpc-head { font-weight: 600; color: var(--text, #F8FAFC); }
.nb2-cpc-msg { flex-basis: 100%; color: var(--muted, #9FB3C8); }
/* in-band: a quiet cyan confirmation (not loud). */
.nb2-cpc--ok { border-color: rgba(0,229,255,.45); }
.nb2-cpc--ok .nb2-cpc-dot { color: var(--ok, #00E5FF); }
/* under/over: a quiet amber nudge, names what to do, never alarms. */
.nb2-cpc--warn { border-color: rgba(245,158,11,.40); }
.nb2-cpc--warn .nb2-cpc-dot { color: var(--warn, #F59E0B); }
/* no cues yet: stays neutral/muted, an honest empty-state, not a warning. */
.nb2-cpc--neutral { border-style: dashed; }

/* ── WIRE 2a: the "N due for review" chip. Prominent-but-calm: a cyan-edged button
   that reads as the one actionable signal in the cues column. Hidden at 0 due. */
.nb2-review-chip {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0 0 10px;
  padding: 7px 13px;
  border: 1px solid var(--cyan, #00E5FF);
  border-radius: 999px;
  background: rgba(0,229,255,.10);
  color: var(--text, #F8FAFC);
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  transition: background .12s ease, box-shadow .12s ease;
}
.nb2-review-chip[hidden] { display: none; }
.nb2-review-chip:hover { background: rgba(0,229,255,.18); box-shadow: 0 0 0 3px rgba(0,229,255,.10); }
.nb2-review-chip:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; }
.nb2-review-chip-icon { font-size: 13px; line-height: 1; flex: none; }
.nb2-review-chip-sub { color: var(--muted, #9FB3C8); font-weight: 400; font-size: 11.5px; }

/* ── WIRE 1b: the "7 Cs of Notes" GUIDE dialog. Reuses .nb-dialog / .nb-dialog-head
   chrome; the body is a numbered 7-step flow with the learner's progress. ── */
.nb2-sevencs { width: min(640px, 94vw); }
.nb2-sevencs-body {
  display: flex; flex-direction: column; gap: 12px;
  max-height: 78vh; overflow: auto;
}
.nb2-sevencs-list {
  list-style: none; margin: 0; padding: 0;
  display: flex; flex-direction: column; gap: 8px;
}
.nb2-sevencs-step {
  padding: 10px 12px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-left: 3px solid var(--hair-strong, rgba(255,255,255,.18));
  border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.45));
}
/* a done C gets the cyan signal on its left edge: calm progress, not a trophy. */
.nb2-sevencs-step.is-done {
  border-left-color: var(--cyan, #00E5FF);
  background: rgba(0,229,255,.05);
}
.nb2-sevencs-steptop { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.nb2-sevencs-mark {
  flex: none; width: 16px; text-align: center; font-size: 12px;
  color: var(--muted, #9FB3C8);
}
.nb2-sevencs-step.is-done .nb2-sevencs-mark { color: var(--cyan, #00E5FF); }
.nb2-sevencs-c { font-weight: 700; color: var(--text, #F8FAFC); font-size: 14px; }
.nb2-sevencs-zone {
  font-size: 11px; color: var(--cyan-glow, #54EFFF);
  text-transform: lowercase; letter-spacing: .02em;
}
.nb2-sevencs-status {
  margin-left: auto; font-size: 11px; color: var(--muted, #9FB3C8);
}
.nb2-sevencs-step.is-done .nb2-sevencs-status { color: var(--ok, #00E5FF); }
.nb2-sevencs-what { margin-top: 5px; font-size: 12.5px; color: var(--text, #F8FAFC); }
.nb2-sevencs-detail {
  margin-top: 3px; font-size: 11.5px; color: var(--muted, #9FB3C8); font-style: italic;
}
.nb2-sevencs-hint { margin-top: 4px; font-size: 11.5px; color: var(--muted, #9FB3C8); }
.nb2-sevencs-tally {
  margin: 0; padding-top: 4px; font-size: 12px; color: var(--muted, #9FB3C8);
  border-top: 1px solid var(--hair, rgba(255,255,255,.10));
}

/* ── WIRE 2b: the INTERLEAVED REVIEW SESSION dialog. One item at a time, mixed
   topics, the progress + topic visible so the interleaving is evident. ── */
.nb2-review { width: min(560px, 94vw); }
.nb2-review-body {
  display: flex; flex-direction: column; gap: 12px;
  max-height: 80vh; overflow: auto;
}
/* INTERLEAVE_RATIONALE: the calm "why", shown once. The ✦ mirrors the coach mark. */
.nb2-review-why {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 9px 11px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.45));
  font-size: 11.5px; line-height: 1.5; color: var(--muted, #9FB3C8);
}
.nb2-review-why-mark { color: var(--cyan, #00E5FF); flex: none; line-height: 1.3; }
/* DISCRIMINATION NUDGE: the contrast cue when this item is confusable with the prior
   one. Calm, hairline, cyan glyph (the ONE signal); never a loud alert. */
.nb2-review-contrast {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 11px; margin-top: 2px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-left: 2px solid var(--cyan, #00E5FF);
  border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.45));
  font-size: 11.5px; line-height: 1.5; color: var(--text, #F8FAFC);
}
.nb2-review-contrast-mark { color: var(--cyan, #00E5FF); flex: none; line-height: 1.3; font-weight: 700; }
/* MISCONCEPTION REPAIR BANNER: the hypercorrection contrast: the learner's prior
   wrong belief named beside the upcoming correction. Amber (the warn register), NOT
   cyan, this is a correction context, not the primary signal. */
.nb2-review-repair {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 8px 11px; margin-top: 2px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-left: 2px solid var(--warn, #F59E0B);
  border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.45));
  font-size: 11.5px; line-height: 1.5; color: var(--text, #F8FAFC);
}
.nb2-review-repair-mark { color: var(--warn, #F59E0B); flex: none; line-height: 1.3; font-weight: 700; }
/* progress (i/N) + the current topic: the interleaving made VISIBLE. */
.nb2-review-meta { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.nb2-review-progress {
  font-size: 12px; font-weight: 600; color: var(--muted, #9FB3C8);
  letter-spacing: .03em;
}
.nb2-review-topic {
  padding: 2px 10px; border-radius: 999px;
  border: 1px solid var(--cyan, #00E5FF);
  background: rgba(0,229,255,.10);
  font-size: 11.5px; font-weight: 600; color: var(--text, #F8FAFC);
}
/* ORIGIN chip: where the card came from (grounded vs standalone), made visible.
   Calm/muted (not the cyan signal) so it informs without competing. */
.nb2-review-origin {
  padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--hair, rgba(255,255,255,.14));
  background: var(--navy-panel, rgba(8,18,32,.4));
  font-size: 11px; color: var(--muted, #9FB3C8); cursor: help;
}
.nb2-review-prompt {
  padding: 12px 13px;
  border: 1px solid var(--hair-strong, rgba(255,255,255,.18));
  border-radius: 9px;
  background: var(--navy-panel, rgba(8,18,32,.55));
}
.nb2-review-prompt-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--cyan-glow, #54EFFF); margin-bottom: 5px;
}
.nb2-review-prompt-text { font-size: 15px; line-height: 1.45; color: var(--text, #F8FAFC); }
.nb2-review-recall {
  width: 100%; min-height: 72px; resize: vertical;
  padding: 9px 11px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-radius: 8px;
  background: rgba(4,12,22,.55);
  color: var(--text, #F8FAFC); font: inherit; font-size: 13px;
}
.nb2-review-recall::placeholder { color: var(--muted, #9FB3C8); }
.nb2-review-recall:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
.nb2-review-grades { display: flex; gap: 8px; flex-wrap: wrap; }
.nb2-review-grade { font-size: 12.5px; }
/* the three honest grades carry a quiet edge tint: calm, mastery-not-dopamine. */
.nb2-review-grade--good { border-color: rgba(0,229,255,.5); }
.nb2-review-grade--shaky { border-color: rgba(245,158,11,.5); }
.nb2-review-grade--missed { border-color: var(--hair-strong, rgba(255,255,255,.18)); }
/* WP-R3 generation gate: the grades stay LOCKED (calm, never scolding) until the
   learner recalls, reveals, or says it aloud. Dimmed + not-allowed, no red alarm. */
.nb2-review-grade:disabled { opacity: .42; cursor: not-allowed; }
.nb2-review-grade:disabled:hover { border-color: inherit; }
/* the opt-in aria-live hint under the grades — a quiet invitation, not a warning. */
.nb2-review-gate-hint { margin-top: 2px; font-size: 11.5px; line-height: 1.4; color: var(--muted, #9FB3C8); }
/* WP-R3 answerless-cue "I said it aloud" (UDL): a calm cyan-accented opt-in that
   unlocks grading for a verbal recall. On -> the instrument light confirms it. */
.nb2-review-saidaloud { align-self: flex-start; }
.nb2-review-said { font-size: 12px; }
.nb2-review-said--on { border-color: var(--cyan, #00E5FF); color: var(--cyan-glow, #54EFFF); }
.nb2-review-skip {
  align-self: flex-start;
  background: none; border: 0; padding: 2px 0;
  color: var(--muted, #9FB3C8); font: inherit; font-size: 11.5px;
  text-decoration: underline; text-underline-offset: 2px; cursor: pointer;
}
.nb2-review-skip:hover { color: var(--cyan-glow, #54EFFF); }
.nb2-review-skip:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; border-radius: 3px; }
/* the calm finish summary: "reviewed N across M topics". */
.nb2-review-done {
  display: flex; flex-direction: column; align-items: center; gap: 10px;
  padding: 18px 14px; text-align: center;
}
.nb2-review-done-mark {
  width: 40px; height: 40px; border-radius: 50%;
  display: grid; place-items: center;
  border: 2px solid var(--cyan, #00E5FF);
  color: var(--cyan, #00E5FF); font-size: 20px;
}
.nb2-review-done-text { font-size: 13px; line-height: 1.5; color: var(--text, #F8FAFC); max-width: 42ch; }
/* CALIBRATION REPORT: the illusion-of-knowledge payoff line in the finish summary. */
.nb2-review-done-calib {
  font-size: 12px; line-height: 1.5; color: var(--muted, #9FB3C8);
  max-width: 44ch; padding: 9px 11px; margin-top: 2px;
  border: 1px solid var(--glass-edge, rgba(84,239,255,.22)); border-radius: 8px;
  background: rgba(0,229,255,.06);
}

/* ── ILLUSION-OF-KNOWLEDGE: the PREDICT (judgment-of-learning) gate ──────────────
   Shown before the recall attempt. Calm, not a quiz: three plain confidence
   choices. Cyan is the one signal; the level tints stay quiet (mastery, not
   dopamine), mirroring the three honest grades. */
.nb2-review-predict {
  display: flex; flex-direction: column; gap: 9px;
  padding: 12px 13px;
  border: 1px solid var(--glass-edge, rgba(84,239,255,.22)); border-radius: 9px;
  background: var(--navy-panel, rgba(8,18,32,.45));
}
.nb2-review-predict-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--cyan-glow, #54EFFF);
}
.nb2-review-predict-row { display: flex; gap: 8px; flex-wrap: wrap; }
.nb2-predict-btn { font-size: 12.5px; }
.nb2-predict-btn--high { border-color: rgba(0,229,255,.5); }
.nb2-predict-btn--mid { border-color: rgba(245,158,11,.5); }
.nb2-predict-btn--low { border-color: var(--hair-strong, rgba(255,255,255,.18)); }
.nb2-review-predict-hint { font-size: 11px; line-height: 1.5; color: var(--muted, #9FB3C8); }
/* the learner's prediction echoed during the recall phase, so the comparison is evident. */
.nb2-review-pred-echo { display: flex; align-items: center; gap: 7px; font-size: 11.5px; }
.nb2-review-pred-echo-label { color: var(--muted, #9FB3C8); }
.nb2-review-pred-echo-val {
  padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--hair-strong, rgba(255,255,255,.18));
  color: var(--text, #F8FAFC); font-weight: 600;
}

/* ── ILLUSION-OF-KNOWLEDGE: the calibration FEEDBACK reveal ──────────────────────
   After a mismatched grade, name the gap (the illusion of knowing, or honest under-
   confidence). Mechanism, not judgment. The illusion reveal carries a quiet amber
   edge (a noticing, not an alarm); under-confidence carries the cyan ✦. */
.nb2-review-feedback {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 11px 13px; border-radius: 9px;
  font-size: 12.5px; line-height: 1.55; color: var(--text, #F8FAFC);
  border: 1px solid var(--hair-strong, rgba(255,255,255,.18));
  background: var(--navy-panel, rgba(8,18,32,.55));
}
.nb2-review-feedback-mark { flex: none; font-size: 15px; line-height: 1.3; }
.nb2-review-feedback--illusion { border-color: rgba(245,158,11,.45); background: rgba(245,158,11,.07); }
.nb2-review-feedback--illusion .nb2-review-feedback-mark { color: #F59E0B; }
.nb2-review-feedback--under { border-color: var(--glass-edge, rgba(84,239,255,.22)); background: rgba(0,229,255,.06); }
.nb2-review-feedback--under .nb2-review-feedback-mark { color: var(--cyan, #00E5FF); }
.nb2-review-next { align-self: flex-start; }

/* FLASHCARD ANSWER REVEAL: check recall against the stored answer (flashcards only). */
.nb2-review-reveal { display: flex; flex-direction: column; gap: 8px; }
.nb2-review-show { align-self: flex-start; font-size: 12px; }
.nb2-review-answer {
  padding: 10px 12px; border-radius: 9px;
  border: 1px solid var(--glass-edge, rgba(84,239,255,.22));
  background: rgba(0,229,255,.05);
}
.nb2-review-answer-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--cyan-glow, #54EFFF); margin-bottom: 4px;
}
.nb2-review-answer-text { font-size: 14px; line-height: 1.45; color: var(--text, #F8FAFC); }
/* §7 worked-example fading: the 'completion' rung blanks the last steps as a
   numbered list, so preserve the line breaks. */
.nb2-review-answer--completion { white-space: pre-line; }
/* the 🃏 deck chip pairs with the review chip; a touch of left margin separates them. */
.nb2-flashcard-chip { margin-top: 6px; }

/* ── TEST-VOWELS (AEIOUY): Approach toggle + the lens row ───────────────────────
   The Approach segmented control lives in the review dialog head (set once, shared
   by cue + flashcard sessions); the head wraps so it never crowds the title/Close. */
.nb2-review .nb-dialog-head { flex-wrap: wrap; }
.nb2-review-strategy { display: inline-flex; align-items: center; gap: 7px; }
.nb2-review-strategy-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted, #9FB3C8);
}
.nb2-strat-seg {
  font-size: 11.5px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--hair, rgba(255,255,255,.12));
  background: transparent; color: var(--muted, #9FB3C8); cursor: pointer; font: inherit;
}
.nb2-strat-seg.nb-seg--on {
  color: var(--text, #F8FAFC); border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.08);
}
.nb2-strat-seg:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
/* RETENTION DIAL (§8): four pills; same calm pill language as the Approach toggle,
   selected pill on the ONE cyan signal. */
.nb2-retention { display: inline-flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.nb2-retention-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--muted, #9FB3C8);
}
.nb2-retention-seg {
  font-size: 11.5px; padding: 3px 10px; border-radius: 999px;
  border: 1px solid var(--hair, rgba(255,255,255,.12));
  background: transparent; color: var(--muted, #9FB3C8); cursor: pointer; font: inherit;
}
.nb2-retention-seg.nb-seg--on {
  color: var(--text, #F8FAFC); border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.08);
}
.nb2-retention-seg:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
/* SETTINGS — a spacious, editorial "studio" cockpit. Cyan is an instrument light on the ACTIVE choice
   ONLY; everything else is calm navy glass with a clear type hierarchy and real breathing room. */
.nb2-settings {
  width: min(544px, 94vw);
  border-radius: 18px;
  border: 1px solid rgba(255, 255, 255, .11);
  box-shadow: 0 26px 64px -16px rgba(0, 0, 0, .62), inset 0 1px 0 rgba(255, 255, 255, .07);
}
/* Cycle 5: Settings / Export / Your data dismiss targets stay 44px; dialogs stay in viewport. */
.nb-dialog-head > .nb-btn,
.nb-dialog-close {
  min-height: 44px;
  min-width: 44px;
  padding: 8px 14px;
  box-sizing: border-box;
}
.nb2-settings,
.nb-export-menu,
.nb2-data {
  max-width: min(560px, 94vw);
}

.nb2-settings .nb-dialog-head {
  padding-bottom: 14px; margin-bottom: 2px;
  border-bottom: 1px solid var(--hair, rgba(255,255,255,.10));
}
.nb2-settings .nb-dialog-head strong {
  font-family: Montserrat, system-ui, sans-serif;
  font-size: 16px; font-weight: 700; letter-spacing: .01em; color: var(--text, #F8FAFC);
}
.nb2-settings-body { display: flex; flex-direction: column; gap: 22px; min-width: 0; max-width: none; padding-top: 8px; }
.nb2-settings-body > .nb-mastery-state:first-child {
  font-size: 13px; line-height: 1.55; color: var(--muted, #9FB3C8); margin: 0 0 2px; font-style: normal;
}
.nb2-setting { display: flex; flex-direction: column; gap: 10px; }
.nb2-setting-head { display: flex; flex-direction: column; gap: 3px; }
.nb2-setting-title {
  font-family: Montserrat, system-ui, sans-serif;
  font-size: 13.5px; font-weight: 600; letter-spacing: .01em; color: var(--text, #F8FAFC);
}
.nb2-setting-hint { font-size: 11.5px; line-height: 1.5; color: var(--muted, #9FB3C8); }

/* editorial section divider: a small-caps cyan label + a hairline running to the edge */
.nb2-setting-section { display: flex; align-items: center; gap: 12px; margin: 6px 0 -6px; }
.nb2-setting-section-h {
  font-family: Montserrat, system-ui, sans-serif;
  font-size: 10px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--cyan, #54EFFF); opacity: .82; flex: none;
}
.nb2-setting-section::after { content: ""; flex: 1; height: 1px; background: var(--hair, rgba(255,255,255,.10)); }

/* SINGLE-SELECT: a full-width segmented track with a SLIDING cyan thumb (the highlight glides between
   choices). The thumb is the accent; the active label goes cyan. Restraint over noise. */
.nb2-setting-seg:not(.nb2-setting-chips) {
  position: relative; display: flex; width: 100%;
  border-radius: 12px;
  background: var(--navy-panel, rgba(8,18,32,.55));
  border: 1px solid var(--hair, rgba(255,255,255,.09));
}
.nb2-seg-thumb {
  position: absolute; top: 3px; bottom: 3px; z-index: 0; pointer-events: none;
  left: calc(var(--seg-i, 0) * 100% / var(--seg-count, 1) + 3px);
  width: calc(100% / var(--seg-count, 1) - 6px);
  border-radius: 9px;
  background: rgba(84,239,255,.12);
  box-shadow: inset 0 0 0 1px rgba(84,239,255,.32), 0 1px 4px rgba(0,0,0,.28);
  transition: left .24s cubic-bezier(.4,0,.2,1);
}
.nb2-setting-seg:not(.nb2-setting-chips) .nb2-set-seg {
  position: relative; z-index: 1; flex: 1 1 0; min-width: 0;
  border: none; background: transparent; border-radius: 9px;
  padding: 9px 10px; color: var(--muted, #9FB3C8);
  font-size: 12px; font-weight: 500; text-align: center; cursor: pointer; font: inherit;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  transition: color .16s ease;
}
.nb2-setting-seg:not(.nb2-setting-chips) .nb2-set-seg:hover { color: var(--text, #F8FAFC); }
.nb2-setting-seg:not(.nb2-setting-chips) .nb2-set-seg.nb-seg--on { color: var(--cyan, #54EFFF); font-weight: 600; }

/* MULTI-SELECT (capture surfaces): a calm chip grid. Off = quiet outline; On = a soft cyan wash. */
.nb2-setting-chips { display: flex; flex-wrap: wrap; gap: 7px; }
.nb2-setting-chips .nb2-set-seg {
  border: 1px solid var(--hair, rgba(255,255,255,.14)); border-radius: 9px; padding: 6px 12px;
  background: transparent; color: var(--muted, #9FB3C8); font-size: 12px; cursor: pointer; font: inherit;
  transition: background .14s ease, border-color .14s ease, color .14s ease;
}
.nb2-setting-chips .nb2-set-seg:hover { color: var(--text, #F8FAFC); border-color: rgba(255,255,255,.24); }
.nb2-setting-chips .nb2-set-seg.nb-seg--on {
  color: var(--text, #F8FAFC); border-color: rgba(84,239,255,.42); background: rgba(84,239,255,.08);
}
.nb2-set-seg:focus-visible { outline: 2px solid var(--cyan, #54EFFF); outline-offset: 2px; }
.nb2-setting-rule { border: none; border-top: 1px solid var(--hair, rgba(255,255,255,.09)); margin: 4px 0; }
/* SUMMARY RECAP: review your cues + notes before you synthesize (Cornell). Calm,
   collapsible, sits above the write box. */
.nb2-summary-recap {
  margin: 0 0 10px;
  border: 1px solid var(--hair, rgba(255,255,255,.10));
  border-radius: 9px;
  background: var(--navy-panel, rgba(8,18,32,.4));
}
.nb2-recap-toggle {
  cursor: pointer; padding: 8px 11px; list-style: none;
  font-size: 11.5px; font-weight: 600; color: var(--muted, #9FB3C8);
  letter-spacing: .02em;
}
.nb2-recap-toggle::-webkit-details-marker { display: none; }
.nb2-recap-toggle::before { content: "▸ "; color: var(--cyan, #00E5FF); }
.nb2-summary-recap[open] .nb2-recap-toggle::before { content: "▾ "; }
.nb2-recap-body { padding: 0 11px 11px; }
.nb2-recap-cols { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 620px) { .nb2-recap-cols { grid-template-columns: 1fr; } }
.nb2-recap-col { min-width: 0; }
.nb2-recap-label {
  font-size: 10.5px; text-transform: uppercase; letter-spacing: .06em;
  color: var(--cyan, #54EFFF); margin-bottom: 5px;
}
.nb2-recap-list {
  list-style: none; margin: 0; padding: 0; max-height: 140px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 4px;
}
.nb2-recap-list li {
  font-size: 12px; line-height: 1.4; color: var(--text, #F8FAFC);
  padding-left: 11px; position: relative;
  overflow: hidden; text-overflow: ellipsis;
}
.nb2-recap-list li::before { content: "·"; position: absolute; left: 2px; color: var(--muted, #9FB3C8); }
.nb2-recap-more { color: var(--muted, #9FB3C8) !important; font-size: 11px !important; }
.nb2-recap-more::before { content: "" !important; }
.nb2-recap-empty { font-size: 11.5px; color: var(--muted, #9FB3C8); font-style: italic; }
/* TEACH YOUR DOG: the closed-book teach-back verdict + rubric. Cyan=strong, amber=thin
   (Glass Canon: no greens). */
.nb2-teach-btn { margin-left: 8px; }
.nb2-teach-verdict {
  display: flex; align-items: flex-start; gap: 8px; padding: 9px 11px; margin-bottom: 8px;
  border: 1px solid var(--hair, rgba(255,255,255,.10)); border-radius: 8px;
  background: var(--navy-panel, rgba(8,18,32,.45)); font-size: 12px; line-height: 1.5; color: var(--text, #F8FAFC);
}
.nb2-teach-mark { flex: none; font-weight: 800; line-height: 1.3; }
.nb2-teach-strong { border-left: 2px solid var(--cyan, #00E5FF); }
.nb2-teach-strong .nb2-teach-mark { color: var(--cyan, #00E5FF); }
.nb2-teach-partial { border-left: 2px solid var(--cyan-glow, #54EFFF); }
.nb2-teach-partial .nb2-teach-mark { color: var(--cyan-glow, #54EFFF); }
.nb2-teach-thin { border-left: 2px solid var(--warn, #F59E0B); }
.nb2-teach-thin .nb2-teach-mark { color: var(--warn, #F59E0B); }
.nb2-teach-dims { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 7px; }
.nb2-teach-dim {
  font-size: 11px; padding: 2px 9px; border-radius: 999px;
  border: 1px solid var(--hair, rgba(255,255,255,.12)); color: var(--muted, #9FB3C8);
}
.nb2-teach-dim.is-on { color: var(--text, #F8FAFC); border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.08); }
.nb2-teach-dim.is-mid { color: var(--text, #F8FAFC); border-color: var(--cyan-glow, #54EFFF); }
.nb2-teach-gaps { margin: 0 0 7px; padding-left: 18px; font-size: 11.5px; line-height: 1.5; color: var(--text, #F8FAFC); }
.nb2-teach-gaps li { margin: 2px 0; }
.nb2-teach-unscored { font-size: 11px; color: var(--muted, #9FB3C8); font-style: italic; }
/* spaced re-teaching (review loop) + AI naive-listener + expectancy + speak-it. */
.nb2-teach-speak { margin-left: 8px; }
.nb2-teach-due {
  margin: 0 0 8px; padding: 7px 11px; border-radius: 8px; font-size: 12px; font-weight: 600;
  color: var(--cyan, #00E5FF); border: 1px solid var(--cyan, #00E5FF); background: rgba(0,229,255,.07);
}
.nb2-teach-sched { margin-top: 8px; font-size: 11.5px; color: var(--cyan, #00E5FF); }
.nb2-teach-ask { margin-top: 9px; }
.nb2-teach-ask-out { margin-top: 6px; font-size: 12px; line-height: 1.5; color: var(--text, #F8FAFC); }
.nb2-teach-expectancy {
  margin: 0 0 8px; padding: 6px 10px; border-left: 2px solid var(--cyan, #00E5FF); border-radius: 4px;
  font-size: 11.5px; color: var(--muted, #9FB3C8); background: rgba(0,229,255,.04);
}
/* save-FAILURE chip: a rejected persist must look alarming, not calm — and legible:
   the AA-lifted --err (see :root) keeps the 12px chip text >= 4.5:1 over this wash. */
.nb-local[data-save-error="true"], #nb-local[data-save-error="true"] {
  color: var(--err, #FF8A8A) !important; border-color: var(--err, #FF8A8A) !important;
  background: rgba(255,138,138,.10) !important;
}

/* CONSTRUCT panel: "what you now know" (Glass Canon: cyan signal, confirmed=cyan, no greens). */
.nb2-construct { max-width: 640px; width: min(640px, 92vw); }
.nb2-construct-lede { color: var(--muted, #9FB3C8); font-size: 12.5px; line-height: 1.55; margin: 4px 0 14px; }
.nb2-construct-sec { margin-bottom: 18px; padding-bottom: 14px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.08)); }
.nb2-construct-sec:last-child { border-bottom: none; }
.nb2-construct-h { font-size: 13px; color: var(--cyan, #00E5FF); margin: 0 0 9px; letter-spacing: .02em; }
.nb2-construct-sub, .nb2-construct-tally { font-size: 11.5px; color: var(--muted, #9FB3C8); margin-bottom: 9px; }
.nb2-construct-knows { display: flex; flex-direction: column; gap: 5px; }
.nb2-construct-know {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  padding: 7px 11px; border-radius: 7px; background: var(--navy-panel, rgba(8,18,32,.45));
  border-left: 2px solid var(--hair, rgba(255,255,255,.12)); font-size: 12.5px; color: var(--text, #F8FAFC);
}
.nb2-construct-know.is-confirmed { border-left-color: var(--cyan, #00E5FF); }
.nb2-construct-know.is-addressed { border-left-color: var(--cyan-glow, #54EFFF); }
.nb2-construct-know.is-building  { border-left-color: var(--muted, #9FB3C8); }
.nb2-construct-stamp { flex: none; font-size: 11px; font-weight: 600; }
.nb2-construct-stamp.is-confirmed { color: var(--cyan, #00E5FF); }
.nb2-construct-stamp.is-addressed { color: var(--cyan-glow, #54EFFF); }
.nb2-construct-stamp.is-building  { color: var(--muted, #9FB3C8); }
.nb2-construct-draft { margin-top: 11px; padding: 10px 12px; border-radius: 8px; background: rgba(0,229,255,.04); border: 1px solid var(--hair, rgba(255,255,255,.1)); }
.nb2-construct-draft-label { font-size: 11px; color: var(--cyan, #00E5FF); margin-bottom: 4px; }
.nb2-construct-draft-body { font-size: 12.5px; color: var(--text, #F8FAFC); line-height: 1.55; }
.nb2-construct-empty { font-size: 12px; color: var(--muted, #9FB3C8); font-style: italic; line-height: 1.5; }
/* PHASE-1: the cold Calibrate baseline surfaced at review (anti-hindsight / anti-DK / anti-sunk-cost). */
.nb2-construct-baseline { margin: 0 0 10px; padding: 8px 11px; border-radius: 8px; border-left: 2px solid var(--cyan, #00E5FF); background: rgba(0,229,255,.05); }
.nb2-construct-baseline-row { font-size: 11.5px; color: var(--text, #F8FAFC); line-height: 1.5; }
.nb2-construct-baseline-row + .nb2-construct-baseline-row { margin-top: 5px; }
.nb2-construct-exit { margin-top: 10px; padding: 8px 11px; border-radius: 8px; border-left: 2px solid var(--warn, #F59E0B); background: rgba(245,158,11,.06); font-size: 11.5px; color: var(--text, #F8FAFC); line-height: 1.5; }
.nb2-construct-recall-stat { font-size: 12.5px; color: var(--text, #F8FAFC); margin-bottom: 9px; }
.nb2-construct-acts { display: flex; gap: 8px; flex-wrap: wrap; }
.nb2-construct-existing { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin-bottom: 10px; }
.nb2-construct-existing-label { font-size: 11px; color: var(--muted, #9FB3C8); }
.nb2-construct-chip { font-size: 11px; padding: 2px 9px; border-radius: 999px; border: 1px solid var(--cyan, #00E5FF); color: var(--cyan, #00E5FF); background: rgba(0,229,255,.06); }
.nb2-construct-suggests { display: flex; flex-direction: column; gap: 9px; }
.nb2-construct-suggest { padding: 10px 12px; border-radius: 8px; border: 1px solid var(--hair, rgba(255,255,255,.12)); background: var(--navy-panel, rgba(8,18,32,.45)); }
.nb2-construct-suggest.is-connected { border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.06); }
.nb2-construct-suggest-title { font-size: 12.5px; color: var(--text, #F8FAFC); }
.nb2-construct-suggest-shared { font-size: 11px; color: var(--muted, #9FB3C8); margin: 3px 0 8px; }
.nb2-construct-suggest-acts { display: flex; align-items: center; gap: 8px; }
.nb2-construct-rel {
  background: var(--navy-deep, #0A1128); color: var(--text, #F8FAFC); border: 1px solid var(--hair, rgba(255,255,255,.18));
  border-radius: 6px; padding: 4px 8px; font-size: 11.5px;
}
.nb2-construct-rel:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; border-color: var(--cyan, #00E5FF); }

/* CALIBRATE panel: the cold-state pre-commitment ledger (Phase 0). Glass Canon. */
.nb2-calibrate { max-width: 600px; width: min(600px, 92vw); }
.nb2-cal-lede { color: var(--muted, #9FB3C8); font-size: 12.5px; line-height: 1.55; margin: 4px 0 14px; }
.nb2-cal-form { display: flex; flex-direction: column; gap: 12px; }
.nb2-cal-group { display: flex; flex-direction: column; gap: 11px; padding: 13px 14px; border-radius: 12px; border: 1px solid var(--hair, rgba(255,255,255,.12)); background: rgba(10,17,40,.4); }
.nb2-cal-group--cold { border-color: rgba(0,229,255,.32); background: linear-gradient(180deg, rgba(0,229,255,.07), rgba(0,229,255,.015)); box-shadow: inset 0 1px 0 rgba(0,229,255,.12); }
.nb2-cal-group-h { font-size: 12px; font-weight: 700; letter-spacing: .02em; color: var(--text, #F8FAFC); }
.nb2-cal-group--cold .nb2-cal-group-h { color: var(--cyan, #00E5FF); }
.nb2-cal-field { display: flex; flex-direction: column; gap: 4px; }
.nb2-cal-field.is-cold { padding: 9px 11px; border-radius: 8px; border: 1px solid rgba(0,229,255,.5); background: rgba(0,229,255,.07); }
.nb2-cal-field.is-cold .nb2-cal-label::after { content: " 🔒"; font-size: .82em; opacity: .85; }
.nb2-cal-label { font-size: 12.5px; color: var(--text, #F8FAFC); font-weight: 600; }
.nb2-cal-hint { font-size: 11px; color: var(--muted, #9FB3C8); line-height: 1.45; }
.nb2-cal-input {
  background: var(--navy-panel, #0F1D3A); color: var(--text, #F8FAFC);
  border: 1px solid var(--hair, rgba(255,255,255,.16)); border-radius: 7px; padding: 7px 10px;
  font-size: 12.5px; font-family: inherit; resize: vertical; min-height: 2.2em;
}
textarea.nb2-cal-input { min-height: 3.2em; line-height: 1.5; }
.nb2-cal-input:focus { outline: none; border-color: var(--cyan, #00E5FF); box-shadow: 0 0 0 2px rgba(0,229,255,.2); }
.nb2-cal-input:disabled { opacity: .8; cursor: not-allowed; border-color: var(--cyan, #00E5FF); }
.nb2-cal-cold-note { font-size: 11.5px; color: var(--cyan, #00E5FF); margin: 0 0 2px; line-height: 1.5; padding: 8px 11px; border-left: 2px solid var(--cyan, #00E5FF); background: rgba(0,229,255,.05); border-radius: 0 7px 7px 0; }
.nb2-cal-stamp { font-size: 11px; color: var(--muted, #9FB3C8); margin-top: 10px; font-style: italic; }
.nb2-cal-science { margin-top: 14px; border-top: 1px solid var(--hair, rgba(255,255,255,.1)); padding-top: 10px; }
.nb2-cal-science-toggle { font-size: 11.5px; color: var(--cyan, #00E5FF); cursor: pointer; list-style: none; }
.nb2-cal-science-toggle::-webkit-details-marker { display: none; }
.nb2-cal-science-toggle::before { content: "▸ "; }
.nb2-cal-science[open] .nb2-cal-science-toggle::before { content: "▾ "; }
.nb2-cal-science-body { font-size: 11.5px; color: var(--muted, #9FB3C8); line-height: 1.55; margin-top: 8px; }
.nb2-cal-science-body ul { margin: 6px 0 0; padding-left: 18px; }
.nb2-cal-science-body li { margin: 4px 0; }
.nb2-cal-science-body strong { color: var(--text, #F8FAFC); }

/* MIND: the metacognitive support layer (Phase 2). Calm by default; the dot lights only
   when the learner has actually put a structural move in place. Glass Canon, no greens. */
.nb2-mind { position: relative; opacity: .82; }
.nb2-mind:hover { opacity: 1; }
.nb2-mind.has-moves::after {
  content: ""; position: absolute; top: 5px; right: 6px; width: 6px; height: 6px; border-radius: 50%;
  background: var(--cyan, #00E5FF); box-shadow: 0 0 5px var(--cyan, #00E5FF);
}
.nb2-mind-dlg { max-width: 560px; width: min(560px, 92vw); }
.nb2-mind-lede { color: var(--muted, #9FB3C8); font-size: 12px; line-height: 1.55; margin: 4px 0 10px; }
.nb2-mind-summary { font-size: 11.5px; color: var(--cyan, #00E5FF); margin-bottom: 12px; }
.nb2-mind-card { border: 1px solid var(--hair, rgba(255,255,255,.12)); border-radius: 8px; margin-bottom: 8px; background: rgba(10,17,40,.4); }
.nb2-mind-card-head { cursor: pointer; padding: 9px 12px; display: flex; justify-content: space-between; align-items: baseline; gap: 12px; list-style: none; }
.nb2-mind-card-head::-webkit-details-marker { display: none; }
.nb2-mind-card-head::before { content: "▸ "; color: var(--cyan, #00E5FF); }
.nb2-mind-card[open] .nb2-mind-card-head::before { content: "▾ "; }
.nb2-mind-card-title { font-size: 12.5px; font-weight: 600; color: var(--text, #F8FAFC); min-width: 0; }
.nb2-mind-card-when { font-size: 10.5px; color: var(--muted, #9FB3C8); font-style: italic; white-space: nowrap; }
.nb2-mind-card-body { padding: 2px 12px 12px; display: flex; flex-direction: column; gap: 8px; }
.nb2-mind-card-blurb { font-size: 12px; color: var(--text, #F8FAFC); line-height: 1.5; }
.nb2-mind-input {
  background: var(--navy-panel, #0F1D3A); color: var(--text, #F8FAFC);
  border: 1px solid var(--hair, rgba(255,255,255,.16)); border-radius: 7px; padding: 7px 10px;
  font-size: 12.5px; font-family: inherit; resize: vertical;
}
textarea.nb2-mind-input { min-height: 3.2em; line-height: 1.5; }
.nb2-mind-input:focus { outline: none; border-color: var(--cyan, #00E5FF); box-shadow: 0 0 0 2px rgba(0,229,255,.2); }
.nb2-mind-preview { font-size: 12px; color: var(--cyan, #00E5FF); font-style: italic; min-height: 1em; }
.nb2-mind-advice { font-size: 12px; color: var(--text, #F8FAFC); line-height: 1.5; padding: 8px 10px; border-radius: 7px; border-left: 2px solid var(--cyan, #00E5FF); background: rgba(0,229,255,.05); }
.nb2-mind-evidence { font-size: 10.5px; color: var(--muted, #9FB3C8); font-style: italic; line-height: 1.45; }
.nb2-mind-card .nb-btn { align-self: flex-start; }
/* PHASE 3 overlay: the metacog tool threaded under each C in the 7-Cs guide. Quiet. */
.nb2-sevencs-mind { display: flex; align-items: center; gap: 8px; margin-top: 6px; padding: 5px 8px; border-radius: 6px; background: rgba(0,229,255,.05); border-left: 2px solid var(--cyan, #00E5FF); }
.nb2-sevencs-mind-icon { font-size: 12px; opacity: .85; }
.nb2-sevencs-mind-txt { font-size: 11px; color: var(--muted, #9FB3C8); flex: 1; line-height: 1.4; }
.nb2-sevencs-mind .nb-btn { flex: none; }

/* CHANNEL cockpit: engagement presets + capture-surface toggles. Glass Canon. */
.nb2-channel { max-width: 540px; width: min(540px, 92vw); }
.nb2-chan-lede { color: var(--muted, #9FB3C8); font-size: 12px; line-height: 1.55; margin: 4px 0 12px; }
.nb2-chan-h { font-size: 10.5px; text-transform: uppercase; letter-spacing: .08em; color: var(--muted, #9FB3C8); margin: 16px 0 8px; padding-bottom: 5px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.08)); }
.nb2-chan-modes { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 8px; }
.nb2-chan-mode { text-align: left; background: rgba(10,17,40,.5); border: 1px solid var(--hair, rgba(255,255,255,.14)); border-radius: 10px; padding: 11px 13px; cursor: pointer; color: var(--text, #F8FAFC); transition: transform .12s ease, border-color .12s ease, background .12s ease; }
.nb2-chan-mode:hover { border-color: rgba(0,229,255,.5); transform: translateY(-1px); background: rgba(10,17,40,.72); }
.nb2-chan-mode.is-on { border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.08); box-shadow: 0 0 0 1px rgba(0,229,255,.3), 0 4px 14px rgba(0,229,255,.08); }
.nb2-chan-mode-label { font-size: 13px; font-weight: 600; }
.nb2-chan-mode-hint { font-size: 11.5px; color: var(--muted, #9FB3C8); margin-top: 3px; line-height: 1.4; }
.nb2-chan-mode-coming { font-size: 10.5px; color: var(--warn, #F59E0B); font-style: italic; margin-top: 4px; }
.nb2-chan-surfaces { display: flex; flex-wrap: wrap; gap: 7px; }
.nb2-chan-surface { background: rgba(10,17,40,.5); border: 1px solid var(--hair, rgba(255,255,255,.16)); border-radius: 20px; padding: 6px 14px; cursor: pointer; color: var(--muted, #9FB3C8); font-size: 12.5px; transition: border-color .12s ease, background .12s ease, color .12s ease; }
.nb2-chan-surface:hover { border-color: rgba(0,229,255,.4); color: var(--text, #F8FAFC); }
.nb2-chan-surface.is-on { border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.1); color: var(--cyan, #00E5FF); font-weight: 600; }
.nb2-chan-used { margin-top: 14px; font-size: 11.5px; line-height: 1.5; }
.nb2-chan-used-label { color: var(--muted, #9FB3C8); }
.nb2-chan-used-val { color: var(--cyan, #00E5FF); }

/* CHUNK board: the per-note concept map + auto-chunk suggestions. Glass Canon. */
.nb2-chunk { max-width: 620px; width: min(620px, 94vw); }
.nb2-chunk-lede { color: var(--muted, #9FB3C8); font-size: 12px; line-height: 1.55; margin: 4px 0 10px; }
.nb2-chunk-board { border: 1px solid var(--hair, rgba(255,255,255,.1)); border-radius: 8px; padding: 6px; background: rgba(10,17,40,.35); margin-bottom: 12px; overflow: auto; }
.nb2-chunk-board svg { display: block; max-width: 100%; height: auto; }
.nb2-chunk-empty { font-size: 12px; color: var(--muted, #9FB3C8); font-style: italic; line-height: 1.5; margin-bottom: 12px; }
.nb2-chunk-auto-h { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--muted, #9FB3C8); margin-bottom: 8px; }
.nb2-chunk-auto-row { display: flex; flex-wrap: wrap; gap: 7px; }
.nb2-chunk-chip {
  display: inline-flex; align-items: center; gap: 6px; background: rgba(0,229,255,.07);
  border: 1px solid var(--cyan, #00E5FF); border-radius: 14px; padding: 5px 12px; cursor: pointer;
  color: var(--text, #F8FAFC); font-size: 12px;
}
.nb2-chunk-chip:hover { background: rgba(0,229,255,.15); }
.nb2-chunk-chip-plus { color: var(--cyan, #00E5FF); font-weight: 700; }
.nb2-chunk-auto-empty { font-size: 11.5px; color: var(--muted, #9FB3C8); font-style: italic; }

/* CONSOLIDATE panel: the co-authored summary surface. Glass Canon. */
.nb2-consol { max-width: 560px; width: min(560px, 92vw); }
.nb2-consol-lede { color: var(--muted, #9FB3C8); font-size: 12px; line-height: 1.55; margin: 4px 0 10px; }
.nb2-consol-input {
  width: 100%; box-sizing: border-box; min-height: 7em; line-height: 1.55;
  background: var(--navy-panel, #0F1D3A); color: var(--text, #F8FAFC);
  border: 1px solid var(--hair, rgba(255,255,255,.16)); border-radius: 8px; padding: 10px 12px;
  font-size: 13px; font-family: inherit; resize: vertical;
}
.nb2-consol-input:focus { outline: none; border-color: var(--cyan, #00E5FF); box-shadow: 0 0 0 2px rgba(0,229,255,.2); }
.nb2-consol-gauge { margin-top: 10px; font-size: 11.5px; color: var(--cyan, #00E5FF); line-height: 1.5; }

/* CLASSIFY panel: felt comfort beside earned bar, + AEIOUY lenses. Glass Canon. */
.nb2-classify { max-width: 600px; width: min(600px, 94vw); }
.nb2-classify-lede { color: var(--muted, #9FB3C8); font-size: 12px; line-height: 1.55; margin: 4px 0 12px; }
.nb2-classify-empty { font-size: 12px; color: var(--muted, #9FB3C8); font-style: italic; line-height: 1.5; }
.nb2-classify-list { display: flex; flex-direction: column; gap: 9px; margin-bottom: 14px; }
.nb2-classify-row { display: grid; grid-template-columns: minmax(90px,1.4fr) 1fr auto; align-items: center; gap: 10px; }
.nb2-classify-name { font-size: 12.5px; color: var(--text, #F8FAFC); min-width: 0; overflow-wrap: anywhere; }   /* min-width:0 so a long concept name can't blow out the first grid track */
@media (max-width: 480px) { .nb2-classify-row { grid-template-columns: 1fr; gap: 6px; } }   /* phone: stack name / bar / comfort chips vertically */

/* TRANSIENT UNDO TOAST: shown after a reversible dismiss, auto-fades. Cyan accent. */
.nb2-toast-host { position: fixed; left: 50%; bottom: 22px; transform: translateX(-50%); z-index: 9999; pointer-events: none; }
.nb2-toast {
  pointer-events: auto; display: flex; align-items: center; gap: 14px; padding: 10px 14px; border-radius: 10px;
  background: var(--navy-panel, #0F1D3A); color: var(--text, #F8FAFC); border: 1px solid var(--cyan, #00E5FF);
  box-shadow: 0 8px 28px rgba(0,0,0,.45); font-size: 12.5px; opacity: 1; transition: opacity .28s ease;
}
.nb2-toast.is-out { opacity: 0; }
.nb2-toast-undo { background: transparent; border: none; color: var(--cyan, #00E5FF); font-weight: 700; cursor: pointer; font-size: 12.5px; padding: 2px 4px; }
.nb2-toast-undo:hover { text-decoration: underline; }

/* DISMISSED recovery bin: dig dismissed cues back out (one click to restore). */
.nb2-dismissed-bin { margin-top: 10px; border-top: 1px dashed var(--hair, rgba(255,255,255,.12)); padding-top: 8px; }
.nb2-dismissed-toggle { font-size: 11.5px; color: var(--muted, #9FB3C8); cursor: pointer; list-style: none; }
.nb2-dismissed-toggle::-webkit-details-marker { display: none; }
.nb2-dismissed-toggle:hover { color: var(--text, #F8FAFC); }
.nb2-dismissed-list { margin-top: 6px; display: flex; flex-direction: column; gap: 5px; }
.nb2-dismissed-row { display: flex; align-items: center; gap: 8px; justify-content: space-between; }
.nb2-dismissed-text { font-size: 11.5px; color: var(--muted, #9FB3C8); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-dismissed-restore { flex: none; }
.nb2-dismissed-all { margin-top: 7px; background: transparent; border: 1px solid var(--hair, rgba(255,255,255,.18)); color: var(--cyan, #00E5FF); border-radius: 6px; font-size: 11px; padding: 3px 9px; cursor: pointer; }
.nb2-dismissed-all:hover { border-color: var(--cyan, #00E5FF); }

/* RECAP flagged band: starred cues + notebook tags, pinned ABOVE the synthesis box. */
.nb2-recap-flagged { margin-bottom: 9px; padding-bottom: 8px; border-bottom: 1px solid var(--hair, rgba(255,255,255,.10)); display: flex; flex-direction: column; gap: 7px; }
.nb2-recap-tags { display: flex; align-items: center; flex-wrap: wrap; gap: 6px; }
.nb2-recap-tagchip { font-size: 11px; padding: 1px 8px; border-radius: 999px; border: 1px solid var(--cyan, #00E5FF); color: var(--cyan, #00E5FF); background: rgba(0,229,255,.06); }
.nb2-recap-starred .nb2-recap-label { color: var(--cyan, #00E5FF); }
.nb2-recap-star-list li::marker { color: var(--cyan, #00E5FF); }

/* LEARN FROM YOUTUBE panel (IO hub): the async video-intake headline. Cyan-framed. */
.nb2-iohub-yt { margin: 8px 0 10px; padding: 11px 13px; border: 1px solid var(--cyan, #00E5FF); border-radius: 10px; background: rgba(0,229,255,.05); }
.nb2-iohub-yt .nb2-iohub-h { margin-top: 0; }
.nb2-iohub-yt-row { display: flex; gap: 8px; margin-top: 9px; }
.nb2-iohub-yt-input {
  flex: 1 1 auto; min-width: 0; background: var(--navy-panel, #0F1D3A);
  border: 1px solid var(--hair, rgba(255,255,255,.18)); color: var(--text, #F8FAFC);
  border-radius: 7px; padding: 7px 10px; font-size: 12.5px;
}
.nb2-iohub-yt-input::placeholder { color: var(--muted, #9FB3C8); }
.nb2-iohub-yt-input:focus { outline: none; border-color: var(--cyan, #00E5FF); box-shadow: 0 0 0 2px rgba(0,229,255,.25); }
.nb2-iohub-yt-status { margin-top: 8px; font-size: 11.5px; color: var(--muted, #9FB3C8); min-height: 1em; line-height: 1.45; }
.nb2-iohub-yt-status.is-busy, .nb2-iohub-yt-status.is-ok { color: var(--cyan, #00E5FF); }
.nb2-iohub-yt-status.is-warn { color: var(--warn, #F59E0B); }

/* the one-line framing that names the chosen approach at the top of a step. */
.nb2-review-strategy-note {
  font-size: 11.5px; line-height: 1.5; color: var(--muted, #9FB3C8);
  padding: 7px 10px; border-left: 2px solid var(--glass-edge, rgba(84,239,255,.22));
  background: rgba(0,229,255,.04); border-radius: 0 6px 6px 0;
}
/* the AEIOUY lens row: six calm chips; tap marks a lens "considered" (formative). */
.nb2-vowels { display: flex; flex-direction: column; gap: 7px; }
.nb2-vowels-label {
  font-size: 11px; text-transform: uppercase; letter-spacing: .06em; color: var(--cyan-glow, #54EFFF);
}
.nb2-vowels-row { display: flex; flex-wrap: wrap; gap: 6px; }
.nb2-vowel {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 10px 5px 6px; border-radius: 8px;
  border: 1px solid var(--hair, rgba(255,255,255,.12));
  background: var(--navy-panel, rgba(8,18,32,.45)); color: var(--text, #F8FAFC);
  font: inherit; font-size: 11.5px; text-align: left; cursor: pointer; max-width: 100%;
}
.nb2-vowel:hover { border-color: var(--glass-edge, rgba(84,239,255,.3)); }
.nb2-vowel.is-on { border-color: var(--cyan, #00E5FF); background: rgba(0,229,255,.08); }
.nb2-vowel-letter {
  flex: none; width: 20px; height: 20px; border-radius: 50%;
  display: grid; place-items: center; font-weight: 700; font-size: 12px;
  border: 1px solid var(--glass-edge, rgba(84,239,255,.3)); color: var(--cyan, #00E5FF);
}
.nb2-vowel.is-on .nb2-vowel-letter { background: var(--cyan, #00E5FF); color: var(--on-cyan-ink); border-color: var(--cyan, #00E5FF); }
.nb2-vowel-prompt { color: var(--muted, #9FB3C8); line-height: 1.3; }
.nb2-vowel.is-on .nb2-vowel-prompt { color: var(--text, #F8FAFC); }

/* ── CONFIDENCE OF COMFORT (Classify): the per-concept felt-comfort chips in the
   Record, + the read-only per-cue echo. Cyan is the single signal (only the chosen
   level glows); the amber/cyan inset is a quiet tone hint on the selected chip. ── */
.nb2-comfort { display: flex; gap: 6px; margin-top: 6px; flex-wrap: wrap; }
.nb2-comfort-chip {
  font-size: 11px; padding: 2px 9px; border-radius: 8px;
  border: 1px solid var(--hair, rgba(255,255,255,.12)); background: var(--navy-panel, rgba(8,18,32,.45));
  color: var(--muted, #9FB3C8); cursor: pointer; font: inherit;
  transition: border-color .12s, color .12s;
}
.nb2-comfort-chip:hover { border-color: var(--glass-edge, var(--cyan, #00E5FF)); }
.nb2-comfort-chip.is-on { border-color: var(--cyan, #00E5FF); color: var(--cyan-glow, #54EFFF); }
.nb2-comfort--shaky.is-on { box-shadow: inset 2px 0 0 var(--warn, #F59E0B); }
.nb2-comfort--solid.is-on { box-shadow: inset 2px 0 0 var(--ok, #00E5FF); }
.nb2-comfort-chip:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; }
/* read-only per-cue echo: muted, no interaction affordance */
.nb-cue-comfort {
  display: inline-block; margin-top: 3px; font-size: 10.5px;
  padding: 1px 7px; border-radius: 7px; border: 1px solid var(--hair, rgba(255,255,255,.12));
  color: var(--muted, #9FB3C8); background: var(--navy-panel, rgba(8,18,32,.45));
}
.nb-cue-comfort.nb2-comfort--shaky { border-color: rgba(245,158,11,.40); }
.nb-cue-comfort.nb2-comfort--solid { border-color: rgba(0,229,255,.45); }

/* ── DEVICE CHECK (e-ink capability probe): the ⋯ More → "Device check" panel. ── */
.nb2-eink-check { min-width: min(440px, 92vw); max-width: 520px; }
.nb2-eink-check-body { display: flex; flex-direction: column; gap: 10px; padding: 14px; }
.nb2-eink-verdict {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 10px 12px; border-radius: 9px;
  border: 1px solid var(--hair, rgba(255,255,255,.12)); background: var(--navy-panel, rgba(8,18,32,.45));
  font-size: 12.5px; line-height: 1.5; color: var(--text, #F8FAFC);
}
.nb2-eink-verdict.is-eink { border-color: var(--glass-edge, rgba(84,239,255,.3)); background: rgba(0,229,255,.05); }
.nb2-eink-verdict-mark { flex: none; font-size: 15px; line-height: 1.3; color: var(--cyan, #00E5FF); }
.nb2-probe-list { display: flex; flex-direction: column; gap: 1px; border-radius: 8px; overflow: hidden; }
.nb2-probe-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 7px 11px; background: var(--navy-panel, rgba(8,18,32,.4));
  border-left: 2px solid var(--hair, rgba(255,255,255,.12));
}
.nb2-probe--ok   { border-left-color: var(--ok, #00E5FF); }
.nb2-probe--warn { border-left-color: var(--warn, #F59E0B); }
.nb2-probe-label { font-size: 12px; color: var(--muted, #9FB3C8); }
.nb2-probe-value { font-size: 12px; color: var(--text, #F8FAFC); text-align: right; }
.nb2-probe--warn .nb2-probe-value { color: #F59E0B; }
.nb2-probe-hint { font-size: 11px; line-height: 1.5; color: var(--muted, #9FB3C8); }

/* E-INK: flatten sketch ink to black. Sketch strokes are INLINE svg `stroke`
   attributes (e.g. cyan #54EFFF) the token rebind can't reach; CSS `stroke`
   overrides a presentation attribute, so this forces every sketch line to solid
   black under paper mode. Also flatten the hover/lock outlines. */
body.eink .nb2-sketch svg,
body.eink .nb2-sketch svg * { stroke: #000 !important; fill: none !important; }
body.eink .nb2-sketch:hover { outline-color: #000 !important; }
body.eink .nb2-sketch.is-locked:hover { outline-color: #444 !important; }

/* ── PHONE-DRAW: on the mobile pair role (opened via the pair QR, ?role=mobile),
   the Draw surface goes FULLSCREEN + touch-sized so a phone becomes a sketch pad
   that relays each stroke to the desktop (the relay itself already runs in
   onLauncherReadyMobile → POST /api/push). The canvas keeps the 640:380 aspect
   (width:100%, height:auto) so strokes never distort, xy() maps via
   getBoundingClientRect, so a bigger canvas just means a bigger drawing area. ── */
body[data-pair-role="mobile"] #nb-draw {
  width: 100vw; max-width: 100vw;
  height: 100vh; height: 100dvh; max-height: 100dvh;
  margin: 0; border: 0; border-radius: 0; padding: 0;
  display: flex; flex-direction: column;
}
body[data-pair-role="mobile"] #nb-draw .nb-dialog-head { flex-wrap: wrap; }
body[data-pair-role="mobile"] #nb-draw .nb-draw-canvas {
  width: 100%; height: auto; max-height: none; flex: 0 0 auto; touch-action: none;
}
/* finger-friendly draw-tool targets on the phone */
body[data-pair-role="mobile"] #nb-draw .nb-shape,
body[data-pair-role="mobile"] #nb-draw .nb-ink,
body[data-pair-role="mobile"] #nb-draw .nb-btn { min-width: 40px; min-height: 40px; }
/* the phone surface leads with capture; mark Draw as the primary action */
body[data-pair-role="mobile"] .nb-cap[data-cap="draw"] {
  border-color: var(--glass-edge, var(--cyan, #00E5FF)); color: var(--cyan-glow, #54EFFF);
}

/* ============================================================================
   WIRE 1d: BUILD RECALL PROMPTS (CpC GENERATION). The Construct C, done FOR the
   learner. A calm cyan-edged action in the Cues column (beside the CpC indicator it
   fills) + the editable curate dialog. Glass Canon: navy field, cyan = the one signal,
   Montserrat (inherited), WCAG AA contrast, #00E5FF focus rings. Never loud, never a nag.
   ============================================================================ */
.nb2-cpc-build {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0 0 10px;
  padding: 6px 12px;
  border: 1px solid var(--cyan, #00E5FF);
  border-radius: 999px;
  background: rgba(0, 229, 255, .08);
  color: var(--text, #F8FAFC);
  font: inherit;
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  transition: background .12s ease, box-shadow .12s ease;
}
.nb2-cpc-build:hover { background: rgba(0, 229, 255, .16); box-shadow: 0 0 0 3px rgba(0, 229, 255, .10); }
.nb2-cpc-build:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; }
.nb2-cpc-build:disabled { opacity: .55; cursor: default; box-shadow: none; }

/* the curate dialog: reuses .nb-dialog / .nb-dialog-head / .nb-dialog-actions / .nb-btn
   chrome from the base sheet; only the editable row list is new. */
.nb2-cpc-curate { width: min(680px, 94vw); }
.nb2-cpc-curate-body { display: flex; flex-direction: column; gap: 12px; max-height: 78vh; overflow: auto; }
.nb2-cpc-curate-list { display: flex; flex-direction: column; gap: 8px; }
.nb2-cpc-curate-row {
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 7px 9px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 9px;
  background: var(--field-2, rgba(12, 22, 38, 0.6));
}
.nb2-cpc-curate-check {
  flex: none;
  width: 16px; height: 16px;
  accent-color: var(--cyan, #00E5FF);
  cursor: pointer;
}
.nb2-cpc-curate-check:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; }
.nb2-cpc-curate-text {
  flex: 1 1 auto;
  min-width: 0;
  padding: 5px 8px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 6px;
  background: var(--field, rgba(8, 18, 32, .55));
  color: var(--text, #F8FAFC);
  font: inherit;
  font-size: 12.5px;
}
.nb2-cpc-curate-text:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; border-color: var(--cyan, #00E5FF); }
.nb2-cpc-curate-kind {
  flex: none;
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--muted, #9FB3C8);
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 4px;
  padding: 1px 5px;
}

/* ============================================================================
   WIRE 2: THE CONSOLIDATION SCAFFOLD. The Consolidate C, made active. A calm assist at
   the foot of the Summary zone (Learn-mode only): the honest message + own-words / connect
   / explain-back nudges + clickable connection chips. Progressive disclosure, never a nag.
   ============================================================================ */
.nb2-consolidate {
  margin: 12px 0 0;
  padding: 10px 12px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 10px;
  background: var(--navy-panel, rgba(8, 18, 32, .45));
  display: flex;
  flex-direction: column;
  gap: 9px;
}
.nb2-consolidate[hidden] { display: none; }
.nb2-consolidate.is-ok { border-color: rgba(0, 229, 255, .40); }
.nb2-consolidate.is-warn { border-color: rgba(245, 158, 11, .38); }
.nb2-consolidate-head { display: flex; align-items: baseline; gap: 6px; }
.nb2-consolidate-dot { font-size: 10px; line-height: 1; flex: none; color: var(--muted, #9FB3C8); }
.nb2-consolidate.is-ok .nb2-consolidate-dot { color: var(--ok, #00E5FF); }
.nb2-consolidate.is-warn .nb2-consolidate-dot { color: var(--warn, #F59E0B); }
.nb2-consolidate-label {
  font-size: 11px; font-weight: 700; letter-spacing: .05em; text-transform: uppercase;
  color: var(--text, #F8FAFC);
}
.nb2-consolidate-msg { margin: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted, #9FB3C8); }
.nb2-consolidate-prompts { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 7px; }
.nb2-consolidate-prompt {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  padding: 6px 9px;
  border-left: 2px solid var(--hair-strong, rgba(255, 255, 255, .14));
  border-radius: 0 6px 6px 0;
  background: var(--field-2, rgba(12, 22, 38, 0.5));
}
.nb2-consolidate-prompt.is-own-words { border-left-color: var(--cyan, #00E5FF); }
.nb2-consolidate-prompt.is-connect { border-left-color: var(--cyan-glow, #54EFFF); }
.nb2-consolidate-prompt.is-explain-back { border-left-color: var(--ok, #00E5FF); }
.nb2-consolidate-prompt-text { flex: 1 1 auto; min-width: 0; font-size: 12px; line-height: 1.4; color: var(--text, #F8FAFC); }
.nb2-consolidate-explain { flex: none; }
.nb2-consolidate-chips { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.nb2-consolidate-chips-label { font-size: 11px; color: var(--muted, #9FB3C8); }
.nb2-consolidate-chip {
  display: inline-flex; align-items: center;
  padding: 3px 10px;
  border: 1px solid var(--cyan, #00E5FF);
  border-radius: 999px;
  background: rgba(0, 229, 255, .08);
  color: var(--text, #F8FAFC);
  font: inherit; font-size: 11.5px; font-weight: 600;
  cursor: pointer;
  transition: background .12s ease, box-shadow .12s ease;
}
.nb2-consolidate-chip:hover { background: rgba(0, 229, 255, .16); box-shadow: 0 0 0 3px rgba(0, 229, 255, .10); }
.nb2-consolidate-chip:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 2px; }
/* the connection bases read with a quiet edge tint so backlink > shared-concept > tag is legible. */
.nb2-consolidate-chip.basis-shared-concept { border-color: var(--cyan-glow, #54EFFF); }
.nb2-consolidate-chip.basis-tag { border-color: var(--hair-strong, rgba(255, 255, 255, .18)); background: rgba(255, 255, 255, .04); }

/* explain-back box: the generation-effect self-check. Navy field, cyan signal. */
.nb2-explain-box {
  flex-basis: 100%;
  margin-top: 6px;
  display: flex; flex-direction: column; gap: 7px;
}
.nb2-explain-input {
  width: 100%; box-sizing: border-box;
  min-height: 54px; resize: vertical;
  padding: 7px 9px;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 7px;
  background: var(--field, rgba(8, 18, 32, .55));
  color: var(--text, #F8FAFC);
  font: inherit; font-size: 12.5px; line-height: 1.45;
}
.nb2-explain-input:focus-visible { outline: 2px solid var(--cyan, #00E5FF); outline-offset: 1px; border-color: var(--cyan, #00E5FF); }
.nb2-explain-actions { display: flex; gap: 8px; }
.nb2-explain-result { font-size: 12px; line-height: 1.5; color: var(--cyan-glow, #54EFFF); }

/* ============================================================================
   WIRE 3: "SEE THIS NOTE'S STRUCTURE" (nb_structure_viz). The active note as a radial
   concept map. Reuses .nb-dialog / .nb-dialog-head chrome (mirrors .nb2-iris); only the
   SVG frame is new: navy field, cyan instrument-light, the module paints the rest.
   ============================================================================ */
.nb2-structure { width: min(840px, 95vw); }
.nb2-structure-body { display: flex; flex-direction: column; gap: 10px; max-height: 80vh; overflow: auto; }
.nb-structure-svg {
  width: 100%; height: auto; display: block;
  border: 1px solid var(--hair, rgba(159, 179, 200, 0.16));
  border-radius: 10px;
  background: var(--field-2, rgba(12, 22, 38, 0.6));
}

/* ── THE 7 Cs: always-visible path nav (canon nb_sevencs, replaces the 4-step stub) ── */
/* One line at the top by default; WRAP to more rows only when the viewport can't hold it (operator ask).
   flex-wrap keeps every step visible instead of the old overflow-x scroll that hid steps behind a fade. */
.nb-flow--7cs{position:sticky;top:0;z-index:40;display:flex;align-items:center;flex-wrap:wrap;gap:6px;row-gap:7px;
  flex:0 0 auto;min-height:44px;box-sizing:border-box;
  padding:8px max(14px, calc((100vw - min(1440px, 92vw)) / 2 + 14px));margin:0;background:var(--navy-panel);border-bottom:1px solid var(--hair)}
.nb-cstep{flex:none;display:inline-flex;align-items:center;gap:7px;background:transparent;border:1px solid var(--hair);
  border-radius:8px;padding:5px 11px;color:var(--muted);font-weight:500;font-size:11.5px;line-height:1;cursor:pointer;white-space:nowrap;font-family:inherit}
.nb-cstep:hover{color:var(--text);border-color:var(--cyan)}
.nb-cstep:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}
/* the C's glyph inherits the chip's live colour (muted -> cyan "now" -> ice-cyan done): the icon IS the signal. */
.nb-cstep-ico{width:16px;height:16px;flex:none}
.nb-cstep-tick{font-size:10px;font-weight:800;line-height:1;margin-left:-3px;color:var(--ok)}
.nb-cstep.is-done{color:var(--ok)}
/* the "now" pointer reads as the obvious next action: a filled, gently-glowing chip, distinct
   from is-done (cyan glyph + text, no glow). Stays within the single cyan signal. */
.nb-cstep.is-now{color:var(--cyan);border-color:var(--cyan);background:rgba(0,229,255,.10);box-shadow:0 0 0 1px var(--cyan),0 0 9px rgba(0,229,255,.32);font-weight:600}
.nb-flow-pivot{flex:none;color:var(--cyan);font-size:15px;font-weight:800;padding:0 2px}
/* SELECTING a C lights it up + mutes the others (wayfinding clarity, operator ask). */
.nb-cstep{transition:opacity .18s ease,filter .18s ease,border-color .18s ease,background .18s ease}
.nb-flow-sel .nb-cstep:not(.is-sel){opacity:.5;filter:saturate(.7)}
.nb-cstep.is-sel:not(.is-now){color:var(--text);border-color:var(--cyan);background:rgba(0,229,255,.06)}

/* ── DRAW shape helper (pen/line/arrow/rect/ellipse) for diagramming on the fly ── */
.nb-draw-shapes{display:inline-flex;gap:4px;margin-right:2px}
.nb-shape{width:30px;height:28px;display:inline-flex;align-items:center;justify-content:center;background:transparent;
  border:1px solid var(--hair);border-radius:7px;color:var(--muted);font-size:14px;line-height:1;cursor:pointer;font-family:inherit}
.nb-shape:hover{color:var(--text);border-color:var(--cyan)}
.nb-shape--on{color:var(--cyan);border-color:var(--cyan);background:rgba(0,229,255,.10)}
.nb-shape:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}
.nb-draw-sep{display:inline-block;width:1px;height:20px;background:var(--hair);margin:0 6px;vertical-align:middle}

/* ── DRAW ink palette (Glass-Canon colours, not just electric blue on navy) ── */
.nb-draw-colors{display:inline-flex;gap:5px;margin:0 2px;align-items:center}
.nb-ink{width:20px;height:20px;border-radius:50%;border:2px solid transparent;background:var(--ink,#54EFFF);cursor:pointer;padding:0;transition:transform .1s}
.nb-ink:hover{transform:scale(1.14)}
.nb-ink--on{border-color:#fff;box-shadow:0 0 0 2px rgba(255,255,255,.22)}
.nb-ink:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}

/* ── real highlighter (drag-to-mark text) + click-to-edit drawings ── */
.nb2-hl{background:rgba(255,207,92,.38);border-radius:2px;padding:0 1px;box-decoration-break:clone;-webkit-box-decoration-break:clone}
.nb-cap--on{color:var(--cyan);border-color:var(--cyan);background:rgba(0,229,255,.10)}
.nb-cap--busy{color:var(--cyan);border-color:var(--cyan);background:rgba(0,229,255,.06);animation:nb-listen-warm 1.2s ease-in-out infinite}
@keyframes nb-listen-warm{50%{box-shadow:inset 0 0 0 1px rgba(0,229,255,.4)}}
@media (prefers-reduced-motion: reduce){.nb-cap--busy{animation:none}}
body.nb2-highlighter .ProseMirror,body.nb2-highlighter .ProseMirror *{cursor:cell}
.nb2-sketch{cursor:pointer}
.nb2-sketch:hover{outline:1px solid var(--cyan);outline-offset:2px;border-radius:6px}
.nb2-sketch.is-locked{cursor:not-allowed}
.nb2-sketch.is-locked:hover{outline:1px dashed var(--muted)}


/* ============================================================================
   E-INK MODE: Lane B keystone for notebook2 (LearnNote on e-readers)

   GOAL: make the Glass Canon notebook readable + usable on e-ink (BOOX primary,
   Supernote/Kindle Scribe secondary). E-ink hates animation, partial-refresh
   blur/shadow/gradient ghosting, and low-contrast cyan-on-navy. So under e-ink
   we flip to a paper surface: pure white field, near-black ink, flat 1-2px
   solid borders, cyan-as-signal demoted to a solid dark underline/border (no
   glow), and EVERY animation / transition / backdrop-filter / blur / box-shadow
   / gradient killed. Tap targets >= 44px. The 7 Cs bar, capture bar, and all
   buttons stay usable.

   TWO SWITCHES, ONE LOOK:
     (1) body.eink            : the PRIMARY manual switch (the toggle button +
                                 the boot-time localStorage restore set this).
     (2) @media auto-detect   : (update: slow) OR (monochrome) OR
                                 (prefers-contrast: more). Fires with no JS at
                                 all, so a no-JS e-reader still gets paper.

   SCOPING: the manual rules live under `body.eink ...`; the media block re-uses
   the SAME declarations but ALSO guards each with :not(.eink-off) so a learner
   who explicitly turns e-ink OFF on a slow-update screen is honored (the toggle
   JS writes body.eink-off in that case). Normal (non-eink, fast-update, color)
   rendering is never touched, none of these selectors match without body.eink
   or one of the three media features.

   Paste this block at the END of notebook2.css (after every other rule) so its
   flat overrides win by source order, no !important needed except where a
   token-driven box-shadow/gradient is set inline on a single rule.
   ============================================================================ */

/* ─── e-ink design tokens: overridden on the scope, inherited by every rule ───
   We re-point the Glass Canon tokens to a paper palette. Because the whole
   stylesheet is authored against var(--cyan)/var(--text)/var(--hair)/… , simply
   re-binding the tokens on body.eink repaints ~90% of the UI to paper for free;
   the explicit rules below mop up the glows, gradients, and motion the tokens
   can't reach. */
body.eink {
  --cyan:        #000000;   /* signal demoted: solid black, never a glow */
  --cyan-glow:   #000000;
  --blue:        #000000;
  --azure:       #000000;
  --text:        #0a0a0a;   /* near-black ink */
  --muted:       #3a3a3a;   /* high-contrast secondary (>= 7:1 on white) */
  --text-dim:    #3a3a3a;   /* secondary text (Expose lede/empty/labels) — the base sheet only ever
                               uses var(--text-dim,#9fb2d6), never defining it, so on paper it stayed
                               #9fb2d6 = 2.14:1 on white (WCAG-AA FAIL; visual_receipts expose-eink).
                               Bind it to the same >=7:1 ink so paper copy is legible. */
  --ok:          #0a0a0a;
  --persistence-ok: #0a0a0a;
  --warn:        #0a0a0a;
  --err:         #0a0a0a;
  --hair:        #444444;   /* flat solid hairlines, not translucent */
  --hair-strong: #000000;
  --glass-edge:  #000000;   /* "glass edge" becomes a plain black border */
  --navy-panel:  #ffffff;
  --navy-slate:  #ffffff;
  --navy-shell:  #ffffff;
  --navy-deep:   #ffffff;
  /* a11y (refine 4): the iohub / export panels fill with var(--field-1|2|…),
     which the base sheet leaves at a translucent dark-navy FALLBACK — never
     defined on the light canon, so on paper it stayed dark and rendered
     near-black ink on navy (WCAG-AA FAIL, axe SERIOUS on sync-eink). Bind the
     field tokens to paper so every panelled surface repaints white for free. */
  --field:       #ffffff;
  --field-1:     #ffffff;
  --field-2:     #ffffff;
  --ink:         #0a0a0a;   /* panel-text token (iohub/ai/history headings): the base
                               default is near-WHITE, so on the paper panels above it
                               was white-on-white (axe SERIOUS, sync-eink). Ink it. */
  --on-cyan-ink: #ffffff;   /* text that rides ON a cyan fill (COCA count badge, cue-due
                               chip, vowel-on): on paper --cyan demotes to #000, so the base
                               near-navy ink (#06121f) went black-on-black — illegible
                               (refine5 coca-eink badge, 1.05:1). White ink on the black
                               fill is the paper canon (mirrors .nb-cue-due below). */
  --shadow:      none;      /* every var(--shadow) box-shadow flattens */
  --radius:      4px;       /* crisp, slightly-softened corners read fine on e-ink */

  /* pure white field, near-black ink, no gradient, no fixed-attachment glow */
  background: #ffffff !important;
  color: #0a0a0a !important;
}

/* ── KILL all motion + GPU compositing artifacts the moment e-ink is on ──
   One broad sweep: no transition, no animation, no backdrop-filter, no blur
   filter. Scoped to descendants of body.eink so it never leaks to normal mode. */
body.eink *,
body.eink *::before,
body.eink *::after {
  transition: none !important;
  animation: none !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
  scroll-behavior: auto !important;
  text-shadow: none !important;
  box-shadow: none !important;
}

/* ── HIDE the "Living" ambient: there is no <canvas>; the ambient register IS
   the fixed body gradient + the cyan radial glow + the per-element glows. We
   already flattened the body field above; this also neutralizes any blur()
   filter and any decorative ::before/::after wash. ── */
body.eink {
  background-attachment: scroll !important;
}
body.eink .nb-rail,
body.eink .nb-notes,
body.eink .nb-cues,
body.eink .nb-summary,
body.eink .nb-record,
body.eink .nb2-library,
body.eink .nb-coach,
body.eink .nb2-partner-card,
body.eink .nb-dialog,
body.eink .nb2-slash-popup,
body.eink .nb2-more #nb2-more-menu,
body.eink .nb2-editor {
  background: #ffffff !important;
  background-image: none !important;       /* drop every gradient + ruling wash */
  filter: none !important;
  -webkit-filter: none !important;
}

/* LearnFloat: an opt-in recovery ledger. It is deliberately a single compact
   settings surface rather than another permanent dashboard element. */
.nb2-learnfloat { width: min(620px, 94vw); }
.nb2-learnfloat-body { display: flex; flex-direction: column; gap: 14px; max-height: 76vh; overflow: auto; }
.nb2-learnfloat-state {
  display: grid; grid-template-columns: 10px minmax(0, 1fr); gap: 10px;
  align-items: start; padding: 10px 0; border-block: 1px solid var(--hair);
}
.nb2-learnfloat-lamp { width: 9px; height: 9px; margin-top: 4px; border: 1px solid currentColor; border-radius: 50%; color: var(--muted); background: transparent; }
.nb2-learnfloat-state[data-state="connected"] .nb2-learnfloat-lamp { color: var(--correct, #54EFFF); background: currentColor; }
.nb2-learnfloat-state[data-state="interrupted"] .nb2-learnfloat-lamp { color: var(--warn, #F59E0B); border-radius: 2px; }
.nb2-learnfloat-state-copy { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.nb2-learnfloat-state-copy strong { color: var(--text); font: 650 13px/1.35 Montserrat, Inter, sans-serif; }
.nb2-learnfloat-state-copy span { color: var(--muted); font-size: 11.5px; line-height: 1.5; overflow-wrap: anywhere; }
.nb2-learnfloat-actions { display: flex; align-items: center; flex-wrap: wrap; gap: 8px; }
.nb2-learnfloat-scope { margin: 0; padding-left: 18px; color: var(--muted); font-size: 11.5px; line-height: 1.55; }
.nb2-learnfloat-note { margin: 0; color: var(--muted); font-size: 11.5px; line-height: 1.55; }
.nb2-learnfloat-file {
  display: inline-block; max-width: 100%; padding: 3px 6px; border: 1px solid var(--hair);
  border-radius: 4px; color: var(--cyan); background: rgba(84,239,255,.04);
  font-family: var(--mono, ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace);
  font-size: 11px; overflow-wrap: anywhere;
}
body.eink .nb2-persistence,
body.eink .nb2-secondary,
body.eink #nb-local[data-save-state],
body.eink .nb2-page-title-input {
  background: #ffffff !important;
  color: #0a0a0a !important;
  border-color: #000000 !important;
  box-shadow: none !important;
}
body.eink .nb-notes[data-persistence-state] .nb2-editor { border-inline-start-color: #000000 !important; }

/* ── FLAT 1-2px SOLID BORDERS everywhere a translucent edge / glass-edge was ── */
body.eink .nb-rail,
body.eink .nb-flow,
body.eink .nb-notes,
body.eink .nb-cues,
body.eink .nb-summary,
body.eink .nb-record,
body.eink .nb2-library,
body.eink .nb-coach,
body.eink .nb2-partner-card,
body.eink .nb-chip,
body.eink .nb-search,
body.eink .nb-mode,
body.eink .nb-btn,
body.eink .nb-cap,
body.eink .nb-cue,
body.eink .nb-cue-filter,
body.eink .nb2-editor,
body.eink .nb2-search,
body.eink .nb2-status-bar,
body.eink .nb2-tag-add,
body.eink .nb2-tag-chip,
body.eink .nb-dialog,
body.eink .nb2-slash-popup,
body.eink #nb2-more-menu {
  border: 1px solid #000000 !important;
  border-radius: 4px !important;
}
/* the header rail + the 7 Cs path read as a clean ruled separator, not a card */
body.eink .nb-rail { border: 0 !important; border-bottom: 2px solid #000000 !important; border-radius: 0 !important; }
body.eink .nb-flow { border: 0 !important; border-bottom: 1px solid #000000 !important; border-radius: 0 !important; }
/* the edge-fade mask softens pixels: drop it on the flat high-contrast paper view */
body.eink .nb-flow--7cs { -webkit-mask-image: none !important; mask-image: none !important; }

/* ── INK + READABILITY: force near-black text on the paper field, kill the
   antialiased smoothing that softens glyphs on a grayscale panel ── */
body.eink,
body.eink .nb2-editor .ProseMirror,
body.eink .nb-source,
body.eink .nb-name,
body.eink .nb-zone-h,
body.eink .nb-cue,
body.eink .nb2-status-item,
body.eink .nb-coach-title,
body.eink .nb2-partner-question {
  color: #0a0a0a !important;
  -webkit-font-smoothing: never;
  text-rendering: optimizeLegibility;
}
body.eink .nb-tag,
body.eink .nb-muted,
body.eink .nb-anchor,
body.eink .nb-zone-sub,
body.eink .nb-cue-kind,
body.eink .nb2-status-hint,
body.eink .nb-coach-why,
body.eink .nb2-partner-foot,
body.eink ::placeholder { color: #3a3a3a !important; }

/* ── CYAN-AS-SIGNAL → SOLID DARK UNDERLINE / BORDER (never a glow) ──
   Active segments, the active 7-Cs step, active cue filters, "due" pills, the
   coach mark, the partner ✦, and links all carry signal via a heavy black
   underline or a solid black border instead of cyan + box-shadow. */
body.eink .nb-seg--on,
body.eink .nb2-focus-toggle[aria-pressed="true"],
body.eink .nb-cue-filter--on,
body.eink .nb-mode .nb-seg--on,
body.eink .nb2-more-btn[aria-expanded="true"],
body.eink .nb2-eink-toggle[aria-pressed="true"] {
  background: #ffffff !important;
  color: #000000 !important;
  border: 2px solid #000000 !important;
  text-decoration: underline !important;
  text-decoration-thickness: 2px !important;
  text-underline-offset: 2px !important;
  font-weight: 700 !important;
}
/* the 7Cs strip is .nb-cstep now (+ the active library note, the build-
   prompts button, and the teach-expectancy box), kill the residual cyan bg/glow these
   keep in e-ink and signal via solid black border/fill like the segments above. */
body.eink .nb-cstep.is-now,
body.eink .nb2-library-note.is-active,
body.eink .nb2-cpc-build {
  background: #ffffff !important; color: #000000 !important;
  border-color: #000000 !important; box-shadow: none !important;
}
/* paper mode is monochrome: the done C's glyph + tick read as solid black, not the cyan --ok. */
body.eink .nb-cstep.is-done,
body.eink .nb-cstep.is-done .nb-cstep-tick { color: #000000 !important; }
body.eink .nb2-teach-expectancy { background: #ffffff !important; box-shadow: none !important; }
/* zone heading tick + cue-seeded mark + coach/partner mark: solid black, no glow */
body.eink .nb-zone-h::before,
body.eink .nb-cue--seeded .nb-cue-mark,
body.eink .nb-coach-icon,
body.eink .nb2-partner-mark,
body.eink .nb-brand,
body.eink .nb-hero-mark { color: #000000 !important; background: #000000 !important; }
body.eink .nb-zone-h::before { background: #000000 !important; }
/* "due for review" pill: was cyan fill → black fill, white text (still a clear chip) */
body.eink .nb-cue-due { background: #000000 !important; color: #ffffff !important; }
body.eink .nb-cue--due { box-shadow: inset 3px 0 0 0 #000000 !important; }
/* local/sync chip dot + pair-live dot: solid black, no glow */
body.eink .nb-dot,
body.eink .nb-chip--local .nb-dot,
body.eink .nb-chip[data-synced="true"] .nb-dot,
body.eink .nb2-secondary-lamp,
body.eink .nb2-attention-dot { background: #000000 !important; box-shadow: none !important; }
/* links + in-editor links: black, underlined (the canon already underlines them) */
body.eink .nb2-editor .ProseMirror a,
body.eink a { color: #000000 !important; text-decoration: underline !important; }
/* caret stays visible as black ink */
body.eink .nb2-editor .ProseMirror { caret-color: #000000 !important; }

/* ── THE EDITOR SURFACE: drop the navy ruling-gradient for a clean white sheet
   with faint solid rules so the Cornell cadence survives without a gradient ── */
body.eink .nb2-editor:not(.lines-off) {
  background: #ffffff !important;
  background-image:
    repeating-linear-gradient(to bottom,
      transparent 0, transparent calc(var(--nb2-rule, 28px) - 1px),
      #cfcfcf calc(var(--nb2-rule, 28px) - 1px), #cfcfcf var(--nb2-rule, 28px)) !important;   /* flat solid rule, no rgba wash; rides the display-control cadence like the media twin */
  background-position: 0 calc(var(--nb2-rule, 28px) / 2 - 1px) !important;
}
body.eink .nb2-editor:focus-within {
  border: 2px solid #000000 !important;
  box-shadow: none !important;
}
/* code / pre / blockquote / callout: white field, solid black edge, no cyan wash */
body.eink .nb2-editor .ProseMirror code,
body.eink .nb2-editor .ProseMirror pre,
body.eink .nb2-editor .ProseMirror blockquote,
body.eink .nb2-editor .ProseMirror blockquote[data-callout],
body.eink .nb2-codeblock-wrap > pre {
  background: #ffffff !important;
  color: #0a0a0a !important;
  border: 1px solid #000000 !important;
}
body.eink .nb2-editor .ProseMirror blockquote,
body.eink .nb2-editor .ProseMirror blockquote[data-callout] { border-left: 3px solid #000000 !important; }
/* hljs syntax colors → all black ink under e-ink (color can't carry meaning) */
body.eink .nb2-editor .ProseMirror [class^="hljs-"],
body.eink .nb2-editor .ProseMirror [class*=" hljs-"] { color: #0a0a0a !important; }
body.eink .nb2-editor .ProseMirror .hljs-keyword,
body.eink .nb2-editor .ProseMirror .hljs-title,
body.eink .nb2-editor .ProseMirror .hljs-strong { font-weight: 700 !important; }
/* bullets: solid black, not cyan */
body.eink .nb2-editor .ProseMirror ul > li::before { color: #000000 !important; }
/* search highlight (Custom Highlight API): black-on-white inverse, no cyan wash */
body.eink ::highlight(nb2-find) { background: #d9d9d9; color: #000000; }
body.eink ::highlight(nb2-find-active) { background: #000000; color: #ffffff; }

/* ── 44px TAP TARGETS: every interactive control comfortably finger/stylus
   sized on a high-DPI e-reader. min-height + padding, never shrink below 44. ── */
body.eink .nb-btn,
body.eink .nb-cap,
body.eink .nb-seg,
body.eink .nb-cue-filter,
body.eink .nb-cue-act,
body.eink .nb2-search-nav,
body.eink .nb2-focus-toggle,
body.eink .nb2-eink-toggle,
body.eink .nb2-more-btn,
body.eink .nb-shape,
body.eink .nb-ink,
body.eink .nb-tag-label,
body.eink .nb2-partner button,
body.eink #nb2-more-menu > .nb-btn {
  min-height: 44px !important;
  min-width: 44px !important;
  padding: 10px 14px !important;
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
}
/* [hidden] stays hidden ON PAPER. The tap-target rule above forces
   display:inline-flex !important across the whole button family, which outranks
   the UA (and this sheet's own non-!important) [hidden] guards — so paper mode
   was RESURRECTING controls the app had switched off: the fresh-notebook hero
   grew the returning-learner doors (Start something new / Just browsing), and
   the gated "Extract text" / "Recognize handwriting" buttons surfaced with
   nothing to act on (copy != behavior, Tenet I). Same specificity, later in the
   sheet → hidden wins again; the more-menu row needs the id-weighted variant to
   outrank its id-weighted sizer. (The auto-detect media path below only forces
   min-height, so it never had this bug.) */
body.eink [hidden],
body.eink #nb2-more-menu > .nb-btn[hidden] { display: none !important; }
/* segmented control: keep the two segments butted but each >= 44px tall */
body.eink .nb-mode { min-height: 44px !important; }
body.eink .nb-mode .nb-seg { min-height: 44px !important; }
/* form inputs + textareas also get the comfortable touch height */
body.eink input,
body.eink textarea,
body.eink .nb-search input,
body.eink .nb2-search-input,
body.eink .nb2-tag-input,
body.eink .nb-cue-add input {
  min-height: 44px !important;
  background: #ffffff !important;
  color: #0a0a0a !important;
  border: 1px solid #000000 !important;
}

/* ── DIALOGS + POPUPS: paper panels, solid black edge, no blurred backdrop ── */
body.eink .nb-dialog,
body.eink .nb2-slash-popup,
body.eink #nb2-more-menu,
body.eink .nb2-pair-dialog {
  background: #ffffff !important;
  color: #0a0a0a !important;
  border: 2px solid #000000 !important;
}
body.eink .nb-dialog::backdrop {
  background: rgba(0,0,0,.35) !important;
  -webkit-backdrop-filter: none !important;
  backdrop-filter: none !important;
}
/* slash-menu selected/hover row: black border, no cyan wash */
body.eink .nb2-slash-item.is-selected,
body.eink .nb2-slash-item:hover { background: #e6e6e6 !important; }

/* ── BUTTON FILLS on paper (a11y: axe color-contrast, refine 4) ──
   The eink token re-bind pointed TEXT to near-black but never touched the button
   FILL: .nb-btn kept its base rgba(22,42,77,.7) navy and .nb-btn--primary its
   solid blue — so every button rendered near-black ink on a dark field (~1.3:1
   and ~2.9:1, WCAG-AA FAIL, axe SERIOUS on every eink surface). On paper a
   resting button is white with black ink + the black border it already carries
   (~19:1); a PRIMARY button keeps its "this is the emphasized action" signal by
   inverting to solid black with white text (the same signal-inversion the
   segmented control uses on paper), also ~19:1. Both switches (manual + the
   auto-detect media block below) are covered. */
body.eink .nb-btn,
body.eink .nb-cap,
body.eink .nb2-partner button,
body.eink #nb2-more-menu > .nb-btn {
  background: #ffffff !important;
  background-image: none !important;
  color: #0a0a0a !important;
}
body.eink .nb-btn--primary {
  background: #000000 !important;
  background-image: none !important;
  color: #ffffff !important;
  border-color: #000000 !important;
}
/* ── RAW-RGBA PANEL FILLS the token re-bind can't reach → paper (a11y refine 4).
   .nb2-status-bar and .nb2-attention-chip hard-code a translucent dark-navy
   background (not a var), so on paper their near-black caption/label text sat on
   a dark field (axe SERIOUS, editor/coca/synth-eink). Flatten them to white. */
body.eink .nb2-status-bar,
body.eink .nb2-attention-chip {
  background: #ffffff !important;
  color: #0a0a0a !important;
}
/* the status-hint + attention-label are secondary ink on that now-white bar */
body.eink .nb2-status-hint,
body.eink .nb2-attention-label { color: #3a3a3a !important; opacity: 1 !important; }

/* ── HOVER STATES that relied on translucent cyan washes → flat gray on e-ink ── */
body.eink .nb-btn:hover,
body.eink .nb-cap:hover,
body.eink .nb-cue-filter:hover,
body.eink .nb2-search-nav:hover { background: #ececec !important; border-color: #000000 !important; color: #000000 !important; }
/* primary keeps its inverted signal on hover: stay black-on-white-text, just lift */
body.eink .nb-btn--primary:hover { background: #1a1a1a !important; color: #ffffff !important; }

/* ── FOCUS MODE under e-ink: drop the inset glow + dim-via-opacity (opacity on
   e-ink just looks muddy). Keep the layout change, lose the glow. ── */
body.eink.nb2-focus .nb2-editor { box-shadow: none !important; border: 2px solid #000000 !important; }
body.eink.nb2-focus .nb-flow,
body.eink.nb2-focus .nb-coach,
body.eink.nb2-focus .nb-cues,
body.eink.nb2-focus .nb-summary,
body.eink.nb2-focus .nb-record { opacity: 1 !important; filter: none !important; }
body.eink.nb2-focus .nb2-editor .ProseMirror > * { opacity: 1 !important; }

/* ============================================================================
   AUTO-DETECT: the same paper look with ZERO JavaScript.
   Fires on (update: slow) [e-ink panels report slow updates], (monochrome)
   [grayscale displays], or (prefers-contrast: more). Each rule is guarded by
   body:not(.eink-off) so a learner who EXPLICITLY disabled e-ink (toggle writes
   body.eink-off) is honored even on a slow screen. Where a learner hasn't
   touched the toggle, the media query alone delivers paper.

   Implementation note: rather than duplicate ~250 lines, the media block simply
   re-applies the e-ink token scope + the motion-kill to the body, which (via the
   var() re-binding) cascades the paper palette through the whole sheet exactly
   like body.eink does. The explicit !important glow/gradient overrides above are
   ALSO emitted here, scoped to the media + :not(.eink-off) guard, so the auto
   path is visually identical to the manual one.
   ============================================================================ */
@media (update: slow), (monochrome), (prefers-contrast: more) {
  body:not(.eink-off) {
    --cyan: #000000; --cyan-glow: #000000; --blue: #000000; --azure: #000000;
    --text: #0a0a0a; --muted: #3a3a3a;
    --ok: #0a0a0a; --persistence-ok: #0a0a0a; --warn: #0a0a0a; --err: #0a0a0a;
    --hair: #444444; --hair-strong: #000000; --glass-edge: #000000;
    --navy-panel: #ffffff; --navy-slate: #ffffff; --navy-shell: #ffffff; --navy-deep: #ffffff;
    --field: #ffffff; --field-1: #ffffff; --field-2: #ffffff;   /* a11y refine 4: iohub panels → paper */
    --ink: #0a0a0a;   /* a11y refine 4: panel-text token → ink (was near-white) */
    --on-cyan-ink: #ffffff;   /* refine 5: on paper --cyan → #000, so on-cyan ink (COCA badge)
                                 was black-on-black; white ink on the black fill (paper canon) */
    --shadow: none; --radius: 4px;
    background: #ffffff !important;
    background-attachment: scroll !important;
    color: #0a0a0a !important;
  }
  body:not(.eink-off) *,
  body:not(.eink-off) *::before,
  body:not(.eink-off) *::after {
    transition: none !important;
    animation: none !important;
    -webkit-backdrop-filter: none !important;
    backdrop-filter: none !important;
    text-shadow: none !important;
    box-shadow: none !important;
  }
  body:not(.eink-off) .nb-rail,
  body:not(.eink-off) .nb-notes,
  body:not(.eink-off) .nb-cues,
  body:not(.eink-off) .nb-summary,
  body:not(.eink-off) .nb-record,
  body:not(.eink-off) .nb2-library,
  body:not(.eink-off) .nb-coach,
  body:not(.eink-off) .nb2-partner-card,
  body:not(.eink-off) .nb-dialog,
  body:not(.eink-off) .nb2-slash-popup,
  body:not(.eink-off) #nb2-more-menu,
  body:not(.eink-off) .nb2-editor {
    background: #ffffff !important;
    background-image: none !important;
    filter: none !important;
  }
  body:not(.eink-off) .nb2-persistence,
  body:not(.eink-off) .nb2-secondary,
  body:not(.eink-off) #nb-local[data-save-state],
  body:not(.eink-off) .nb2-page-title-input {
    background: #ffffff !important;
    color: #0a0a0a !important;
    border-color: #000000 !important;
  }
  body:not(.eink-off) .nb-notes[data-persistence-state] .nb2-editor { border-inline-start-color: #000000 !important; }
  body:not(.eink-off) .nb-rail { border: 0 !important; border-bottom: 2px solid #000 !important; border-radius: 0 !important; }
  body:not(.eink-off) .nb-flow { border: 0 !important; border-bottom: 1px solid #000 !important; border-radius: 0 !important; }
  body:not(.eink-off) .nb-zone-h::before,
  body:not(.eink-off) .nb-cue--seeded .nb-cue-mark,
  body:not(.eink-off) .nb-coach-icon,
  body:not(.eink-off) .nb2-partner-mark,
  body:not(.eink-off) .nb-brand { color: #000 !important; }
  body:not(.eink-off) .nb-cue-due { background: #000 !important; color: #fff !important; }
  body:not(.eink-off) .nb-dot,
  body:not(.eink-off) .nb2-attention-dot { background: #000 !important; }
  body:not(.eink-off) .nb-seg--on,
  body:not(.eink-off) .nb-cue-filter--on,
  body:not(.eink-off) .nb2-focus-toggle[aria-pressed="true"],
  body:not(.eink-off) .nb2-eink-toggle[aria-pressed="true"] {
    background: #fff !important; color: #000 !important; border: 2px solid #000 !important;
    text-decoration: underline !important; text-decoration-thickness: 2px !important; font-weight: 700 !important;
  }
  body:not(.eink-off) .nb2-editor:not(.lines-off) {
    background-image:
      repeating-linear-gradient(to bottom, transparent 0, transparent calc(var(--nb2-rule, 28px) - 1px), #cfcfcf calc(var(--nb2-rule, 28px) - 1px), #cfcfcf var(--nb2-rule, 28px)) !important;
    background-position: 0 calc(var(--nb2-rule, 28px) / 2 - 1px) !important;
  }
  body:not(.eink-off) .nb2-editor .ProseMirror [class^="hljs-"],
  body:not(.eink-off) .nb2-editor .ProseMirror [class*=" hljs-"] { color: #0a0a0a !important; }
  body:not(.eink-off) .nb2-editor .ProseMirror ul > li::before { color: #000 !important; }
  body:not(.eink-off) .nb2-editor .ProseMirror a,
  body:not(.eink-off) a { color: #000 !important; text-decoration: underline !important; }
  /* 44px tap targets in the auto path too */
  body:not(.eink-off) .nb-btn,
  body:not(.eink-off) .nb-cap,
  body:not(.eink-off) .nb-seg,
  body:not(.eink-off) .nb-cue-filter,
  body:not(.eink-off) .nb-cue-act,
  body:not(.eink-off) .nb2-search-nav,
  body:not(.eink-off) .nb2-focus-toggle,
  body:not(.eink-off) .nb2-eink-toggle,
  body:not(.eink-off) .nb2-more-btn,
  body:not(.eink-off) input,
  body:not(.eink-off) textarea {
    min-height: 44px !important;
  }
  body:not(.eink-off) .nb-dialog::backdrop { background: rgba(0,0,0,.35) !important; backdrop-filter: none !important; }
  /* button fills on paper — the no-JS twin of the body.eink rule above (a11y:
     axe color-contrast, refine 4). Without this the auto-detect path rendered
     near-black ink on the base navy / blue button fills. */
  body:not(.eink-off) .nb-btn,
  body:not(.eink-off) .nb-cap,
  body:not(.eink-off) .nb2-partner button,
  body:not(.eink-off) #nb2-more-menu > .nb-btn {
    background: #ffffff !important;
    background-image: none !important;
    color: #0a0a0a !important;
    border: 1px solid #000 !important;
  }
  body:not(.eink-off) .nb-btn--primary {
    background: #000 !important;
    background-image: none !important;
    color: #fff !important;
    border: 1px solid #000 !important;
  }
  /* raw-rgba panel fills → paper (no-JS twin, a11y refine 4) */
  body:not(.eink-off) .nb2-status-bar,
  body:not(.eink-off) .nb2-attention-chip {
    background: #fff !important;
    color: #0a0a0a !important;
  }
  body:not(.eink-off) .nb2-status-hint,
  body:not(.eink-off) .nb2-attention-label { color: #3a3a3a !important; opacity: 1 !important; }
}

/* ============================================================================
   PREFERS-CONTRAST: MORE on paper — push the sub-black tones to full ink.
   The paper palette already carries near-black text on white; a learner who
   ALSO asks the OS for more contrast gets the secondary ink and every hairline
   at solid black (~21:1), so no border or caption sits below their preference.
   Covers BOTH switches (manual body.eink and the media auto-detect above,
   whose query now includes prefers-contrast as its header promised). Sits
   AFTER both so the re-bind wins by source order; an explicit body.eink-off
   opt-out is still honored — neither selector matches it, and the normal navy
   canon is never touched (prefers-contrast alone already routes to paper).
   ============================================================================ */
@media (prefers-contrast: more) {
  body.eink,
  body:not(.eink-off) {
    --muted: #000000;
    --hair: #000000;
    --hair-strong: #000000;
  }
}

body.eink .nb2-practice-card,
body.eink .nb2-practice-choice,
body.eink .nb2-practice-why {
  background: #ffffff !important;
  background-image: none !important;
  color: #0a0a0a !important;
  border-color: #000000 !important;
  box-shadow: none !important;
}
body.eink .nb2-practice-choice.is-selected {
  box-shadow: inset 3px 0 0 #000000 !important;
  font-weight: 700 !important;
}
@media (update: slow), (monochrome), (prefers-contrast: more) {
  body:not(.eink-off) .nb2-practice-card,
  body:not(.eink-off) .nb2-practice-choice,
  body:not(.eink-off) .nb2-practice-why {
    background: #ffffff !important;
    background-image: none !important;
    color: #0a0a0a !important;
    border-color: #000000 !important;
    box-shadow: none !important;
  }
  body:not(.eink-off) .nb2-practice-choice.is-selected {
    box-shadow: inset 3px 0 0 #000000 !important;
    font-weight: 700 !important;
  }
}

/* BYOQ — Evaluate This Question (LearnNote core · LearnQuiz ULR) */
.nb2-byq-panel {
  margin-top: 14px;
  padding: 14px 16px;
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  background: rgba(15, 29, 58, 0.35);
}
.nb2-byq-lede { font-size: 13px; color: var(--muted); margin: 0 0 10px; line-height: 1.45; }
.nb2-byq-preview { margin: 10px 0; max-height: 180px; overflow: auto; }
.nb2-byq-thumb { max-width: 100%; height: auto; border: 1px solid var(--hair); border-radius: 6px; }
.nb2-byq-key-row {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px;
  margin: 10px 0 6px; font-size: 13px;
}
.nb2-byq-key-label { color: var(--muted); }
.nb2-byq-key-select {
  min-width: 9rem; padding: 4px 8px; border-radius: 6px;
  border: 1px solid var(--hair); background: var(--surface, #1a1a1a); color: var(--text);
}
.nb2-byq-attest-label {
  display: flex; align-items: flex-start; gap: 8px;
  font-size: 13px; margin: 10px 0; cursor: pointer;
}
.nb2-byq-actions { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0; }
.nb2-byq-stem-label { font-size: 12px; color: var(--muted); margin: 12px 0 4px; }
.nb2-byq-stem { font-size: 14px; line-height: 1.45; margin-bottom: 10px; }
.nb2-byq-receipts { display: flex; flex-direction: column; gap: 12px; margin-top: 8px; }
.nb2-byq-h { font-size: 13px; margin: 0 0 6px; color: var(--cyan); }
.nb2-byq-dl { margin: 0; font-size: 13px; }
.nb2-byq-dl dt { font-weight: 600; margin-top: 6px; }
.nb2-byq-dl dd { margin: 2px 0 0 0; color: var(--text); opacity: 0.92; }
.nb2-byq-list { margin: 0; padding-left: 1.2rem; font-size: 13px; }
.nb2-byq-vr-pass { color: var(--ok, #7dcea0); }
.nb2-byq-vr-kill { color: var(--warn, #f5b041); }
.nb2-byq-tier { font-size: 13px; margin: 0; }
.nb2-byq-empty { font-size: 13px; color: var(--muted); margin: 0; }

/* ═══════════════════ KNOWLEDGE LAYER: glossary + citations + readings ═══════════════════
   Read-only chrome over DECORATIONS and already-stamped marks: nothing here
   mutates the doc. The .nb2-gloss class arrives via ProseMirror inline
   decorations (editor.js GlossaryUnderline), never via doc bytes. */

/* acronym underline: subtle, spellcheck-calm, never a link-blue */
.ProseMirror .nb2-gloss {
  text-decoration: underline dotted rgba(84, 239, 255, .55);
  text-underline-offset: 3px;
  cursor: help;
}

/* the hover/tap popover (glass register, worry-plate family) */
.nb2-gloss-pop {
  z-index: 60;
  width: min(320px, calc(100vw - 24px));
  padding: 10px 12px;
  border: 1px solid rgba(84, 239, 255, .4);
  border-radius: 8px;
  background:
    linear-gradient(135deg, rgba(37, 67, 113, .94), rgba(22, 42, 77, .84)),
    radial-gradient(circle at 22% 0%, rgba(84, 239, 255, .14), transparent 38%);
  box-shadow: 0 0 28px rgba(84, 239, 255, .16), inset 0 0 18px rgba(84, 239, 255, .06);
  backdrop-filter: blur(8px);
  color: var(--text, #F8FAFC);
  font-size: 13px;
}
.nb2-gloss-pop[hidden] { display: none; }
.nb2-gloss-pop-head { display: flex; align-items: baseline; gap: 8px; margin-bottom: 4px; }
.nb2-gloss-pop-term { color: var(--cyan, #54efff); letter-spacing: .04em; }
.nb2-gloss-pop-src {
  font-size: 10px; text-transform: uppercase; letter-spacing: .08em;
  color: var(--muted, #9FB3C8); border: 1px solid var(--hair, rgba(255,255,255,.12));
  border-radius: 999px; padding: 1px 8px; white-space: nowrap;
}
.nb2-gloss-pop-exp { line-height: 1.45; margin-bottom: 8px; }
.nb2-gloss-pop-acts { display: flex; flex-wrap: wrap; gap: 6px; }

/* realtime citation chip: superscript marker on capture-stamped attribution
   (cite[data-cite]) and foreign-provenance ranges (span[data-source]) */
.ProseMirror cite[data-cite] { font-style: inherit; }
.ProseMirror cite[data-cite]::after,
.ProseMirror span[data-provenance][data-source]::after {
  content: "❞";
  font-size: .62em;
  vertical-align: super;
  line-height: 0;
  margin-left: 2px;
  color: var(--cyan, #54efff);
  opacity: .75;
}

/* resources panel: Citations + Go deeper sections */
.nb2-cite-list, .nb2-deeper-list { display: flex; flex-direction: column; gap: 4px; }
.nb2-cite-item {
  display: flex; align-items: baseline; gap: 8px; width: 100%;
  padding: 5px 6px; border: 0; border-radius: 6px; background: transparent;
  color: var(--text, #F8FAFC); text-align: left; font-size: 12.5px; cursor: pointer;
}
.nb2-cite-item:hover { background: rgba(84, 239, 255, .08); }
.nb2-cite-n { flex: none; color: var(--cyan, #54efff); font-size: 11px; }
.nb2-cite-tx { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.nb2-deeper-item { display: flex; flex-direction: column; gap: 1px; padding: 4px 0; }
.nb2-deeper-ti { font-size: 12.5px; color: var(--text, #F8FAFC); }
.nb2-deeper-ref { font-size: 11.5px; color: var(--muted, #9FB3C8); }

/* e-ink: monochrome calm for the knowledge layer */
body.eink .ProseMirror .nb2-gloss { text-decoration-color: #555555; }
body.eink .nb2-gloss-pop {
  background: #ffffff; border-color: #000000; box-shadow: none; backdrop-filter: none;
  color: #000000;
}
body.eink .nb2-gloss-pop-term { color: #000000; }
body.eink .ProseMirror cite[data-cite]::after,
body.eink .ProseMirror span[data-provenance][data-source]::after { color: #000000; }
body.eink .nb2-cite-n { color: #000000; }

/* CENTRAL WORKSPACE VIEW: one quiet rail popover, with native checkboxes. */
.nb2-view-control { position: relative; display: inline-flex; }
body.nb2-view-open .nb-rail { z-index: 100; }
body.nb2-more-open .nb-rail { z-index: 100; }

/* Optional live-class join. It lives in Channel and disappears completely when
   unused, preserving LearnNote's zero-login, zero-network local surface. */
.nb2-chan-learnnet {
  display: grid;
  gap: 10px;
  margin: 12px 0;
  padding: 12px;
  border: 1px solid var(--glass-edge);
  border-radius: 8px;
  background: rgba(10, 17, 40, .35);
}
.nb2-chan-learnnet-hint { margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.nb2-chan-learnnet-input {
  width: 100%;
  box-sizing: border-box;
  padding: 8px 10px;
  border: 1px solid var(--glass-edge);
  border-radius: 7px;
  background: rgba(0, 0, 0, .2);
  color: var(--text);
}
.nb2-chan-learnnet-actions,
.nb2-chan-learnnet-tabs,
.nb2-chan-learnnet-body { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; }
.nb2-chan-learnnet-body .nb2-chan-learnnet-input { flex: 1 1 220px; }
.nb2-chan-learnnet-connected { display: grid; gap: 8px; }
.nb2-chan-learnnet-state { display: flex; align-items: center; gap: 8px; min-width: 0; }
.nb2-chan-learnnet-state .nb-mastery-state { min-width: 0; margin: 0; }
.nb2-chan-learnnet-dot {
  width: 8px;
  height: 8px;
  flex: 0 0 8px;
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 0 3px rgba(84, 239, 255, .1);
}
.nb2-chan-learnnet-connected[data-connection-state="connecting"] .nb2-chan-learnnet-dot,
.nb2-chan-learnnet-connected[data-connection-state="unavailable"] .nb2-chan-learnnet-dot {
  background: var(--warn, #F59E0B);
  box-shadow: 0 0 0 3px rgba(255, 193, 7, .1);
}

/* LearnOS shell: flex column so the note grid can fill the viewport height. */
.learnos-shell {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.learnos-shell .nb-grid {
  flex: 1 1 auto;
}

/* LearnOS desk substrate: a calm, collapsible shelf under the active note. */
.nb-desk-substrate {
  position: relative;
  z-index: 12;
  margin-top: 10px;
  overflow: hidden;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: rgba(22, 42, 77, .32);
  box-shadow: var(--shadow);
}
.nb-desk-substrate[hidden], .nb-desk-body[hidden], .nb-desk-bucket[hidden], .nb-desk-count[hidden] { display: none; }
.nb-desk-toggle {
  width: 100%;
  min-height: 44px;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 13px;
  border: 0;
  background: transparent;
  color: var(--text);
  cursor: pointer;
  text-align: left;
}
.nb-desk-toggle:focus-visible { outline: 2px solid var(--cyan); outline-offset: -3px; }
.nb-desk-caret { color: var(--cyan); transition: transform .15s ease; }
.nb-desk-toggle[aria-expanded="true"] .nb-desk-caret { transform: rotate(90deg); }
.nb-desk-count {
  min-width: 22px;
  height: 22px;
  margin-left: auto;
  display: inline-grid;
  place-items: center;
  border: 1px solid var(--hair-strong);
  border-radius: 11px;
  color: var(--text);
  font-size: 11px;
}
.nb-desk-body { display: flex; flex-direction: column; gap: 8px; padding: 0 13px 12px; }
.nb-desk-empty { margin: 0; color: var(--muted); font-size: 12.5px; line-height: 1.45; }
.nb-desk-bucket {
  padding: 8px 10px;
  border: 1px solid var(--hair);
  border-radius: 7px;
  background: rgba(10, 17, 40, .28);
  color: var(--text);
  font-size: 12.5px;
}
@media (prefers-reduced-motion: reduce) { .nb-desk-caret { transition: none; } }
.nb2-view-toggle[aria-expanded="true"] { border-color: var(--glass-edge); background: rgba(0,229,255,.10); }
.nb2-view-toggle:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
.nb2-view-popover {
  position: fixed; z-index: 90; width: min(270px, calc(100vw - 24px)); max-height: calc(100vh - 24px);
  overflow-y: auto; padding: 10px; box-sizing: border-box; color: var(--text);
  background: var(--navy-panel); border: 1px solid var(--hair-strong); border-radius: 8px;
  box-shadow: 0 16px 42px rgba(0,0,0,.5);
}
.nb2-view-popover[hidden] { display: none; }
.nb2-view-options { min-width: 0; margin: 0; padding: 0; border: 0; }
.nb2-view-options legend { width: 100%; padding: 0 4px 7px; color: var(--muted); font-size: 11px; font-weight: 600; }
.nb2-view-option { display: flex; align-items: center; gap: 9px; min-height: 44px; padding: 8px 8px; border-radius: 5px; cursor: pointer; font-size: 12.5px; }
.nb2-view-option:hover { background: rgba(84,239,255,.07); }
.nb2-view-option input { width: 17px; height: 17px; flex: none; margin: 0; accent-color: var(--cyan); }
.nb2-view-option input:focus-visible { outline: 2px solid var(--cyan); outline-offset: 2px; }
body.eink .nb2-view-popover { color: #000; background: #fff !important; border-color: #000 !important; box-shadow: none; }
body.eink .nb2-view-options legend { color: #333 !important; }

/* Removing Pages, Cues, or Summary also removes their named grid tracks. */
body[data-workspace-layout="pages-cues-summary"] {
  --nb-view-columns: minmax(168px,16%) minmax(220px,28%) 1fr;
  --nb-view-learn-areas: "library cues notes" "library summary summary" "library record record";
  --nb-view-capture-areas: "library cues notes" "library summary summary";
  --nb-view-mobile-learn: "notes" "library" "cues" "summary" "record";
  --nb-view-mobile-capture: "notes" "library" "cues" "summary";
  --nb-view-capture-rows: 1fr auto;
}
body[data-workspace-layout="pages-cues"] {
  --nb-view-columns: minmax(168px,16%) minmax(220px,28%) 1fr;
  --nb-view-learn-areas: "library cues notes" "library record record";
  --nb-view-capture-areas: "library cues notes";
  --nb-view-mobile-learn: "notes" "library" "cues" "record";
  --nb-view-mobile-capture: "notes" "library" "cues";
  --nb-view-capture-rows: 1fr;
}
body[data-workspace-layout="pages-summary"] {
  --nb-view-columns: minmax(168px,18%) 1fr;
  --nb-view-learn-areas: "library notes" "library summary" "library record";
  --nb-view-capture-areas: "library notes" "library summary";
  --nb-view-mobile-learn: "notes" "library" "summary" "record";
  --nb-view-mobile-capture: "notes" "library" "summary";
  --nb-view-capture-rows: 1fr auto;
}
body[data-workspace-layout="pages"] {
  --nb-view-columns: minmax(168px,18%) 1fr;
  --nb-view-learn-areas: "library notes" "library record";
  --nb-view-capture-areas: "library notes";
  --nb-view-mobile-learn: "notes" "library" "record";
  --nb-view-mobile-capture: "notes" "library";
  --nb-view-capture-rows: 1fr;
}
body[data-workspace-layout="cues-summary"] {
  --nb-view-columns: minmax(220px,28%) 1fr;
  --nb-view-learn-areas: "cues notes" "summary summary" "record record";
  --nb-view-capture-areas: "cues notes" "summary summary";
  --nb-view-mobile-learn: "notes" "cues" "summary" "record";
  --nb-view-mobile-capture: "notes" "cues" "summary";
  --nb-view-capture-rows: 1fr auto;
}
body[data-workspace-layout="cues"] {
  --nb-view-columns: minmax(220px,28%) 1fr;
  --nb-view-learn-areas: "cues notes" "record record";
  --nb-view-capture-areas: "cues notes";
  --nb-view-mobile-learn: "notes" "cues" "record";
  --nb-view-mobile-capture: "notes" "cues";
  --nb-view-capture-rows: 1fr;
}
body[data-workspace-layout="summary"] {
  --nb-view-columns: minmax(0,1fr);
  --nb-view-learn-areas: "notes" "summary" "record";
  --nb-view-capture-areas: "notes" "summary";
  --nb-view-mobile-learn: "notes" "summary" "record";
  --nb-view-mobile-capture: "notes" "summary";
  --nb-view-capture-rows: 1fr auto;
}
body[data-workspace-layout="notes"] {
  --nb-view-columns: minmax(0,1fr);
  --nb-view-learn-areas: "notes" "record";
  --nb-view-capture-areas: "notes";
  --nb-view-mobile-learn: "notes" "record";
  --nb-view-mobile-capture: "notes";
  --nb-view-capture-rows: 1fr;
}
body:not(.nb2-watching)[data-workspace-layout] .nb-grid {
  grid-template-columns: var(--nb-view-columns);
  grid-template-areas: var(--nb-view-learn-areas);
}
body[data-mode="capture"]:not(.nb2-watching)[data-workspace-layout] .nb-grid {
  grid-template-areas: var(--nb-view-capture-areas);
  grid-template-rows: var(--nb-view-capture-rows);
}

/* Watch reuses the same complete Pages/Cues/Summary matrix as the workspace;
   the nested .nb-notes grid above owns source-specific rows. */
body.nb2-watching[data-workspace-layout] .nb-grid {
  grid-template-columns: var(--nb-view-columns);
  grid-template-areas: var(--nb-view-learn-areas);
  grid-template-rows: none;
}
body.nb2-watching[data-mode="capture"][data-workspace-layout] .nb-grid {
  grid-template-areas: var(--nb-view-capture-areas);
}

@media (max-width: 760px) {
  body:not(.nb2-watching)[data-workspace-layout] .nb-grid {
    grid-template-columns: minmax(0,1fr);
    grid-template-areas: var(--nb-view-mobile-learn);
    grid-template-rows: none;
  }
  body[data-mode="capture"]:not(.nb2-watching)[data-workspace-layout] .nb-grid { grid-template-areas: var(--nb-view-mobile-capture); }
  body.nb2-watching[data-workspace-layout] .nb-grid {
    grid-template-columns: minmax(0,1fr);
    grid-template-areas: var(--nb-view-mobile-learn);
    grid-template-rows: none;
  }
  body.nb2-watching[data-mode="capture"][data-workspace-layout] .nb-grid { grid-template-areas: var(--nb-view-mobile-capture); }
}

/* ============================================================================
   TECH COVER — navy glass OVER the current surface (not a replacement picture).
   Live frost: backdrop-filter on .nb-hero-page samples the real visible DOM
   (hero if hero is showing; the open note if a note is showing). Never clone
   #learnos-shell — .nb-hero { display:flex } and .nb-grid { display:grid }
   un-hide [hidden] siblings in a clone and paint leftover note/hero text.
   Close/Open = one transform+opacity on this one sheet. Rail stays above (z 22).
   Cyan = binding hairline + 1px inscription catch. Frost white = sheen hairline.
   No holiday ice. Rail wordmark/toggle stay still.
   ============================================================================ */
#nb-hero-glass {
  position: fixed;
  inset: 0;
  z-index: 18;
  pointer-events: auto;
  overflow: hidden;
  perspective: 1600px;
  perspective-origin: left center;
}
#nb-hero-glass[hidden] { display: none !important; pointer-events: none; }
body.nb-hero-open #nb-hero { position: relative; z-index: 8; }
.nb-hero-page {
  position: absolute;
  inset: 0;
  overflow: hidden;
  contain: paint;
  isolation: isolate;
  transform-origin: left center;
  transform-style: preserve-3d;
  transform: translateZ(0);
  backface-visibility: hidden;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--navy-shell) 48%, transparent), transparent 30%),
    linear-gradient(135deg,
      color-mix(in srgb, var(--navy-shell) 40%, transparent),
      color-mix(in srgb, var(--navy-deep) 42%, transparent) 48%,
      color-mix(in srgb, var(--navy-abyss) 38%, transparent));
  border: 1px solid var(--hair);
  box-shadow:
    inset 0 0 0 1px var(--hair),
    inset 0 1px 0 color-mix(in srgb, #F8FAFC 24%, transparent),
    inset 0 0 0 1px color-mix(in srgb, #F8FAFC 10%, transparent),
    inset 0 46px 88px color-mix(in srgb, var(--navy-abyss) 34%, transparent),
    inset 0 -52px 96px color-mix(in srgb, var(--navy-abyss) 30%, transparent);
  backdrop-filter: blur(10px) saturate(.7) brightness(.92);
  -webkit-backdrop-filter: blur(10px) saturate(.7) brightness(.92);
}
/* Idle ice: layered navy glass + visible crystalline sheen. Blur stays 10px
   and static. See-but-not-read still comes from this live sheet — not a clone. */
.nb-hero-page::before,
.nb-hero-page::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 1;
}
.nb-hero-page::before {
  background:
    linear-gradient(180deg, color-mix(in srgb, #F8FAFC 12%, transparent), transparent 16%),
    linear-gradient(118deg,
      color-mix(in srgb, var(--navy-shell) 30%, transparent),
      transparent 34%,
      color-mix(in srgb, var(--navy-abyss) 24%, transparent));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, #F8FAFC 32%, transparent),
    inset 0 14px 28px color-mix(in srgb, #F8FAFC 5%, transparent);
}
.nb-hero-page::after {
  background:
    radial-gradient(120% 84% at 50% 32%, transparent 42%, color-mix(in srgb, var(--navy-abyss) 42%, transparent) 100%),
    radial-gradient(56% 40% at 16% 6%, color-mix(in srgb, #F8FAFC 7%, transparent), transparent 52%);
  box-shadow: inset 0 0 0 1px color-mix(in srgb, #F8FAFC 14%, transparent);
}
.nb-cover-frost,
.nb-cover-sheen,
.nb-cover-bind {
  position: absolute;
  inset: 0;
  pointer-events: none;
  transform: none;
}
.nb-cover-frost {
  z-index: 1;
  background:
    linear-gradient(180deg, color-mix(in srgb, var(--navy-shell) 40%, transparent), transparent 38%),
    linear-gradient(135deg,
      color-mix(in srgb, var(--navy-abyss) 34%, transparent),
      color-mix(in srgb, var(--navy-shell) 22%, transparent) 50%,
      color-mix(in srgb, var(--navy-deep) 24%, transparent));
  opacity: 1;
}
.nb-cover-frost::before,
.nb-cover-frost::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}
.nb-cover-frost::before {
  background:
    repeating-linear-gradient(116deg, transparent 0 9px, color-mix(in srgb, #F8FAFC 14%, transparent) 9px 10px),
    repeating-linear-gradient(64deg, transparent 0 15px, color-mix(in srgb, var(--navy-shell) 20%, transparent) 15px 16px);
  opacity: .88;
}
.nb-cover-frost::after {
  background:
    repeating-linear-gradient(28deg, transparent 0 20px, color-mix(in srgb, #F8FAFC 9%, transparent) 20px 21px),
    radial-gradient(80% 58% at 74% 14%, color-mix(in srgb, #F8FAFC 6%, transparent), transparent 44%);
  opacity: .7;
}
.nb-cover-sheen {
  z-index: 2;
  background-image: url("./assets/cover-frost.svg");
  background-size: cover;
  background-position: center;
  opacity: .52;
  animation: nb-cover-sheen-drift 22s ease-in-out infinite;
}
.nb-cover-bind {
  z-index: 3;
  left: 0; right: auto; width: 15px;
  background: linear-gradient(90deg, var(--navy-abyss), transparent);
  border-right: 1px solid var(--hair);
}
.nb-cover-bind::after {
  content: "";
  position: absolute;
  left: 13px; top: 8%; bottom: 8%;
  width: 1px;
  background: var(--cyan);
  opacity: .38;
  box-shadow: 0 0 8px var(--cyan-glow);
}
.nb-cover-inscription {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 15%;
  z-index: 3;
  margin: 0;
  padding: 0 28px;
  pointer-events: none;
  user-select: none;
  text-align: center;
  font-family: "Iowan Old Style", Palatino, "Palatino Linotype", Georgia, serif;
  font-size: 13px;
  font-weight: 400;
  font-style: italic;
  letter-spacing: 0.26em;
  line-height: 1.3;
  color: color-mix(in srgb, #F8FAFC 62%, var(--navy-shell));
  text-shadow:
    0 1px 0 color-mix(in srgb, #F8FAFC 30%, transparent),
    0 -1px 0 color-mix(in srgb, var(--navy-abyss) 62%, transparent);
}
.nb-cover-inscription::after {
  content: "";
  display: block;
  width: 22px;
  height: 1px;
  margin: 9px auto 0;
  background: color-mix(in srgb, var(--cyan) 28%, transparent);
}
@keyframes nb-cover-arrive {
  0% { transform: rotateY(-86deg); opacity: .42; }
  100% { transform: rotateY(0); opacity: 1; }
}
@keyframes nb-cover-leave {
  0% { transform: rotateY(0); opacity: 1; }
  100% { transform: rotateY(-86deg); opacity: .22; }
}
@keyframes nb-frost-settle {
  0% { opacity: .46; }
  100% { opacity: 1; }
}
@keyframes nb-sheen-settle {
  0% { opacity: .16; }
  100% { opacity: .52; }
}
@keyframes nb-cover-sheen-drift {
  0%, 100% { opacity: .48; transform: translate3d(0, 0, 0); }
  50% { opacity: .58; transform: translate3d(0.55%, -0.2%, 0); }
}
@keyframes nb-page-unturn {
  0% { transform: rotateY(-86deg); opacity: .42; }
  100% { transform: rotateY(0); opacity: 1; }
}
@keyframes nb-page-turn {
  0% { transform: rotateY(0); opacity: 1; }
  100% { transform: rotateY(-86deg); opacity: .22; }
}
#nb-hero-glass.nb-hero-glass--unturn .nb-hero-page,
#nb-hero-glass.nb-hero-glass--turn .nb-hero-page {
  will-change: transform, opacity;
}
#nb-hero-glass.nb-hero-glass--unturn .nb-hero-page {
  animation: nb-cover-arrive 700ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
#nb-hero-glass.nb-hero-glass--turn .nb-hero-page {
  animation: nb-cover-leave 620ms cubic-bezier(0.4, 0, 0.2, 1) both;
}
/* During the turn: fluid glass only. Do not animate frost/sheen or backdrop-filter
   (that hitch is why settle was later paused). Ice crystallizes after land. */
#nb-hero-glass.nb-hero-glass--unturn .nb-cover-frost,
#nb-hero-glass.nb-hero-glass--turn .nb-cover-frost {
  animation: none;
  opacity: .46;
}
#nb-hero-glass.nb-hero-glass--unturn .nb-cover-sheen,
#nb-hero-glass.nb-hero-glass--turn .nb-cover-sheen {
  animation: none;
  opacity: .16;
}
#nb-hero-glass:not([hidden]):not(.nb-hero-glass--unturn):not(.nb-hero-glass--turn) .nb-cover-frost {
  animation: nb-frost-settle 820ms cubic-bezier(0.22, 1, 0.36, 1) both;
}
#nb-hero-glass:not([hidden]):not(.nb-hero-glass--unturn):not(.nb-hero-glass--turn) .nb-cover-sheen {
  animation: nb-sheen-settle 900ms cubic-bezier(0.22, 1, 0.36, 1) both, nb-cover-sheen-drift 22s ease-in-out 900ms infinite;
}
#nb-hero.nb-hero--ink-hold { transform: none; }
@keyframes nb-hero-ink-turn {
  0%, 100% { transform: none; opacity: 1; }
}
@keyframes nb-hero-ink-arrive {
  0%, 100% { transform: none; opacity: 1; }
}
#nb-main.nb-main--under-cover { pointer-events: auto; }
@media (prefers-reduced-motion: reduce) {
  /* Kill frost/blur/shimmer. Cover still exists as a navy sheet; Close/Open
     stay on #nb-cover-toggle. Default (no RM) path keeps page-turn + frost.
     Inscription stays as quiet engraved text. */
  .nb-hero-page {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    background: color-mix(in srgb, var(--navy-shell) 86%, var(--text));
    box-shadow: inset 0 0 0 1px var(--hair);
    animation: none !important;
    transform: none !important;
  }
  .nb-hero-page::before,
  .nb-hero-page::after { display: none !important; }
  .nb-cover-frost,
  .nb-cover-sheen { display: none !important; }
  .nb-cover-inscription {
    color: color-mix(in srgb, #F8FAFC 72%, var(--navy-shell));
    text-shadow: none;
    letter-spacing: 0.18em;
  }
  #nb-hero-glass.nb-hero-glass--turn .nb-hero-page,
  #nb-hero-glass.nb-hero-glass--unturn .nb-hero-page,
  #nb-hero-glass:not([hidden]) .nb-hero-page,
  #nb-hero-glass:not([hidden]):not(.nb-hero-glass--unturn):not(.nb-hero-glass--turn) .nb-cover-frost,
  #nb-hero-glass:not([hidden]):not(.nb-hero-glass--unturn):not(.nb-hero-glass--turn) .nb-cover-sheen {
    animation: none !important;
  }
}
body.eink .nb-cover-frost,
body.eink .nb-cover-sheen,
body.nb2-eink .nb-cover-frost,
body.nb2-eink .nb-cover-sheen { display: none !important; }
body.eink .nb-hero-page,
body.nb2-eink .nb-hero-page {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  background: color-mix(in srgb, var(--navy-shell) 86%, var(--text));
  box-shadow: inset 0 0 0 1px var(--hair);
  animation: none !important;
  transform: none !important;
}
body.eink .nb-hero-page::before,
body.eink .nb-hero-page::after,
body.nb2-eink .nb-hero-page::before,
body.nb2-eink .nb-hero-page::after { display: none !important; }
body.eink .nb-cover-inscription,
body.nb2-eink .nb-cover-inscription {
  color: #111;
  text-shadow: none;
  letter-spacing: 0.16em;
}
body.eink .nb-cover-inscription::after,
body.nb2-eink .nb-cover-inscription::after { background: #111; opacity: .45; }
body.eink #nb-hero-glass.nb-hero-glass--turn .nb-hero-page,
body.eink #nb-hero-glass.nb-hero-glass--unturn .nb-hero-page,
body.nb2-eink #nb-hero-glass.nb-hero-glass--turn .nb-hero-page,
body.nb2-eink #nb-hero-glass.nb-hero-glass--unturn .nb-hero-page {
  animation: none !important;
}

/* Cycle 7: rail + notes-head + capture + IoHub/History — 44px floor.
   Exception: #nb-local is a status chip, not a control (no click). Connect is
   Nav OUT for behavior but still sized so Tab does not land on a 28px target. */
.nb-rail .nb-btn,
.nb-rail .nb-seg,
.nb-rail .nb-chip--surface,
.nb-rail .nb-chip--connect,
.nb-rail #nb-cover-toggle,
.nb-rail .nb-home,
.nb-rail .nb2-view-toggle,
.nb-rail .nb-search,
.nb-rail .nb-search input,
.nb-notes-head .nb-cap,
.nb-notes-head .nb-cap-more,
.nb-notes-head .nb2-pager-nav,
.nb-notes-head .nb2-pager-add,
.nb-notes-head .nb-source,
.nb-rail .nb-source,
.nb-kicker-text .nb-source,
#nb2-secondary,
.nb-capture-bar .nb-cap,
.nb-capture-bar .nb-cap-more,
.nb2-iohub-file-btn,
#nb2-iohub-paste-btn,
#nb2-iohub-yt-btn,
#nb2-iohub-course-btn,
.nb2-history-acts .nb-btn {
  min-height: 44px;
  box-sizing: border-box;
}
.nb-rail .nb-btn,
.nb-rail .nb-seg,
.nb-rail .nb-home,
.nb-notes-head .nb2-pager-nav,
.nb-notes-head .nb-cap-more,
.nb2-more-btn {
  min-width: 44px;
}
.nb2-iohub-lead { margin: 0 16px 10px; }
.nb2-iohub-needs-net {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px dashed var(--hair-strong, #2a3f6b);
}
.nb2-history-empty.nb-empty-glass { margin-top: 8px; }
.nb2-iohub { max-width: min(920px, 96vw); }

/* Cycle 8: Cues desk door + library density. Cornell cues are a primary zone;
   the door is always on the desk (not buried in View). Library rows are 44px
   and mark the current page with stripe + “This page” + underline. */
#nb-cues-door {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
  padding: 0 14px;
  border: 1px solid var(--hair-strong, #2a3f6b);
  border-radius: 8px;
  background: transparent;
  color: var(--text, #F8FAFC);
  font: inherit;
  font-size: 13px;
  font-weight: 650;
  cursor: pointer;
  white-space: nowrap;
}
#nb-cues-door[aria-pressed="true"] {
  border-color: var(--text, #F8FAFC);
  box-shadow: inset 3px 0 0 var(--text, #F8FAFC);
  text-decoration: underline;
  text-underline-offset: 3px;
}
#nb-cues-door:focus-visible { outline: 2px solid var(--cyan, #54efff); outline-offset: 2px; }
.nb2-library-folder { min-height: 44px; }
.nb2-library-folder-act { min-width: 44px; min-height: 44px; }
.nb-rail .nb-source,
.nb-kicker-text .nb-source,
#nb2-secondary {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  box-sizing: border-box;
}

/* Cycle 9: Coach / LearnLoop 44px + Schedule chrome. Optional strips recede
   on Capture; More restores them. Schedule is local-only, empty-honest. */
#nb-coach-do,
#nb-coach-known,
#nb-coach-snooze,
#nb-coach-off,
#nb-loop-dismiss,
#nb-loop-plan-met,
#nb-loop-chain-toggle,
#nb-loop-demand-action {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}
#nb-coach-off {
  display: inline-grid;
  place-items: center;
  padding: 8px 12px;
  border: 0;
  background: transparent;
  color: var(--muted, #8b93a7);
  cursor: pointer;
  font: inherit;
}
#nb-coach-off:focus-visible,
#nb-loop-dismiss:focus-visible,
#nb-loop-demand-dismiss:focus-visible {
  outline: 2px solid var(--cyan, #54efff);
  outline-offset: 2px;
}
#nb-loop[data-empty="true"] {
  border: 1px dashed var(--hair-strong, #2a3f6b);
  background: transparent;
}
.nb-plan-close,
.nb-plan-tab,
.nb-plan-submit,
.nb-plan-action,
.nb-plan-drag-handle,
.nb-plan-window-menu-trigger {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}
.nb-plan-close { width: 44px; height: 44px; }
.nb-plan-help { font-size: 13px; line-height: 1.45; }
.nb-plan-empty.nb-empty-glass {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin: 0 0 10px;
  padding: 12px 14px;
  border: 1px dashed var(--hair-strong, #2a3f6b);
  border-radius: 8px;
  background: transparent;
  font-size: 13px;
  line-height: 1.45;
}
.nb-plan-empty .nb-empty-lead { color: var(--text, #F8FAFC); font-weight: 650; }
.nb-plan-empty .nb-empty-why { color: var(--muted, #8b93a7); }

/* Cycle 10: pager IS the page list; cue walk 44px; Replay empty honesty. */
.nb2-library--pager-owns-list .nb2-library-head,
.nb2-library--pager-owns-list .nb2-library-list {
  display: none !important;
}
body[data-mode="capture"] #nb2-library { display: none !important; }
body[data-mode="capture"] .nb-grid {
  grid-template-columns: minmax(210px, 27%) 1fr;
  grid-template-areas: "cues notes" "summary summary";
}
.nb2-pagejump-input { min-height: 44px; box-sizing: border-box; }
.nb2-pagejump-row {
  min-height: 44px;
  box-sizing: border-box;
}
.nb2-pagejump-row.is-active {
  box-shadow: inset 3px 0 0 var(--text, #F8FAFC);
  background: rgba(159, 179, 200, .10);
}
.nb2-pagejump-row.is-active .nb2-pagejump-title {
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  color: var(--text, #F8FAFC);
}
.nb2-pagejump-here {
  font-size: 11px;
  letter-spacing: .04em;
  text-transform: none;
  color: var(--text, #F8FAFC);
  font-weight: 650;
}
.nb-cue-filter,
.nb-cue-act,
.nb-cue-add input,
.nb-cue-add button,
#nb-cues-empty-act,
#nb-cues-cover {
  min-height: 44px;
  box-sizing: border-box;
}
.nb-cue-filter--on {
  font-weight: 700;
  text-decoration: underline;
  text-underline-offset: 3px;
  box-shadow: inset 3px 0 0 var(--text, #F8FAFC);
}
#nb-cues-cover {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  margin: 0 0 8px;
  padding: 0 12px;
  border: 1px solid var(--hair-strong, #2a3f6b);
  border-radius: 8px;
  background: transparent;
  color: var(--text, #F8FAFC);
  font: inherit;
  font-size: 13px;
  font-weight: 650;
  cursor: pointer;
}
#nb-cues-cover[aria-pressed="true"] {
  border-color: var(--text, #F8FAFC);
  box-shadow: inset 3px 0 0 var(--text, #F8FAFC);
  text-decoration: underline;
  text-underline-offset: 3px;
}
#nb-cues-cover:focus-visible,
.nb-cue-filter:focus-visible,
.nb-cue-act:focus-visible {
  outline: 2px solid var(--cyan, #54efff);
  outline-offset: 2px;
}
.nb-cap[data-cap="replay"][data-empty="true"] {
  opacity: .78;
}
.nb-vr-empty {
  min-height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px 18px;
  text-align: center;
  line-height: 1.45;
  color: var(--text, #F8FAFC);
  border: 1px dashed var(--hair-strong, #2a3f6b);
  border-radius: 8px;
  background: transparent;
}

/* Cycle 11: Screen / Listen / Video / Transcript empty-honest; cites prompt 44px;
   Calibrate once-after-enter; source close 44px. */
.nb-cap[data-empty="true"] { opacity: .78; }
.nb-cap-honesty .nb-cap-honesty-empty {
  min-height: 88px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px 18px;
  text-align: center;
  line-height: 1.45;
  color: var(--text, #F8FAFC);
  border: 1px dashed var(--hair-strong, #2a3f6b);
  border-radius: 8px;
  background: transparent;
}
.nb-cap-honesty .nb-dialog-actions .nb-btn,
#nb-prompt-ok,
#nb-prompt-cancel,
.nb2-paste-acts .nb-btn,
.nb-cal-invite-acts .nb-btn,
#nb2-src-close,
#nb2-src-save,
#nb2-src-fs,
#nb2-pair-dialog .nb-btn {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}
.nb-cal-invite {
  margin: 8px 0 0;
}

/* Cycle 12: hero identity leftover + age/parental UDL; rail wrap at 390;
   PWA/file honesty (no store listing); print + Sync folder honesty.
   Swell stays ONLY on #nb-hero-glass .nb-hero-page. */
@media (max-width: 480px) {
  .nb-rail {
    flex-wrap: wrap;
    overflow-x: auto;
    overflow-y: visible;
    min-width: 0;
    max-width: 100%;
  }
  .nb-kicker {
    flex: 1 1 100%;
    min-width: 0;
  }
  .nb-rail-actions {
    flex: 1 1 100%;
    width: 100%;
    min-width: 0;
    flex-wrap: wrap;
    overflow: visible;
  }
  .nb-rail-actions .nb-chip,
  .nb-rail-actions .nb-btn,
  .nb-rail-actions .nb-seg,
  .nb-rail-actions .nb-search,
  .nb-rail-actions .nb-mode {
    flex: 0 1 auto;
    min-width: 44px;
    max-width: 100%;
  }
}
#nb2-eink-check .nb-btn,
#nb2-ai .nb-dialog-head .nb-btn,
.nb-export-target .nb-btn {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}
.nb2-clanker-btn.is-on {
  background: color-mix(in srgb, var(--navy-panel, #0F1D3A) 70%, transparent);
  border-color: var(--hair-strong, #2a3f6b);
  color: var(--text);
  box-shadow: inset 3px 0 0 var(--cyan, #54efff);
}

/* Cycle 13: sketch a11y hits figure[data-sketch]; remount restores sketch+photo;
   source Close + tag chips 44px. Ice cover / rail toggle unchanged. */

/* Cycle 14: 390 rail density — keep identity + find + mode + More; park
   Schedule/Focus/Sync/Import/Export/LearnFloat (already in ⋯). Wordmark extras
   recede. RM frost-kill and ice cover unchanged. */
@media (max-width: 480px) {
  .nb-wordmark .nb-by,
  .nb-wordmark .nb-tag { display: none; }
  .nb-rail-actions #nb-plan-toggle,
  .nb-rail-actions #nb2-focus-toggle,
  .nb-rail-actions #nb-sync,
  .nb-rail-actions #nb2-learnfloat-btn,
  .nb-rail-actions #nb-import,
  .nb-rail-actions #nb-export,
  .nb-rail-actions #nb2-pair-btn,
  .nb-rail-actions #nb2-pair-chip { display: none; }
}

/* Cycle 15: 390 rail height — recede parked chrome so the rail is two rows
   (kicker + one action row), not a ~327px wrap stack. Cover + More stay 44px.
   Connect stays visible (Nav OUT — do not hide). Search / surface / local /
   Galaxy / partner recede; Find + surface live in ⋯ More. */
@media (max-width: 480px) {
  .nb-kicker-text,
  .nb-kicker-divider { display: none; }
  .nb-kicker {
    max-height: 52px;
    overflow: hidden;
  }
  .nb-rail-actions {
    flex-wrap: nowrap !important;
    overflow-x: auto;
    overflow-y: hidden;
    max-height: 52px;
  }
  .nb-rail-actions > * { flex: 0 0 auto !important; max-width: none; }
  .nb-rail-actions #nb-surface-chip,
  .nb-rail-actions #nb-local,
  .nb-rail-actions .nb-search,
  .nb-rail-actions #nb2-galaxy-rail-btn,
  .nb-rail-actions #nb2-partner,
  .nb-rail-actions #nb2-ocr,
  .nb-rail-actions #nb2-handwriting,
  .nb-rail-actions #nb2-secondary { display: none !important; }
  .nb-search { flex: 0 0 auto; }
}
#nb2-more-find,
#nb2-more-surface {
  min-height: 44px !important;
  padding-top: 10px;
  padding-bottom: 10px;
  box-sizing: border-box;
}

/* Cycle 15: sketch inks / shapes — 44px labeled targets (was 20×20 / 30×28). */
.nb-draw-shapes { flex-wrap: wrap; }
.nb-draw-colors { flex-wrap: wrap; }
.nb-shape {
  min-width: 44px;
  min-height: 44px;
  width: auto;
  height: auto;
  padding: 6px 8px;
  box-sizing: border-box;
}
.nb-ink {
  min-width: 44px;
  min-height: 44px;
  width: auto;
  height: auto;
  border-radius: 8px;
  padding: 6px 8px;
  font-size: 11px;
  line-height: 1.2;
  color: var(--text, #F5F9FC);
  background: color-mix(in srgb, var(--ink, #54EFFF) 22%, transparent);
  border: 2px solid var(--ink, #54EFFF);
  box-sizing: border-box;
}
.nb-ink:hover { transform: none; }
#nb-draw-clear,
#nb-draw-cancel,
#nb-draw-save {
  min-height: 44px;
  min-width: 44px;
  box-sizing: border-box;
}

/* Opening HUD — title-bar mode/connection instrumentation (Atrium).
   Slot after #nb-cover-toggle. Who / age / parental lives in Set up, not a kicker chip.
   Do not restyle cover, doors, or frost. */
.nb-hud {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex: 0 0 auto;
  min-width: min-content;
  min-height: 44px;
  padding: 0 6px 0 10px;
  box-sizing: border-box;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: color-mix(in srgb, var(--navy-panel, #0F1D3A) 48%, transparent);
  color: var(--text);
  box-shadow: none;
}
.nb-hud-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin: 0;
  min-height: 44px;
  font: 550 12px/1.2 Montserrat, Inter, sans-serif;
  letter-spacing: .02em;
  color: var(--text);
  white-space: nowrap;
}
#nb-hud-mode { white-space: nowrap; }
.nb-hud-pip {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex: none;
  border: 1px solid var(--muted);
  background: transparent;
  box-shadow: none;
}
.nb-hud[data-mode="open-note"] .nb-hud-pip {
  border-color: var(--muted);
  background: transparent;
}
.nb-hud[data-mode="offline"] .nb-hud-pip {
  border-color: var(--muted);
  background: var(--muted);
}
.nb-hud[data-mode="can-connect"] .nb-hud-pip,
.nb-hud[data-mode="learnnet"] .nb-hud-pip {
  border-color: var(--cyan);
  background: var(--cyan);
}
.nb-hud-setup {
  min-height: 44px;
  min-width: 44px;
  padding: 8px 10px;
  box-sizing: border-box;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: transparent;
  color: var(--text);
  font: 550 12px/1.2 Montserrat, Inter, sans-serif;
  letter-spacing: .02em;
  cursor: pointer;
}
.nb-hud-setup:hover,
.nb-hud-setup:focus-visible {
  border-color: var(--hair-strong);
  background: color-mix(in srgb, var(--navy-crest, #1E3358) 42%, transparent);
}
.nb-hud-setup:focus-visible {
  outline: 2px solid var(--cyan);
  outline-offset: 2px;
}
.nb-hud-version {
  color: var(--muted);
  font: 400 11px/1.2 "JetBrains Mono", ui-monospace, monospace;
  white-space: nowrap;
}
body.nb-hero-open .nb-hud { display: inline-flex; }
@media (prefers-reduced-motion: reduce) {
  .nb-hud,
  .nb-hud-pip,
  .nb-hud-setup { animation: none !important; transition: none; }
}
body.eink .nb-hud,
body.nb2-eink .nb-hud {
  background: #fff;
  color: #000;
  border-color: #000;
  box-shadow: none;
}
body.eink .nb-hud-pip,
body.nb2-eink .nb-hud-pip { box-shadow: none; }
body.eink .nb-hud-setup,
body.nb2-eink .nb-hud-setup {
  background: #fff;
  color: #000;
  border-color: #000;
}
@media (max-width: 480px) {
  .nb-hud-version { display: none; }
  /* Compose: one 44px kicker row. Recede labels (Close/Open) instead of
     wrapping a second fat row or clipping Set up. HUD must not shrink-wrap. */
  .nb-kicker {
    gap: 6px;
    flex-wrap: nowrap;
    max-height: 52px;
    overflow-x: auto;
    overflow-y: hidden;
  }
  .nb-home { flex: 0 0 auto; }
  .nb-home .nb-brand { display: none; }
  #nb-cover-toggle .nb-cover-toggle-glyph,
  #nb-cover-toggle[aria-pressed="true"] .nb-cover-toggle-glyph--lift {
    display: none;
  }
  .nb-kicker:has(#nb-hud) {
    max-height: 52px;
    overflow-x: auto;
    overflow-y: hidden;
  }
  #nb-cover-toggle {
    padding: 8px 8px;
    gap: 6px;
  }
  .nb-hud {
    flex: 0 0 auto;
    min-width: min-content;
    min-height: 44px;
    padding: 0 4px 0 8px;
    gap: 6px;
  }
  .nb-hud-status { gap: 6px; }
  .nb-hud-setup { padding: 8px 8px; }
}
