/* =========================================================================
   Red Stet — clean typography reader + editorial markup
   ========================================================================= */

/* ---- Type, all served locally from project ./fonts/ ----
   Licensed Klim production files:
     • Tiempos Headline — display cut for headings (ball terminals, drama)
     • Tiempos Text     — back-pocket body serif (loaded, not the default)
     • Söhne            — body prose + chrome (Klim Swiss-neutral grotesque)
     • Caveat           — red proofreader's handwriting on marks + notes
   (Befonts trial cuts have been replaced with the licensed production
   files purchased from Klim.) */

/* Söhne — body prose + chrome. Six cuts: Buch/Kraftig/Halbfett upright +
   italic ("Kursiv" in Klim's naming). */
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-Buch.otf') format('opentype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-BuchKursiv.otf') format('opentype');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-Kraftig.otf') format('opentype');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-KraftigKursiv.otf') format('opentype');
  font-weight: 500; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-Halbfett.otf') format('opentype');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Söhne';
  src: url('fonts/sohne/Sohne-HalbfettKursiv.otf') format('opentype');
  font-weight: 600; font-style: italic; font-display: swap;
}

/* Tiempos Headline — DISPLAY cut. Light (300), Regular (400), Medium (500),
   Semibold (600). The licensed bundle has no italic Headline cuts; if an
   italic heading is requested the browser will synthesize one from the
   upright. */
@font-face {
  font-family: 'Tiempos Headline';
  src: url('fonts/tiempos/TiemposHeadline-Light.ttf') format('truetype');
  font-weight: 300; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Headline';
  src: url('fonts/tiempos/TiemposHeadline-Regular.otf') format('opentype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Headline';
  src: url('fonts/tiempos/TiemposHeadline-Medium.ttf') format('truetype');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Headline';
  src: url('fonts/tiempos/TiemposHeadline-Semibold.ttf') format('truetype');
  font-weight: 600; font-style: normal; font-display: swap;
}

/* Tiempos Text — back-pocket body serif. Full 8-cut family. */
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-400-Regular.otf') format('opentype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-400-Regular-Italic.otf') format('opentype');
  font-weight: 400; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-500-Medium.otf') format('opentype');
  font-weight: 500; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-500-Medium-Italic.otf') format('opentype');
  font-weight: 500; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-600-Semibold.otf') format('opentype');
  font-weight: 600; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-600-Semibold-Italic.otf') format('opentype');
  font-weight: 600; font-style: italic; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-700-Bold.otf') format('opentype');
  font-weight: 700; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Tiempos Text';
  src: url('fonts/tiempos/TiemposText-700-Bold-Italic.otf') format('opentype');
  font-weight: 700; font-style: italic; font-display: swap;
}

/* Caveat — red proofreader's handwriting on marks + margin notes */
@font-face {
  font-family: 'Caveat';
  src: url('fonts/caveat/Caveat-VariableFont_wght.ttf') format('truetype-variations');
  font-weight: 400 700; font-style: normal; font-display: swap;
}

:root {
  /* Editorial type system — manuscript-first:
     --display → Tiempos Headline  (high-contrast display, headings)
     --prose   → Tiempos Text      (BODY — the manuscript voice)
     --serif   → Tiempos Text      (alias of --prose for general serif use)
     --sans    → Söhne             (chrome only: sidebar, toolbar, palette, status)
     --hand    → Caveat            (red proofreader's handwriting on marks) */
  --display: 'Tiempos Headline', 'Tiempos Text', 'Tiempos',
             Georgia, serif;
  --prose:   'Tiempos Text', 'Tiempos', 'Charter', Georgia, 'Times New Roman', serif;
  --serif:   var(--prose);
  --sans:    'Söhne', 'Sohne',
             -apple-system, BlinkMacSystemFont, 'Helvetica Neue', Arial, sans-serif;
  --hand:    'Caveat', 'Bradley Hand', 'Marker Felt', cursive;
  --mono:    'JetBrains Mono', 'SF Mono', ui-monospace, 'Menlo', monospace;

  /* Paper palette — editorial cream, soft ink, no pure black */
  --paper:        #FAF8F2;   /* warm cream */
  --paper-edge:   #ece8df;
  --ink:          #1A1815;   /* soft black, never pure #000 */
  --ink-2:        #3e3a32;   /* secondary body text — readable, slightly softer than full ink */
  --ink-soft:     #4a463f;
  --ink-fade:     #8a857a;
  --hair:         #e3ddce;
  --hair-strong:  #c9c1ad;

  /* Editorial red (proofreader's pen — Pilot G-2 red, not stop-sign red) */
  --red:          #B83A2C;
  --red-soft:     #d96b62;
  --red-deep:     #8c1a13;
  --red-wash:     rgba(184, 58, 44, 0.08);

  --accent:       #2b4a6f;   /* deep navy for UI accents */
  --highlight:    #fff7b0;

  --shadow-1: 0 1px 0 rgba(0,0,0,0.04);
  --shadow-2: 0 10px 30px rgba(28, 26, 23, 0.10), 0 1px 0 rgba(28, 26, 23, 0.04);

  --sidebar-w: 260px;
  --reader-max: 38rem;   /* ~640px → ~65 chars/line, the classic book measure */
  --tb-h: 56px;

  --t-fast: 120ms cubic-bezier(.2,.7,.3,1);
  --t-med:  220ms cubic-bezier(.2,.7,.3,1);
}

body[data-theme="dark"] {
  /* Dark mode tuned for long-form reading. Earlier pass leaned too
     contrasty — the ink and the editorial red both sat at the maximum
     legible brightness against #15. Walking everything down a step:
     ink is warmer cream rather than near-white; the red is dialed to
     a softer terracotta that still reads as a proofreader's pen but
     doesn't burn at small sizes. */
  --paper:        #15171a;
  --paper-edge:   #0f1114;
  --ink:          #d4ccba;       /* warm cream, not white */
  --ink-2:        #b5ad9b;       /* softer secondary */
  --ink-soft:     #95907f;
  --ink-fade:     #6a6759;
  --hair:         #2a2d33;
  --hair-strong:  #3a3e46;
  --red:          #c75d54;       /* dialed back from #ef6c63 — terracotta */
  --red-soft:     #d27a72;
  --red-deep:     #e29a93;
  --red-wash:     rgba(199, 93, 84, 0.08);
  --accent:       #7ea2cf;
  --highlight:    #3d3308;
  --shadow-2: 0 10px 30px rgba(0,0,0,0.5), 0 1px 0 rgba(255,255,255,0.04);
}

* { box-sizing: border-box; }

/* Global [hidden] enforcement. Many class rules below set explicit
   `display: flex/grid/inline-flex/etc.` which would otherwise win
   against the UA default `[hidden] { display: none }`. This single
   rule means we never have to remember to add a per-class override
   when introducing a new component. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0;
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 15px;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

body {
  display: grid;
  grid-template-columns: var(--sidebar-w) 1fr;
  grid-template-rows: 100vh;
  overflow: hidden;
  transition: background var(--t-med), color var(--t-med);

  /* GLOBAL hairline scrollbar. We deliberately DO NOT set
     `scrollbar-width: thin` here — in Chrome 121+ / Safari 18+ the
     native `thin` preset OVERRIDES `::-webkit-scrollbar` width rules
     and locks the scrollbar at ~8px. By leaving scrollbar-width at
     its default (`auto`), our WebKit pseudo-element rules below take
     full effect and we get a true 2px hairline. Firefox users see
     `auto` width (default ~12px) — acceptable tradeoff; the rest of
     the planet is on WebKit/Chromium. */
  scrollbar-color: var(--hair-strong) transparent;
}
/* Hairline scrollbar in Chromium/WebKit — 2px wide, transparent track,
   faint thumb. Applied universally so canvas + sidebar + palettes all
   share the same minimal style. */
*::-webkit-scrollbar         { width: 2px; height: 2px; }
*::-webkit-scrollbar-track   { background: transparent; }
*::-webkit-scrollbar-thumb   {
  background: var(--hair-strong);
  border-radius: 2px;
}
*::-webkit-scrollbar-thumb:hover { background: var(--ink-2); }
*::-webkit-scrollbar-corner  { background: transparent; }

/* Sidebar = always-overlay. The body never shifts when it opens / closes;
   it slides over the proofreader palettes (and any other left-column UI)
   to the same x as the body text begins (388px), and disappears off-
   screen when closed. The canvas keeps its constant padding-left:388px,
   so prose position is stable in every mode. */
body { grid-template-columns: 1fr; }
.sidebar {
  position: fixed;
  top: 0; left: 0;
  bottom: 0;
  width: 340px;                  /* narrower than before — file names ellipsize */
  z-index: 50;                   /* above the palettes (z-index ~10–20) and FABs */
  transform: translateX(0);
  box-shadow: var(--shadow-2);
  transition: transform var(--t-med);
}
body.sidebar-collapsed .sidebar {
  transform: translateX(-100%);  /* fully off-screen — no hover strip */
  box-shadow: none;
}

::selection { background: var(--red-wash); color: var(--ink); }

/* =========================================================================
   Sidebar
   ========================================================================= */

.sidebar {
  background: var(--paper-edge);
  border-right: 1px solid var(--hair);
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  transition: transform var(--t-med);
  font-family: var(--sans);
}
.sidebar-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  border: 0;
  background: transparent;
  font-size: 20px;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  border-radius: 6px;
  z-index: 5;
  transition: background var(--t-fast), color var(--t-fast);
}
.sidebar-close:hover { background: var(--red-wash); color: var(--red); }
body.sidebar-collapsed .sidebar-close { display: none; }

.brand {
  padding: 22px 22px 14px;
  border-bottom: 1px solid var(--hair);
}
.brand h1 {
  margin: 0;
  font-family: var(--sans);
  font-weight: 600;
  font-size: 17px;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.brand-sub {
  margin: 4px 0 0;
  font-size: 12px;
  color: var(--ink-fade);
  font-style: italic;
  font-family: var(--serif);
}

.search {
  padding: 12px 14px;
  border-bottom: 1px solid var(--hair);
}

/* File browser: Open folder… / Open file(s)… buttons at the top of
   the sidebar so the user can load .md files from disk. */
.file-browser {
  padding: 10px 14px;
  border-bottom: 1px solid var(--hair);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.file-browser .ghost-btn {
  width: 100%;
  text-align: left;
  padding: 8px 10px;
  font-size: 12.5px;
}
.file-browser-current {
  font-size: 11.5px;
  color: var(--ink-fade);
  font-style: italic;
  margin-top: 2px;
  word-break: break-all;
}
.file-browser-current:empty { display: none; }

/* File-tree breadcrumb — the picked folder rendered as a real
   collapsible tree-root node. Click anywhere on the name to toggle
   the entire tree below; the small ⇄ to the right re-prompts for a
   different folder (the File System Access API doesn't allow
   navigating ABOVE the originally-granted root). */
.file-browser-bread {
  display: flex;
  align-items: center;
  gap: 2px;
  margin-top: 8px;
  font-size: 12.5px;
}
.file-browser-bread[hidden] { display: none; }
.folder-bread-name {
  flex: 1;
  display: flex;
  align-items: center;
  gap: 4px;
  appearance: none;
  border: 0;
  background: transparent;
  text-align: left;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--ink);
  font-weight: 500;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 5px;
  min-width: 0;
}
.folder-bread-name:hover { background: var(--red-wash); color: var(--red); }
.folder-bread-chevron {
  display: inline-block;
  width: 10px;
  font-size: 10px;
  color: var(--ink-fade);
  flex-shrink: 0;
  transition: transform var(--t-fast);
}
.folder-bread-name[aria-expanded="false"] .folder-bread-chevron {
  transform: rotate(-90deg);
}
.folder-bread-icon { flex-shrink: 0; }
.folder-bread-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.folder-switch {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-fade);
  font-size: 13px;
  padding: 4px 6px;
  border-radius: 4px;
  cursor: pointer;
  flex-shrink: 0;
}
.folder-switch:hover { background: rgba(0,0,0,0.05); color: var(--ink); }

/* Recursive file tree — folders are expandable (▸ → ▾ chevron); files
   are clickable to load. Indented by depth via inline padding-left. */
.file-tree {
  margin-top: 6px;
  max-height: 320px;
  overflow-y: auto;
  font-size: 12.5px;
}
.file-tree:empty { display: none; }
.ft-node {
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 3px 6px;
  border-radius: 5px;
  cursor: pointer;
  color: var(--ink-soft);
  user-select: none;
  min-width: 0;
}
.ft-node .ft-label {
  flex: 1;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
}
.ft-node .ft-chevron, .ft-node .ft-icon { flex-shrink: 0; }
.ft-node:hover { background: var(--red-wash); color: var(--red); }
.ft-node.is-active { background: var(--red); color: white; }
.ft-node.is-active .ft-chevron, .ft-node.is-active .ft-icon { color: white; }
.ft-chevron {
  display: inline-block;
  width: 10px;
  color: var(--ink-fade);
  font-size: 10px;
  transition: transform var(--t-fast);
}
.ft-node.is-leaf .ft-chevron { visibility: hidden; }
.ft-node[aria-expanded="true"] .ft-chevron { transform: rotate(90deg); }
.ft-icon {
  display: inline-block;
  width: 14px;
  color: var(--ink-fade);
  font-size: 12px;
}
.ft-children { padding-left: 14px; }
.ft-children[hidden] { display: none; }
.ft-empty {
  padding: 4px 6px;
  font-size: 11.5px;
  font-style: italic;
  color: var(--ink-fade);
}

/* Section header inside the doc nav distinguishing bundled docs from
   user-loaded files. */
.doc-nav .doc-section {
  font-size: 10.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-fade);
  padding: 12px 22px 4px;
}
/* Collapsible "Documentation" folder. Groups bundled reference docs
   (Quick start, About Provenance, For teachers, T&Cs, etc.) so they
   don't clutter the sidebar. Default-collapsed; expand state persists
   per browser via localStorage. */
.doc-folder {
  margin-top: 6px;
}
.doc-folder-head {
  display: flex;
  align-items: center;
  gap: 8px;
  width: 100%;
  padding: 8px 22px;
  background: transparent;
  border: 0;
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-fade);
  cursor: pointer;
  text-align: left;
}
.doc-folder-head:hover { color: var(--ink-soft); }
.doc-folder-chevron {
  display: inline-block;
  font-size: 9px;
  color: var(--ink-fade);
  transition: transform 140ms ease;
  flex: 0 0 auto;
}
.doc-folder.is-open .doc-folder-chevron { transform: rotate(90deg); }
.doc-folder-label { flex: 1; }
.doc-folder-count {
  font-size: 10px;
  font-weight: 400;
  color: var(--ink-fade);
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--paper-edge);
  flex: 0 0 auto;
}
.doc-folder-body {
  display: none;
  padding-left: 8px;
}
.doc-folder.is-open .doc-folder-body { display: block; }
.doc-folder-body .doc-link {
  /* Nested doc rows get a slightly tighter indent so the hierarchy
     reads — flush-left with the chevron above. */
  padding-left: 30px;
  font-size: 12.5px;
}
.search input {
  width: 100%;
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border-radius: 8px;
  border: 1px solid var(--hair-strong);
  background: var(--paper);
  color: var(--ink);
  outline: none;
}
.search input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px rgba(43,74,111,0.12); }

.doc-nav {
  flex: 1;
  padding: 6px 0;
  overflow-y: auto;
}
/* Doc row = clickable doc-link + × remove button. */
.doc-row {
  display: flex;
  align-items: stretch;
  border-left: 2px solid transparent;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.doc-row:hover { background: rgba(0,0,0,0.03); }
body[data-theme="dark"] .doc-row:hover { background: rgba(255,255,255,0.04); }
.doc-row.is-active {
  background: var(--red-wash);
  border-left-color: var(--red);
}
.doc-link {
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  padding: 7px 12px 7px 22px;
  font-size: 13px;
  color: var(--ink-soft);
  text-decoration: none;
  cursor: pointer;
  min-width: 0;
}
.doc-row.is-active .doc-link {
  color: var(--red);
  font-weight: 500;
}
.doc-row:hover .doc-link { color: var(--ink); }
.doc-row.is-active:hover .doc-link { color: var(--red); }
.doc-link .doc-title {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.doc-link .mark-count {
  font-size: 11px;
  color: var(--red);
  font-family: var(--mono);
  flex-shrink: 0;
}
.doc-remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--ink-fade);
  font-size: 15px;
  line-height: 1;
  padding: 0 14px 0 6px;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast), color var(--t-fast);
}
.doc-row:hover .doc-remove,
.doc-row:focus-within .doc-remove { opacity: 1; }
.doc-remove:hover { color: var(--red); }

.sidebar-foot {
  border-top: 1px solid var(--hair);
  padding: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}

/* Feature toggle row — small iOS-style switch + label inside the sidebar
   foot. Used for per-user preferences like the Bookmarks on/off toggle. */
.sidebar-feature-row {
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 2px 4px 6px;
  border-bottom: 1px solid var(--hair);
  margin-bottom: 4px;
}
.sidebar-feature-toggle {
  appearance: none;
  background: transparent;
  border: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  cursor: pointer;
  padding: 4px 2px;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-2);
}
.sidebar-feature-track {
  position: relative;
  display: inline-block;
  width: 26px;
  height: 14px;
  border-radius: 999px;
  background: var(--hair-strong);
  transition: background 160ms ease;
  flex-shrink: 0;
}
.sidebar-feature-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(0,0,0,0.2);
  transition: transform 160ms cubic-bezier(.2,.7,.3,1);
}
.sidebar-feature-toggle[aria-pressed="true"] .sidebar-feature-track { background: var(--red); }
.sidebar-feature-toggle[aria-pressed="true"] .sidebar-feature-thumb { transform: translateX(12px); }
.sidebar-feature-label {
  letter-spacing: 0.02em;
}

/* Feature: bookmarks OFF — the toggle is now purely VISUAL CHROME.
   It hides the on-canvas ribbons only. Sidebar list, palette buttons,
   and right-click entry stay so the user can still manage / drop
   bookmarks without seeing them on the page. */
body.feature-bookmarks-off #bookmark-rail {
  display: none !important;
}

/* Tab visibility — set via body.tab-<mode>-off when the user has
   hidden that tab in the Setup section of the Customizations drawer.
   Hiding affects the top-bar button only; if the user explicitly
   tries to enter the mode (URL / shortcut / programmatic setMode),
   the tab auto-shows and they enter it normally. */
body.tab-read-off  #mode-read  { display: none; }
body.tab-mark-off  #mode-mark  { display: none; }
body.tab-write-off #mode-write { display: none; }

/* Marks-hidden — toggled via the pen FAB. Hides every element in the
   proofreader marks layer in any mode. Each mode remembers its own
   marks-visible / marks-hidden state via prefs. */
body.marks-hidden #margin-notes,
body.marks-hidden #note-arrows,
body.marks-hidden #bookmark-rail,
body.marks-hidden #pen-strokes,
body.marks-hidden #filter-bar {
  display: none !important;
}
body.marks-hidden .prose [data-mark-id] {
  /* Hide inline marks (ins/del/circled labels) by making them inherit
     plain text styling. CSS earlier already strips border/padding in
     non-mark mode — this extends that to all modes when marks-hidden. */
  color: inherit !important;
  background: transparent !important;
  text-decoration: none !important;
  border-color: transparent !important;
  border-width: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
}
body.marks-hidden .prose [data-mark-id]::before,
body.marks-hidden .prose [data-mark-id]::after {
  content: none !important;
}
body.marks-hidden .prose .rm-ins,
body.marks-hidden .prose .rm-punct,
body.marks-hidden .prose .rm-label,
body.marks-hidden .prose .rm-anchor,
body.marks-hidden .prose .rm-mic-anchor,
body.marks-hidden .prose .rm-indent-mark,
body.marks-hidden .prose .rm-hyphen,
body.marks-hidden .prose .rm-endash,
body.marks-hidden .prose .rm-emdash,
body.marks-hidden .prose .gutter-add-note {
  display: none !important;
}
/* Sidebar export toggle — full-width pill button with the ⤓ glyph
   tucked to the left. Menu opens UPWARD from this button so it
   doesn't collide with the bottom edge of the sidebar. */
.sidebar-export-menu { width: 100%; }
.sidebar-export-toggle {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-start;
}
.sidebar-export-toggle .se-glyph {
  color: var(--red);
  font-size: 14px;
  flex: 0 0 auto;
}
.sidebar-export-menu .export-menu-list {
  /* Open upward so the menu doesn't run off the bottom of the
     viewport. Right-anchor matches the toolbar version. */
  top: auto;
  bottom: calc(100% + 6px);
  right: auto;
  left: 0;
  min-width: calc(100% - 0px);
}

/* =========================================================================
   Write tab (Step 15) — palette + meter + Provenance indicator
   ========================================================================= */
/* Write palette uses the same .mark-palette base styles. Visible only
   in write mode (Panels A and B are hidden). Pinned to the leftmost
   rail position — same column the Punctuation palette (Panel B) lives
   in. Panel A is editorial (right column); we want Panel C in the
   leftmost column since it's the only palette visible in write mode
   and the prose stays anchored at 388px regardless. */
#write-palette { left: 24px; }
#write-palette.is-expanded { left: 24px; }
body[data-mode="write"]:not(.palette-c-expanded) .write-palette { display: flex; }
body[data-mode="write"].palette-c-expanded #mark-palette-b,
body[data-mode="write"].palette-c-expanded #mark-palette {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
}
/* Write mode: same prose typography as read mode (no 2× line-height). */
body[data-mode="write"] .prose {
  line-height: 1.6;
  outline: none;
}
/* In write mode, the marks layer disappears entirely — the writer is
   composing, not reviewing. The render code defensively also re-loads
   the doc when exiting Write so Read/Mark always see the canonical
   rendered body, not the Write-mode contenteditable HTML. */
body[data-mode="write"] #margin-notes,
body[data-mode="write"] #note-arrows,
body[data-mode="write"] #bookmark-rail,
body[data-mode="write"] #pen-strokes,
body[data-mode="write"] #filter-bar {
  display: none;
}
/* Visible focus ring on the editable prose so the user knows they're
   in "writing" mode without it screaming. */
body[data-mode="write"] .prose:focus {
  background: linear-gradient(180deg, var(--paper) 0%, var(--paper) 100%);
}

/* Bottom-right meter — word count, saved status, active time. */
.write-meter {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-fade);
  letter-spacing: 0.02em;
}
.write-meter[hidden] { display: none; }

/* Provenance indicator — inline pill in the status bar at the far
   right, next to TTS state. Sits in the natural document flow
   alongside other status items rather than floating over the canvas.
   Visible only while recording per Step 16/17 spec. */
.provenance-indicator {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 2px 8px;
  background: var(--paper);
  border: 1px solid var(--red);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--red);
  margin: 0 4px;
}
.provenance-indicator[hidden] { display: none; }
.provenance-dot {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--red);
  animation: provenance-pulse 1.4s ease-in-out infinite;
  flex-shrink: 0;
}
@keyframes provenance-pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(184, 56, 41, 0.5); }
  50%      { box-shadow: 0 0 0 5px rgba(184, 56, 41, 0); }
}

/* =========================================================================
   TTS — moving-word highlight + paused anchor marker
   ========================================================================= */
.tts-word-highlight {
  position: absolute;
  pointer-events: none;
  background: rgba(255, 215, 90, 0.45);
  border-radius: 3px;
  z-index: 3;
  transition: left 80ms ease, top 80ms ease, width 80ms ease, height 80ms ease;
}
body[data-theme="dark"] .tts-word-highlight {
  background: rgba(255, 215, 90, 0.22);
}
.tts-anchor-marker {
  position: absolute;
  pointer-events: none;
  color: var(--red);
  font-size: 14px;
  line-height: 1;
  z-index: 5;
  /* Small drop-shadow so the caret reads cleanly over any backdrop. */
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.15));
  /* Subtle pulse so the anchor "pings" the user. */
  animation: tts-anchor-ping 1.6s ease-in-out infinite;
}
@keyframes tts-anchor-ping {
  0%, 100% { transform: translateY(0); opacity: 0.95; }
  50%      { transform: translateY(-2px); opacity: 0.7; }
}

/* =========================================================================
   Pencil layer — Apple Pencil freehand strokes (Step 14)
   ========================================================================= */
.pen-strokes {
  position: absolute;
  top: 0;
  left: 0;
  pointer-events: none;     /* strokes don't intercept clicks on prose */
  z-index: 6;               /* above margin-notes leader arrows, below palette */
}
.pen-stroke {
  fill: none;
  /* Stroke color set inline so brand red can be themed via CSS var. */
  opacity: 0.92;
  /* Subtle drop-shadow gives the pen ink a slight lift off the page. */
  filter: drop-shadow(0 0.5px 0.5px rgba(184, 56, 41, 0.18));
}
.pen-stroke-active {
  /* Live-draw stroke — slightly brighter while wet. */
  opacity: 1;
}
/* In read mode, pen strokes fade — same convention as other marks. */
body:not([data-mode="mark"]) .pen-stroke { opacity: 0.45; }

/* =========================================================================
   Student assignment surfaces
   ========================================================================= */
/* Subtle assignment metadata header at the top of the canvas.
   "Mr. Wallace · English IV · Two Forces — Chapter 1" style. Same
   visual weight as the edit count widget; intentionally low-key.
   Sits inline at the top of the canvas content (not sticky) — keeps
   the prose layout predictable. */
.assignment-header {
  padding: 16px 24px 10px 388px;     /* match prose left-align */
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--ink-fade);
  letter-spacing: 0.02em;
  /* No background, no border — blends with the canvas so it doesn't
     compete with the doc title below. */
}
.assignment-header[hidden] { display: none; }
.assignment-sep {
  color: var(--hair-strong);
  margin: 0 4px;
}

/* Sidebar Assignments section — student role only. */
.assignments-sidebar {
  border-top: 1px solid var(--hair);
  padding: 10px 12px;
  font-family: var(--sans);
}
.assignments-sidebar[hidden] { display: none; }
.assignments-head {
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-bottom: 6px;
}
.assignments-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.assignments-item {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px;
  padding: 6px 8px;
  border-radius: 6px;
  color: var(--ink);
  text-decoration: none;
  background: var(--paper);
  border: 1px solid var(--hair);
  transition: border-color 120ms ease;
}
.assignments-item:hover { border-color: var(--ink-fade); }
.assignments-item-title {
  font-size: 12.5px;
  font-weight: 500;
}
.assignments-item-meta {
  grid-column: 1 / 2;
  font-size: 11px;
  color: var(--ink-fade);
}
.assignments-item-status {
  grid-row: 1 / 3;
  grid-column: 2;
  align-self: center;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  white-space: nowrap;
}
.assignments-item-status.status-not-started { background: var(--paper-edge); color: var(--ink-fade); }
.assignments-item-status.status-in-progress { background: rgba(201, 138, 26, 0.12); color: #c98a1a; }
.assignments-item-status.status-submitted   { background: rgba(74, 138, 74, 0.12); color: #4a8a4a; }

/* =========================================================================
   Bookmarks — rail dots in the canvas + sidebar list section
   ========================================================================= */
.bookmark-rail {
  position: absolute;
  top: 0;
  /* Just inside the canvas left padding-line, above the prose column.
     The hit-zone is wider than the visible ribbon column (36px) so the
     hover affordance is easy to find with the mouse, but visible
     ribbons still occupy only the leftmost 14px. */
  left: 352px;
  width: 36px;
  bottom: 0;
  z-index: 4;
}
/* Bookmark ribbon — universal pennant shape (rectangle with V-notch
   bottom) standing in for the old generic dot. Lives in the rail at
   the y-coordinate of the bookmarked block. */
.bookmark-rail-ribbon,
.bookmark-rail-preview {
  position: absolute;
  left: 0;
  width: 14px;
  height: 18px;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: var(--red);
  transition: transform 120ms ease, filter 120ms ease, opacity 120ms ease;
  margin-top: 6px;      /* nudge so the ribbon sits over the first line */
}
/* Hover-to-drop preview ribbon — ghosted outline, full-color on hover. */
.bookmark-rail-preview {
  opacity: 0.3;
}
.bookmark-rail-preview:hover {
  opacity: 0.9;
  transform: translateY(2px) scale(1.1);
}
.bookmark-rail-ribbon svg {
  width: 14px;
  height: 18px;
  display: block;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.15));
}
.bookmark-rail-ribbon:hover {
  transform: translateY(2px) scale(1.15);
}
.bookmark-rail-ribbon.is-flash {
  animation: rm-bookmark-pulse 0.8s ease;
}
@keyframes rm-bookmark-pulse {
  0%   { box-shadow: 0 0 0 0   rgba(184, 56, 41, 0.6); transform: scale(1); }
  50%  { box-shadow: 0 0 0 8px rgba(184, 56, 41, 0);   transform: scale(1.6); }
  100% { box-shadow: 0 0 0 0   rgba(184, 56, 41, 0);   transform: scale(1); }
}

/* Block flash on bookmark drop / jump — a soft yellow wash so the
   user sees what just happened without permanent staining. */
.block.bookmark-flash {
  animation: rm-bookmark-flash 1.6s ease;
}
@keyframes rm-bookmark-flash {
  0%, 100% { background: transparent; }
  20%, 60% { background: rgba(255, 219, 88, 0.18); }
}

/* Sidebar bookmark section — quiet under the doc list. Less divider
   weight, no shouty uppercase header, just enough hierarchy to read
   as its own group without screaming. */
.bookmark-sidebar-section {
  padding: 6px 12px 8px;
  font-family: var(--sans);
}
.bookmark-sidebar-section[hidden] { display: none; }
.bookmark-sidebar-head {
  display: flex;
  align-items: center;
  gap: 8px;
  margin-bottom: 4px;
  font-size: 11.5px;
  color: var(--ink-fade);
  letter-spacing: 0;
  text-transform: none;
}
.bookmark-sidebar-title {
  flex: 1;
  min-width: 0;
}
.bookmark-sidebar-count {
  font-family: var(--mono);
  color: var(--ink-fade);
  font-size: 10.5px;
  margin-left: 2px;
}
/* Toggle inside the bookmark header — small, no label (the section
   header provides the label). Visually identical to the iOS-style
   switch but compact. */
.bookmark-sidebar-toggle { padding: 2px; }
.bookmark-sidebar-toggle .sidebar-feature-track {
  width: 22px;
  height: 12px;
}
.bookmark-sidebar-toggle .sidebar-feature-thumb {
  width: 8px;
  height: 8px;
}
.bookmark-sidebar-toggle[aria-pressed="true"] .sidebar-feature-thumb {
  transform: translateX(10px);
}
.bookmark-sidebar-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.bookmark-sidebar-item {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  border-radius: 5px;
  padding: 2px 4px;
}
.bookmark-sidebar-item:hover { background: var(--paper-edge); }
.bookmark-jump {
  appearance: none;
  background: transparent;
  border: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  cursor: pointer;
  padding: 4px 2px;
  text-align: left;
  color: var(--ink);
  font-family: inherit;
  font-size: 12.5px;
  min-width: 0;
  width: 100%;
}
/* Sidebar list ribbon — same SVG glyph as the rail, scaled smaller. */
.bookmark-jump .bookmark-glyph {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--red);
}
.bookmark-jump .bookmark-glyph svg {
  width: 10px;
  height: 14px;
  display: block;
}
/* Inline-edit text input that replaces the bookmark name when ✎ clicked. */
.bookmark-name-input {
  appearance: none;
  width: 100%;
  padding: 2px 4px;
  border: 1px solid var(--red);
  border-radius: 4px;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--ink);
  background: var(--paper);
}
.bookmark-name-input:focus {
  outline: none;
  box-shadow: 0 0 0 2px rgba(184, 56, 41, 0.18);
}
.bookmark-sidebar-item.is-editing .bookmark-jump { cursor: default; }
.bookmark-sidebar-item.is-editing .bookmark-actions { opacity: 0; pointer-events: none; }
.bookmark-jump .bookmark-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.bookmark-actions {
  display: flex;
  gap: 2px;
  opacity: 0;
  transition: opacity 120ms ease;
}
.bookmark-sidebar-item:hover .bookmark-actions { opacity: 1; }
.bookmark-action {
  appearance: none;
  background: transparent;
  border: 0;
  width: 22px;
  height: 22px;
  border-radius: 4px;
  cursor: pointer;
  color: var(--ink-fade);
  font-size: 12px;
}
.bookmark-action:hover { color: var(--red); background: rgba(0,0,0,0.04); }

/* =========================================================================
   Gutter filter bar — top-of-canvas strip, mark-mode only
   ========================================================================= */
.filter-bar {
  display: flex;
  align-items: flex-start;     /* label stays top-aligned when chips wrap */
  gap: 18px;
  padding: 8px 24px;
  border-bottom: 1px solid var(--hair);
  background: var(--paper);
  font-family: var(--sans);
  font-size: 12px;
  /* Left edge aligns with the prose left edge (388px palette + canvas
     padding) so chips line up under the body-text column. */
  padding-left: 388px;
  flex-wrap: wrap;
}
.filter-bar[hidden] { display: none; }
.filter-cluster {
  display: flex;
  align-items: flex-start;
  gap: 8px;
}
/* Constrain the types cluster to the body-text width so chips wrap to
   a second / third row instead of running off into the right margin.
   Matches the prose column (--reader-max). */
.filter-types-cluster {
  flex: 0 1 var(--reader-max);
  max-width: var(--reader-max);
  min-width: 0;
}
.filter-cluster-label {
  /* Stay top-aligned with the first row of chips when they wrap. */
  padding-top: 4px;
  flex: 0 0 auto;
}
.filter-cluster-label {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.filter-authors, .filter-types {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
/* Author orb-with-name chip. Off by default — thin outline; on = filled. */
.filter-orb {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px 3px 5px;
  background: transparent;
  border: 1px solid var(--hair-strong);
  border-radius: 999px;
  font-family: inherit;
  font-size: 11.5px;
  color: var(--ink-2);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.filter-orb:hover { border-color: var(--ink-2); color: var(--ink); }
.filter-orb.is-on {
  background: var(--paper-edge);
  border-color: var(--ink);
  color: var(--ink);
}
.filter-orb-dot {
  width: 9px; height: 9px;
  border-radius: 50%;
  display: inline-block;
  background: #6b6b6b;
}
/* Count badge on author chips — same monospace muted style as the
   type-chip count, so the row reads consistently. */
.filter-orb-count {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-fade);
  font-weight: 400;
  margin-left: 2px;
}
/* Type chip. Two-line layout: glyph + count badge. */
.filter-chip {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 8px;
  background: transparent;
  border: 1px solid var(--hair-strong);
  border-radius: 5px;
  font-family: var(--hand);
  font-size: 14px;
  color: var(--red);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease;
}
.filter-chip:hover { border-color: var(--red); }
.filter-chip.is-on {
  background: var(--red-wash);
  border-color: var(--red);
}
.filter-chip-count {
  font-family: var(--mono);
  font-size: 10px;
  color: var(--ink-fade);
  font-weight: 400;
}
.filter-clear {
  margin-left: auto;
  appearance: none;
  background: transparent;
  border: 0;
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--red);
  cursor: pointer;
  padding: 4px 6px;
}
.filter-clear:hover { text-decoration: underline; }
.filter-clear[hidden] { display: none; }

/* Filtered-OUT visual: marks and notes fade to ~15% opacity so the
   editor can still see they exist (ghosts) without losing focus. */
[data-mark-id].is-filtered-out,
.margin-note.is-filtered-out {
  opacity: 0.15;
  transition: opacity 200ms ease;
}
[data-mark-id].is-filtered-out:hover,
.margin-note.is-filtered-out:hover {
  opacity: 0.6;
}

/* =========================================================================
   Reader
   ========================================================================= */

.reader {
  display: grid;
  grid-template-rows: var(--tb-h) 1fr auto;
  grid-template-columns: 1fr;  /* explicit so the canvas spans the full row */
  height: 100vh;
  min-width: 0;
  width: 100%;
  position: relative;
}

.toolbar {
  /* The .reader grid already places the toolbar in its own non-scrolling
     row (height: 100vh; grid-template-rows: var(--tb-h) 1fr auto). This
     keeps it visible regardless of canvas scroll. Adding an explicit
     min-height + z-index here as belt-and-suspenders so no later
     layout change can compress or layer-cover the toolbar. The z-index
     must sit ABOVE the FAB stack (.fab is z-index 22 / 25) so the
     profile chip + its dropdown menu paint on top of the right-edge
     FABs (memo, review) rather than under them. */
  position: relative;          /* anchor for absolutely-positioned .center */
  min-height: var(--tb-h);
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 18px;
  border-bottom: 1px solid var(--hair);
  background: var(--paper);
  font-family: var(--sans);
  gap: 12px;
}
.toolbar .left, .toolbar .right {
  display: flex; align-items: center; gap: 10px;
}
/* Center slot is ABSOLUTELY positioned so the Read / Mark up toggle
   sits perfectly over the body-text column rather than the toolbar's
   geometric midpoint. The prose is left-anchored at the canvas
   padding-left (388px = palette column width) and capped at
   --reader-max. Center of prose = 388 + (reader-max / 2). The
   transform pulls the toggle back by half its own width so its
   midpoint lands exactly on the prose midpoint. */
.toolbar .center {
  position: absolute;
  top: 50%;
  left: calc(388px + var(--reader-max) / 2);
  transform: translate(-50%, -50%);
  display: flex; align-items: center; gap: 10px;
  pointer-events: auto;
  z-index: 1;                  /* above the right cluster's background but tiny */
}
/* Very narrow viewports: if the absolute-positioned center would
   collide with the right cluster, drop back to the flexbox-center
   geometry rather than overlap. */
@media (max-width: 1200px) {
  .toolbar .center {
    position: static;
    transform: none;
  }
}
.crumbs {
  display: inline-flex;
  align-items: baseline;
  min-width: 0;
  flex: 1 1 auto;          /* claim available space so long doc titles can breathe */
  max-width: 64ch;
  font-size: 12.5px;
  color: var(--ink-fade);
  letter-spacing: 0.01em;
}
.crumbs #crumb-section {
  flex: 0 0 auto;           /* the "Red Stet" brand chip never shrinks */
  white-space: nowrap;
}
.crumbs .sep { margin: 0 6px; color: var(--hair-strong); flex: 0 0 auto; }
#crumb-title {
  color: var(--ink);
  font-weight: 500;
  min-width: 0;
  flex: 1 1 auto;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  cursor: default;
}
/* When the title is wider than its slot, hover/focus reveals the full
   string by sliding it leftward via a marquee animation. The OS tooltip
   (set via the `title` attribute in JS) is the fallback. */
#crumb-title:hover,
#crumb-title:focus {
  text-overflow: clip;
  overflow: visible;
  position: relative;
  z-index: 2;
}

/* Narrow viewports: shed non-essential toolbar bits so the core controls fit. */
@media (max-width: 1100px) {
  .toolbar .crumbs #crumb-section,
  .toolbar .crumbs .sep { display: none; }
  .tts .rate span:first-child { display: none; }
}
@media (max-width: 900px) {
  .tts .rate { display: none; }
  #voice-select { max-width: 90px; }
}

.mode-toggle {
  display: inline-flex;
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 3px;
}
.mode-btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--ink-fade);                /* inactive: faded grey */
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  padding: 6px 14px;
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}
.mode-btn:hover { color: var(--ink-soft); }
/* Active state: soft grey pill on cream — readable but quiet. Not the
   loud black-on-white default. */
.mode-btn.is-active {
  background: var(--paper);              /* the warm cream itself */
  color: var(--ink-soft);                /* soft grey ink, not solid black */
  box-shadow: 0 1px 0 rgba(28, 24, 21, 0.04),
              0 0 0 1px var(--hair-strong);
}
body[data-theme="dark"] .mode-btn.is-active {
  background: var(--paper-edge);
  color: var(--ink-soft);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.4),
              0 0 0 1px var(--hair-strong);
}

.icon-btn {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  color: var(--ink-soft);
  font-size: 14px;
  /* Uniform 32×32 circle so every toolbar bubble matches:
     hamburger, theme toggle, TTS controls, profile chip, etc. */
  width: 32px; height: 32px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
/* Honor the `hidden` HTML attribute on icon-btns — `display: inline-flex`
   above would otherwise win against the UA default `[hidden]{display:none}`.
   This affects the now-hidden toolbar theme toggle (moved to User
   Preferences) plus any other icon-btn we mark hidden. */
.icon-btn[hidden] { display: none !important; }
.icon-btn:hover { background: rgba(0,0,0,0.05); color: var(--ink); }
body[data-theme="dark"] .icon-btn:hover { background: rgba(255,255,255,0.06); }
.icon-btn.rec { color: var(--red); font-size: 18px; line-height: 1; }
.icon-btn.rec.is-on { background: var(--red); color: white; animation: pulse 1.2s infinite; }
.icon-btn.is-hidden { display: none; }

/* Combined Open dropdown in the sidebar. Same visual language as
   the export menu — small card with two-line entries. */
.open-menu { position: relative; }
.open-menu-list {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  right: 0;
  z-index: 70;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 6px;
  font-family: var(--sans);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.open-menu-list[hidden] { display: none; }
.open-item {
  appearance: none;
  background: transparent;
  border: 0;
  border-radius: 6px;
  padding: 7px 8px;
  display: flex;
  align-items: center;
  gap: 10px;
  cursor: pointer;
  text-align: left;
  color: var(--ink);
  font-family: inherit;
  font-size: 12.5px;
}
.open-item:hover { background: var(--paper-edge); }
.open-item .open-glyph {
  font-size: 16px;
  flex-shrink: 0;
  width: 22px;
  text-align: center;
}
.open-item .open-label { display: flex; flex-direction: column; gap: 1px; }
.open-item .open-main { font-weight: 500; }
.open-item .open-sub  { font-size: 11px; color: var(--ink-fade); }

/* Export menu — opens beneath the ⤓ icon-btn in the toolbar. */
.export-menu { position: relative; display: inline-block; }
.export-menu-list {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 60;
  min-width: 240px;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 6px;
  font-family: var(--sans);
}
.export-menu-list[hidden] { display: none; }
.export-divider { height: 1px; background: var(--hair); margin: 4px 4px; }
.export-item {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  padding: 8px 10px;
  border: 0;
  border-radius: 6px;
  background: transparent;
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
  text-align: left;
  cursor: pointer;
}
.export-item:hover { background: var(--red-wash); color: var(--red); }
.export-item .ex-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 28px;
  padding: 1px 6px;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
  background: var(--paper-edge);
  border-radius: 4px;
}
.export-item:hover .ex-glyph { color: var(--red); background: white; }
.export-item.export-item-small {
  padding: 5px 10px;
  font-size: 11.5px;
  color: var(--ink-fade);
}
.export-item.export-item-small:hover { color: var(--ink); background: rgba(0,0,0,0.04); }
.export-item.export-item-small:hover .ex-glyph { color: var(--ink-soft); background: var(--paper-edge); }
.export-sub {
  padding: 2px 12px 6px;
  font-size: 10.5px;
  color: var(--ink-fade);
  letter-spacing: 0.02em;
}

/* Tiny floating "Converting…" toast shown while a .docx / .pdf is
   being parsed into markdown. Centered low on the screen so it doesn't
   sit under the cursor. */
.convert-toast {
  position: fixed;
  left: 50%;
  bottom: 64px;
  transform: translateX(-50%);
  z-index: 100;
  padding: 10px 18px;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--sans);
  font-size: 13px;
  letter-spacing: 0.01em;
  border-radius: 999px;
  box-shadow: 0 14px 40px rgba(0,0,0,0.18);
  pointer-events: none;
}
.convert-toast[hidden] { display: none; }

/* Drag-and-drop overlay — shown when files/folders are dragged over
   the window. Body.is-dragging fades it in; otherwise hidden. */
.drop-overlay {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(28, 24, 21, 0.55);
  backdrop-filter: blur(3px);
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 160ms ease;
}
body.is-dragging .drop-overlay {
  opacity: 1;
  pointer-events: auto;
}
.drop-overlay-card {
  background: var(--paper);
  border: 2px dashed var(--red);
  border-radius: 12px;
  padding: 36px 56px;
  text-align: center;
  box-shadow: 0 18px 56px rgba(28,22,16,0.25);
}
.drop-overlay-glyph {
  font-size: 44px;
  line-height: 1;
  margin-bottom: 12px;
}
.drop-overlay-title {
  font-family: var(--sans);
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.005em;
}
.drop-overlay-sub {
  margin-top: 6px;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-fade);
}

@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(194,54,45,0.5); }
  50%      { box-shadow: 0 0 0 6px rgba(194,54,45,0); }
}

/* The TTS cluster is a click-to-open dropdown anchored on the right of
   the toolbar. A single trigger bubble (.tts-trigger) lives in the
   toolbar; clicking it opens a panel below with the full transport
   (play/pause/prev/next/voice/speed). The trigger glows red while TTS
   is playing so the user always sees state at a glance. */
.tts-wrap {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.tts-trigger {
  width: 32px;
  height: 32px;
  border: 1px solid var(--hair-strong);
  border-radius: 50%;
  background: var(--paper);
  color: var(--red);
  font-size: 14px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.tts-trigger:hover { border-color: var(--red); }
body.tts-playing .tts-trigger,
body.tts-paused  .tts-trigger { background: var(--red-wash); border-color: var(--red); }
body.tts-playing .tts-trigger { animation: pulse 1.6s ease-out infinite; }
/* Dropdown panel — same visual treatment as the profile menu so the
   two read as siblings on the toolbar. */
.tts-panel {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 100;
  min-width: 280px;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 10px;
  display: none;
  flex-direction: column;
  gap: 8px;
}
.tts-panel[hidden] { display: none; }
.tts-panel.is-open { display: flex; }
.tts-panel-row {
  display: flex;
  align-items: center;
  gap: 4px;
  justify-content: center;
}
.tts-panel .icon-btn {
  width: 28px;
  height: 28px;
}
.tts-panel-rate {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-top: 6px;
  border-top: 1px solid var(--hair);
  font-size: 12px;
  color: var(--ink-fade);
}
.tts-panel-rate span { flex: 0 0 auto; }
.tts-panel-rate input { flex: 1; accent-color: var(--red); }
.tts-panel select {
  width: 100%;
  border: 1px solid var(--hair);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 12px;
  padding: 4px 6px;
  border-radius: 6px;
  outline: none;
  cursor: pointer;
}
.tts select {
  border: none; background: transparent;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-soft);
  max-width: 140px;
  outline: none;
  cursor: pointer;
}
.tts .rate {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11.5px;
  color: var(--ink-fade);
  padding: 0 4px 0 8px;
  border-left: 1px solid var(--hair);
}
.tts .rate input { width: 80px; accent-color: var(--red); }

.ghost-btn, .primary-btn {
  appearance: none;
  font-family: var(--sans);
  font-size: 12px;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  border: 1px solid var(--hair-strong);
  background: transparent;
  color: var(--ink-soft);
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.ghost-btn:hover { background: var(--paper); color: var(--ink); }
.primary-btn {
  background: var(--red);
  color: white;
  border-color: var(--red);
}
.primary-btn:hover { background: var(--red-deep); border-color: var(--red-deep); }

/* =========================================================================
   Reading canvas — manuscript-clean prose
   ========================================================================= */

.canvas {
  overflow-y: auto;
  background: var(--paper);
  /* Book-page proportions: generous top/bottom; the side gutter is whatever's
     left after centering the reading column with margin:auto. */
  padding: clamp(56px, 8vh, 120px) clamp(20px, 4vw, 64px) clamp(120px, 18vh, 240px);
  scroll-behavior: smooth;
  width: 100%;
  min-width: 0;
  position: relative;                  /* containing block for margin notes */
}

/* --- SVG overlay for note leader-arrows ---------------------------- */
.note-arrows {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 4;
  overflow: visible;
  /* Stays hidden until _drawNoteArrowsNow() emits a real path with
     non-zero coords — prevents the brief "all arrows at (0,0)" flash
     during the first paint and webfont reflow. */
  visibility: hidden;
}
.note-arrow {
  fill: none;
  stroke: var(--red);
  stroke-width: 1.4;
  stroke-linecap: round;
  opacity: 0.55;
  transition: opacity 180ms ease;
}
.note-arrow.is-active { opacity: 1; }

/* Proofreader's ^ caret rendered as an SVG <text> at each note's
   anchor point — points UP at where the note refers to. */
.note-anchor-caret {
  fill: var(--red);
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  text-anchor: middle;
  opacity: 0.7;
  user-select: none;
}
body:not([data-mode="mark"]) .note-arrows { display: none; }

/* --- Margin notes column ----------------------------------------------
   Lives on the RIGHT of the prose, positioned absolutely inside the
   canvas so each note can be `top:`-pinned to its target block. */
.margin-notes {
  position: absolute;
  top: 0;
  /* Just to the right of the locked prose column (368 padding + 38rem
     max width + 24 gap). Falls back to viewport-relative if narrower. */
  left: calc(368px + 38rem + 24px);
  width: 240px;
  max-width: calc(100vw - 368px - 38rem - 48px);
  pointer-events: none;                 /* clicks pass through except on notes */
  z-index: 5;
}
body:not([data-mode="mark"]) .margin-notes { display: none; }

.margin-note {
  position: absolute;
  font-family: var(--hand);
  color: var(--red);
  font-size: 1.15em;
  line-height: 1.35;
  padding: 4px 8px;
  border-left: 2px solid var(--red);
  background: transparent;
  min-width: 140px;
  max-width: 240px;
  cursor: text;
  pointer-events: auto;
  opacity: 0.55;                       /* dimmed when not active */
  outline: none;
  white-space: pre-wrap;
  word-wrap: break-word;
  transition: opacity 180ms ease, background 180ms ease;
  border-radius: 0 6px 6px 0;
}

/* Author orb at the leading edge of every margin note. Inline so it
   sits flush with the first line of text, contentEditable=false so it
   never participates in caret movement. Hidden by default and revealed
   only when the user toggles "Authors" on in the review panel — same
   gating as the inline ins / editorial-mark orbs, so one switch covers
   the entire authorship-display surface. */
.margin-note-author-dot {
  display: none;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 6px;
  vertical-align: middle;
  flex-shrink: 0;
  background: #6b6b6b;                 /* fallback before inline color */
}
body[data-author-orbs="on"] .margin-note-author-dot {
  display: inline-block;
}
.margin-note:hover,
.margin-note:focus,
.margin-note.is-editing {
  opacity: 1;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(28,26,23,0.06);
}
.margin-note[data-empty="true"]::before {
  content: "Type a note…";
  color: var(--ink-fade);
  font-family: var(--sans);
  font-style: italic;
  font-size: 12px;
  opacity: 0.6;
}
.margin-note .rm-mic-tag {
  display: block;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--red);
  opacity: 0.7;
  margin-bottom: 2px;
}

/* Threaded replies nested under a margin note. They share the parent's
   absolute position (no own anchor / no own arrow) and visually indent
   under it with a subtle inset rail. This is how the margin column
   stays readable when one paragraph has multiple comments. */
.margin-note-thread {
  margin-top: 6px;
  padding-top: 6px;
  border-top: 1px dashed rgba(184, 56, 41, 0.25);  /* dashed in red, faded */
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.margin-note.is-reply {
  position: static;                 /* not absolutely positioned — flows inside parent */
  font-size: 1em;                   /* a touch smaller than top-level */
  padding: 2px 6px 2px 10px;
  margin-left: 6px;
  border-left: 2px solid rgba(184, 56, 41, 0.4); /* faded red rail */
  opacity: 0.85;
  min-width: 0;
  max-width: none;
  background: transparent;
  box-shadow: none;
}
.margin-note.is-reply:hover,
.margin-note.is-reply:focus,
.margin-note.is-reply.is-editing {
  opacity: 1;
  background: var(--paper);
}
/* The orb on a reply is slightly smaller — gentle visual hierarchy. */
.margin-note.is-reply .margin-note-author-dot {
  width: 7px;
  height: 7px;
  margin-right: 5px;
}

.prose {
  max-width: var(--reader-max);
  /* Left-anchored in BOTH modes so switching read↔mark never shifts the
     text. (The .canvas padding-left: 388px below puts the prose just to
     the right of the proofreader palette column.) */
  margin-left: 0;
  margin-right: auto;
  font-family: var(--prose);          /* Tiempos Text — manuscript body serif */
  /* Reader text size + line height are driven by User Preferences
     sliders. The custom properties default to 1.0 and 1.55 so an
     untuned install matches the original design. */
  font-size: calc(18.5px * var(--reader-font-scale, 1));
  line-height: var(--reader-line-height, 1.55);
  color: var(--ink);
  /* Old-style figures (1929, 1934 sit on the baseline like prose, not
     uppercase). Tiempos Text has them — opt in. */
  font-feature-settings: "onum" 1, "kern" 1, "liga" 1;
  transition: line-height 1000ms cubic-bezier(.2,.6,.2,1);
}
/* Mark mode: prose opens up to give the editor's marks room to
   breathe. The +0.5 keeps the additional room consistent regardless of
   the user's accessibility setting. */
body[data-mode="mark"] .prose { line-height: calc(var(--reader-line-height, 1.55) + 0.45); }

/* ----- Read mode: hide ALL proofreader visuals ------------------------
   The marks are baked into the prose HTML, so we strip their styling in
   read mode rather than removing them. For wrap marks (rm-del, rm-cap,
   rm-italic, etc.) the original text inside stays visible — just plain.
   Additive marks (the floating insert text, point punctuation, editorial
   labels, gutter + button, margin notes column, leader arrows) have no
   original text to preserve, so they get display:none. */
body:not([data-mode="mark"]) .prose [data-mark-id] {
  color: inherit !important;
  background: transparent !important;
  text-decoration: none !important;
  text-decoration-color: transparent !important;
  border-color: transparent !important;
  /* Critical: strip border WIDTH and padding too, not just colors.
     A transparent border still takes inline space — that's what was
     producing the phantom gap around words wrapped in circled marks
     like awk / wdw / ww when the doc was viewed in Read or Write mode. */
  border-width: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  font-style: inherit !important;
  font-weight: inherit !important;
}
body:not([data-mode="mark"]) .prose [data-mark-id]::before,
body:not([data-mode="mark"]) .prose [data-mark-id]::after {
  content: none !important;
}
/* Citations are an EXCEPTION: they must remain visible in every mode
   (Read shows the reader where sourcing is owed; Write lets the author
   see their own flags). Re-assert the counter-driven superscript with
   high specificity so it survives the blanket-hide rule above. */
body .prose .rm-cite[data-mark-id]::after,
body .prose .rm-cite::after {
  content: "[" counter(rm-cite-num) "]" !important;
  counter-increment: rm-cite-num !important;
  display: inline-block !important;
  vertical-align: super !important;
  font-size: 0.68em !important;
  font-weight: 500 !important;
  color: var(--ink-fade) !important;
  margin-left: 2px !important;
  font-family: var(--serif) !important;
  line-height: 1 !important;
  background: transparent !important;
  padding: 0 !important;
}
body:not([data-mode="mark"]) .prose .rm-ins,
body:not([data-mode="mark"]) .prose .rm-punct,
body:not([data-mode="mark"]) .prose .rm-label,
body:not([data-mode="mark"]) .prose .rm-anchor,
body:not([data-mode="mark"]) .prose .rm-mic-anchor,
body:not([data-mode="mark"]) .prose .rm-indent-mark,
body:not([data-mode="mark"]) .prose .rm-hyphen,
body:not([data-mode="mark"]) .prose .rm-endash,
body:not([data-mode="mark"]) .prose .rm-emdash,
body:not([data-mode="mark"]) .prose .gutter-add-note {
  display: none !important;
}
/* (Margin notes column + leader-arrow SVG are already hidden in read
   mode by existing rules further up.) */

/* ----- Mark-mode entry: 1-second time-lapse fade-in ------------------
   When setMode('mark') runs from read mode, JS adds `.rm-inking` to
   <body> for ~1.05s. While it's there, every proofreader visual runs a
   one-shot opacity 0 → 1 animation so the red lettering and marks feel
   like they're being written in fast-forward. */
body.rm-inking[data-mode="mark"] .prose [data-mark-id],
body.rm-inking[data-mode="mark"] .prose .gutter-add-note,
body.rm-inking[data-mode="mark"] .margin-notes .margin-note,
body.rm-inking[data-mode="mark"] .note-arrows {
  animation: rm-ink-in 1s ease-out both;
}
@keyframes rm-ink-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.prose > * { margin: 0 0 1.05em; }
.prose > *:first-child { margin-top: 0; }

/* Paragraph rhythm — set by JS on body.dataset.paragraphStyle. Default
   ("gap", set above) leaves the 1.05em paragraph spacing alone. When
   the document was authored typewriter-style with indented first lines,
   we drop the gap and add a first-line indent instead. The paragraph
   immediately after a heading or the first child of .prose stays
   un-indented, which is the book-interior convention. */
body[data-paragraph-style="indent"] .prose p {
  margin-bottom: 0;
  text-indent: 1.6em;
}
body[data-paragraph-style="indent"] .prose > p:first-child,
body[data-paragraph-style="indent"] .prose h1 + p,
body[data-paragraph-style="indent"] .prose h2 + p,
body[data-paragraph-style="indent"] .prose h3 + p,
body[data-paragraph-style="indent"] .prose h4 + p,
body[data-paragraph-style="indent"] .prose blockquote + p,
body[data-paragraph-style="indent"] .prose hr + p {
  text-indent: 0;
}

/* Editorial Tiempos Headline for headings — ball terminals, high stroke
   contrast, the "I'm Stephanie." aesthetic. */
.prose h1, .prose h2, .prose h3, .prose h4 {
  font-family: var(--display);
  font-weight: 400;          /* Tiempos Headline Regular — the proper editorial weight */
  color: var(--ink);
  letter-spacing: -0.012em;
  line-height: 1.08;
  margin-top: 1.4em;
  margin-bottom: 0.5em;
}
.prose h1 {
  font-size: 2.6em;          /* tuned to fit "Welcome to Red Stet." on one line at the reader column width */
  font-weight: 400;
  letter-spacing: -0.022em;
  line-height: 1.02;
  margin-top: 0;
  margin-bottom: 0.4em;
}
.prose h2 {
  font-size: 2.0em;
  letter-spacing: -0.018em;
  margin-top: 1.6em;
  padding-top: 0.6em;
  border-top: 1px solid var(--hair);
}
.prose h3 {
  font-size: 1.4em;
  letter-spacing: -0.012em;
}
.prose h4 {
  font-size: 1.08em;
  font-family: var(--sans);   /* tiny inline-section headers stay sans for clarity */
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: uppercase;
  color: var(--ink-soft);
}

.prose p { hyphens: auto; -webkit-hyphens: auto; }

.prose a { color: var(--accent); text-decoration: none; border-bottom: 1px solid currentColor; }
.prose a:hover { color: var(--red); }

.prose strong { font-weight: 600; }
/* Body italic stays in the Tiempos Text family (same as the body
   upright) — proper cursive forms (looped a, descending f, slanted e). */
.prose em,
.prose i,
.prose cite {
  font-style: italic;
}

.prose code {
  font-family: var(--mono);
  font-size: 0.88em;
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-radius: 4px;
  padding: 1px 5px;
}
.prose pre {
  font-family: var(--mono);
  font-size: 13.5px;
  line-height: 1.55;
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 14px 16px;
  overflow-x: auto;
}
.prose pre code { background: transparent; border: none; padding: 0; font-size: inherit; }

.prose blockquote {
  margin-left: 0;
  padding: 0.1em 0 0.1em 1.1em;
  border-left: 2px solid var(--red);
  color: var(--ink-soft);
  font-style: italic;
}

.prose ul, .prose ol { padding-left: 1.4em; }
.prose li { margin-bottom: 0.35em; }
.prose li::marker { color: var(--ink-fade); }

.prose hr {
  border: none;
  border-top: 1px solid var(--hair);
  margin: 2em auto;
  max-width: 50%;
}

.prose table {
  border-collapse: collapse;
  width: 100%;
  font-size: 0.94em;
  font-family: var(--sans);
}
.prose th, .prose td {
  border-bottom: 1px solid var(--hair);
  padding: 8px 12px;
  text-align: left;
  vertical-align: top;
}
.prose th { font-weight: 600; color: var(--ink); border-bottom: 1.5px solid var(--hair-strong); }
.prose tr:hover td { background: rgba(0,0,0,0.015); }

.prose img { max-width: 100%; height: auto; border-radius: 6px; }

/* =========================================================================
   Mark-up mode — proofreader's pencil
   =========================================================================

   The document text NEVER mutates. Marks are a separate annotation layer
   rendered on top: insertions float above the line in red handwriting,
   deletions get a struck-through red line, paragraph-level marks like
   capitalize/italicize sit beneath the affected text. Each marked block
   doubles its line-height so the floating insertions have a paper-like
   gap to live in. */

.prose .block {
  /* Same 1s line-height ease as .prose itself, so the read → mark
     direction (where .block.is-marked switches on with line-height
     2.7 !important) is as smooth as the mark → read direction. */
  transition: line-height 1000ms cubic-bezier(.2,.6,.2,1),
              background var(--t-fast);
}
body[data-mode="mark"] .prose .block {
  position: relative;
  padding: 4px 0;
  cursor: text;
  border-radius: 3px;
}
body[data-mode="mark"] .prose .block:hover { background: rgba(194,54,45,0.04); }

/* In MARK mode, any block with one or more marks gets double-spaced so
   floating insertions and underline marks have room. In READ mode the
   marks are hidden, so the block follows the tight 1.5 prose line-height
   like any unmarked paragraph — keeping the text position identical
   between modes. */
body[data-mode="mark"] .block.is-marked {
  line-height: 2.7 !important;
}
body[data-mode="mark"] .block.is-marked.is-marked-light {
  line-height: 2.1 !important;
}

/* --- INSERT: text floats above (or below) the line, ∧ caret points at it - */
.rm-ins {
  position: relative;
  display: inline;
  letter-spacing: 0;
}
.rm-ins-text {
  position: absolute;
  bottom: 1.4em;                 /* default: lift into the gap above the line */
  left: 50%;
  transform: translateX(-50%);
  font-family: var(--hand);
  color: var(--red);
  font-size: 1.1em;
  line-height: 1;
  white-space: nowrap;            /* insertions are single-line */
  padding: 0 2px;
  pointer-events: none;
  z-index: 2;
}
.rm-ins-caret {
  display: inline-block;
  position: relative;
  width: 0;
  color: var(--red);
  font-family: var(--sans);
}
.rm-ins-caret::before {
  /* Arrow's BASE sits clearly ABOVE the top of capital letters / ascenders
     (k, h, l, T, etc.) so it never overlaps the lettering. Small font so
     it tucks neatly into the gap between letters and the floating note. */
  content: "∧";
  position: absolute;
  left: 50%;
  bottom: 0.95em;
  transform: translateX(-50%);
  font-size: 0.62em;
  line-height: 1;
}
/* If the layout pass moves an insertion BELOW the line to avoid colliding
   with a neighbor above, render the handwritten text under the line.
   Distance matches the above-line variant (1.4em from baseline) so the
   above/below symmetry is visually balanced. */
.rm-ins.is-below .rm-ins-text {
  bottom: auto;
  top: 1.0em;
}
.rm-ins.is-below .rm-ins-caret::before {
  content: "∨";
  bottom: auto;
  top: 0.4em;
  font-size: 0.62em;
}

/* Live in-progress insertion (user is still typing) — dotted halo */
.rm-ins.is-active .rm-ins-text {
  outline: 1.5px dashed var(--red);
  outline-offset: 2px;
  border-radius: 4px;
  padding: 0 4px;
  background: var(--paper);
}
.rm-ins.is-active .rm-ins-text::after {
  content: "▍";
  display: inline-block;
  color: var(--red);
  margin-left: 1px;
  animation: blink 0.9s steps(2, end) infinite;
}
@keyframes blink { to { opacity: 0; } }

/* --- DELETE: red strike with a small terminal swirl --------------------- */
.rm-del {
  color: var(--red);
  text-decoration: line-through;
  text-decoration-color: var(--red);
  text-decoration-thickness: 1.6px;
  text-decoration-skip-ink: none;
  animation: rm-del-fade 320ms ease-out;
}
@keyframes rm-del-fade {
  from { text-decoration-color: transparent; color: var(--ink); }
  to   { text-decoration-color: var(--red);  color: var(--red); }
}

/* Consistency-layer marks — same red strikethrough vocabulary as
   editorial deletions, but rendered with a wavy underline + a
   light cursor hint so editors can tell at a glance that this
   mark came from the Style Guide rather than a human reviewer.
   Hovering shows the corrected value via the data-replacement attr. */
.rm-consistency {
  /* Override the linear strikethrough with a wavy red underline so
     consistency marks read as "system finding" rather than "editor
     deletion" while still using the red-mark vocabulary. */
  text-decoration: underline wavy var(--red);
  text-decoration-thickness: 1.2px;
  cursor: help;
}
.rm-consistency:hover {
  background: color-mix(in srgb, var(--red) 8%, transparent);
  border-radius: 3px;
}

/* --- TRANSPOSE: curl drawn above two adjacent words --------------------- */
.rm-trans {
  position: relative;
  color: var(--ink);
}
.rm-trans::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: -0.55em;
  height: 0.7em;
  border: 1.6px solid var(--red);
  border-color: var(--red) var(--red) transparent var(--red);
  border-radius: 60% 60% 0 0 / 100% 100% 0 0;
  pointer-events: none;
}
.rm-trans::after {
  /* the second arc going the other direction — the s-curve transpose loop */
  content: "tr";
  position: absolute;
  left: -1.4em;
  top: -1.1em;
  font-family: var(--hand);
  font-size: 0.9em;
  color: var(--red);
  pointer-events: none;
}

/* --- STET: dotted underline (let it stand) ------------------------------ */
.rm-stet {
  color: var(--ink);
  border-bottom: 2px dotted var(--red);
}
.rm-stet::after {
  content: " stet";
  font-family: var(--hand);
  font-size: 0.85em;
  color: var(--red);
  margin-left: 2px;
}

/* (Removed standalone .rm-spell — spell-out now uses .rm-edit-note with
   data-label="sp" so it shares the circled-with-label visual.) */

/* --- CAPITALIZE: triple underline --------------------------------------- */
.rm-cap {
  color: var(--ink);
  background-image:
    linear-gradient(var(--red), var(--red)),
    linear-gradient(var(--red), var(--red)),
    linear-gradient(var(--red), var(--red));
  background-size: 100% 1.2px;
  background-position: 0 100%, 0 calc(100% - 3px), 0 calc(100% - 6px);
  background-repeat: no-repeat;
  padding-bottom: 8px;
  animation: rm-cap-draw 420ms ease-out;
}
@keyframes rm-cap-draw {
  from { background-size: 0% 1.2px; }
  to   { background-size: 100% 1.2px; }
}

/* --- LOWERCASE: forward slash through the word -------------------------- */
.rm-lower {
  position: relative;
  color: var(--ink);
}
.rm-lower::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: -0.1em; bottom: -0.1em;
  background: linear-gradient(
    to top right,
    transparent calc(50% - 1px),
    var(--red) calc(50% - 1px),
    var(--red) calc(50% + 1px),
    transparent calc(50% + 1px)
  );
  pointer-events: none;
}

/* --- ITALICS: single red underline -------------------------------------- */
.rm-italic-mark {
  color: var(--ink);
  border-bottom: 1.6px solid var(--red);
}
.rm-italic-mark::after {
  content: " ital";
  font-family: var(--hand);
  font-size: 0.8em;
  color: var(--red);
  margin-left: 2px;
}

/* --- BOLD: wavy red underline ------------------------------------------- */
.rm-bold-mark {
  color: var(--ink);
  text-decoration: underline wavy var(--red);
  text-decoration-thickness: 1.6px;
  text-underline-offset: 3px;
}
.rm-bold-mark::after {
  content: " bf";
  font-family: var(--hand);
  font-size: 0.8em;
  color: var(--red);
  margin-left: 4px;
}

/* --- UNDERLINE: plain single red underline (no marker label) ----------- */
.rm-underline-mark {
  color: var(--ink);
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.4px;
  text-underline-offset: 3px;
}
.rm-underline-mark::after {
  content: " u";
  font-family: var(--hand);
  font-size: 0.8em;
  color: var(--red);
  margin-left: 4px;
}

/* (Removed standalone .rm-roman-mark — roman now uses .rm-edit-note with
   data-label="rom" so it shares the circled-with-label visual.) */

/* --- NOTE ANCHOR: underline the range a margin note references ------ */
.rm-note-anchor {
  color: var(--ink);
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
}

/* --- CITATION marks: "this claim needs a source" --------------------------
   The marked text stays styled like normal prose; CSS appends a small
   superscript number after the span. The counter increments in document
   order automatically — no JS needed to compute numbering. */
#prose {
  counter-reset: rm-cite-num;
}
.rm-cite {
  /* Dashed red underline + soft tint so the marked claim is unmistakable
     against the prose. The citation number is also bold red — between
     the two the writer can't miss it. */
  background: rgba(184, 56, 41, 0.10);
  border-bottom: 1.5px dashed var(--red);
  cursor: pointer;
  transition: background var(--t-fast);
  padding-bottom: 1px;
}
.rm-cite:hover {
  background: rgba(184, 56, 41, 0.20);
}
.rm-cite::after {
  counter-increment: rm-cite-num;
  content: "[" counter(rm-cite-num) "]";
  display: inline-block;
  vertical-align: super;
  font-size: 0.68em;
  font-weight: 500;
  color: var(--ink-fade);
  margin-left: 2px;
  font-family: var(--serif);
  line-height: 1;
}
/* When the row in the Sources panel is clicked, the corresponding
   span gets .rm-cite-focus for ~1.4s — soft pulse so the eye lands. */
.rm-cite.rm-cite-focus {
  animation: rm-cite-pulse 1.4s ease;
}
@keyframes rm-cite-pulse {
  0%, 100% { background: linear-gradient(transparent 75%, rgba(184, 56, 41, 0.10) 75%); }
  30%, 60% { background: rgba(184, 56, 41, 0.20); }
}

/* Floating Citations drawer (Write mode) — small bottom-right panel
   that lists every .rm-cite in the current doc, available outside any
   assignment context. Toggle pill shows a count; expanded body shows
   the numbered list and lets the writer jump to each claim. */
.cite-drawer {
  position: fixed;
  right: 18px;
  bottom: 60px;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 8px;
  pointer-events: none;
}
.cite-drawer > * { pointer-events: auto; }
.cite-drawer-toggle {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 12px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 999px;
  box-shadow: 0 4px 14px rgba(0,0,0,0.08);
  cursor: pointer;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  transition: transform var(--t-fast), box-shadow var(--t-fast);
}
.cite-drawer-toggle:hover {
  transform: translateY(-1px);
  box-shadow: 0 6px 18px rgba(0,0,0,0.12);
}
.cite-drawer-icon {
  color: var(--red);
  font-weight: 700;
  letter-spacing: -1px;
}
.cite-drawer-count {
  display: inline-block;
  min-width: 20px;
  padding: 2px 7px;
  background: var(--red);
  color: white;
  border-radius: 999px;
  font-weight: 700;
  font-size: 11px;
  line-height: 1.2;
  text-align: center;
}
.cite-drawer-body {
  width: 320px;
  max-height: 50vh;
  overflow-y: auto;
  padding: 14px 16px;
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0,0,0,0.14);
}
.cite-drawer-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 6px;
}
.cite-drawer-header strong {
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
}
.cite-drawer-close {
  border: 0;
  background: transparent;
  font-size: 18px;
  line-height: 1;
  cursor: pointer;
  color: var(--muted);
  padding: 2px 6px;
}
.cite-drawer-close:hover { color: var(--ink); }
.cite-drawer-hint {
  font-size: 11px;
  color: var(--muted);
  margin: 0 0 10px 0;
  line-height: 1.4;
}
.cite-drawer-list { display: flex; flex-direction: column; gap: 2px; }
.cite-drawer-row-wrap {
  display: flex;
  flex-direction: column;
  gap: 0;
  border-radius: 6px;
  padding: 2px 0;
}
.cite-drawer-row-wrap.is-open {
  background: rgba(0, 0, 0, 0.02);
  padding: 4px;
  margin: 2px 0;
}
.cite-drawer-row-head {
  display: flex;
  align-items: center;
  gap: 4px;
}
.cite-drawer-row {
  display: flex;
  gap: 8px;
  align-items: center;
  padding: 6px 8px;
  border: 0;
  background: transparent;
  border-radius: 6px;
  text-align: left;
  cursor: pointer;
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink);
  flex: 1 1 auto;
  min-width: 0;
}
.cite-drawer-row:hover { background: rgba(184, 56, 41, 0.06); }
.cite-drawer-row-status {
  flex: 0 0 auto;
  color: var(--ink-fade);
  font-size: 13px;
  font-weight: 600;
  font-family: var(--sans);
  margin-left: auto;
  padding-left: 6px;
}
.cite-drawer-row-wrap.has-source .cite-drawer-row-status { color: #2f8a4a; }
.cite-drawer-row-remove {
  flex: 0 0 auto;
  width: 24px;
  height: 24px;
  border: 0;
  background: transparent;
  border-radius: 4px;
  color: var(--muted);
  cursor: pointer;
  font-size: 16px;
  line-height: 1;
  padding: 0;
}
.cite-drawer-row-remove:hover {
  background: rgba(184, 56, 41, 0.10);
  color: var(--red);
}
.cite-drawer-row-body { padding: 6px 8px 4px 8px; }
.cite-drawer-source-label {
  display: block;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--muted);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin-bottom: 4px;
}
.cite-drawer-source-input {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid var(--rule);
  border-radius: 6px;
  padding: 8px 10px;
  font-family: var(--serif);
  font-size: 13px;
  line-height: 1.4;
  color: var(--ink);
  background: var(--paper);
  resize: vertical;
  min-height: 64px;
}
.cite-drawer-source-input:focus {
  outline: 0;
  border-color: var(--red);
  box-shadow: 0 0 0 2px rgba(184, 56, 41, 0.18);
}
.cite-drawer-footer {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 8px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px solid var(--rule);
}
.cite-drawer-copy {
  border: 1px solid var(--rule);
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.cite-drawer-copy:hover {
  background: rgba(184, 56, 41, 0.06);
  border-color: var(--red);
  color: var(--red);
}
.cite-drawer-copy-status {
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-fade);
  font-style: italic;
}
.cite-drawer-row-num {
  flex: 0 0 auto;
  min-width: 22px;
  color: var(--red);
  font-family: var(--sans);
  font-weight: 700;
  font-size: 12px;
  background: rgba(184, 56, 41, 0.10);
  border-radius: 3px;
  padding: 1px 5px;
  text-align: center;
}
.cite-drawer-row-text {
  flex: 1 1 auto;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Write-mode "Insert note" stub — the tiny inline marker dropped at
   the cursor when the writer clicks ∧ in the Write palette. We can't
   render the full floating ins overlay here (Write mode is live
   contentEditable, no per-block originalText), so this gives the writer
   a visible anchor that turns into the full overlay when they flip to
   Mark/Read mode. */
.rm-ins-write-stub {
  display: inline-block;
  width: 0.7em;
  height: 0.9em;
  vertical-align: text-bottom;
  border-left: 2px solid var(--red);
  border-right: 2px solid var(--red);
  margin: 0 1px;
  position: relative;
  background: rgba(184, 56, 41, 0.06);
}
.rm-ins-write-stub::before {
  content: "∧";
  position: absolute;
  top: -0.9em;
  left: 50%;
  transform: translateX(-50%);
  color: var(--red);
  font-family: var(--hand);
  font-size: 0.7em;
  line-height: 1;
}

/* --- PARENS: red ( and ) bracketing the selection --------------------- */
.rm-parens, .rm-brackets {
  position: relative;
  color: var(--ink);
}
.rm-parens::before { content: "("; color: var(--red); font-family: var(--hand); margin-right: 1px; }
.rm-parens::after  { content: ")"; color: var(--red); font-family: var(--hand); margin-left:  1px; }
.rm-brackets::before { content: "["; color: var(--red); font-family: var(--hand); margin-right: 1px; }
.rm-brackets::after  { content: "]"; color: var(--red); font-family: var(--hand); margin-left:  1px; }
.rm-quote-range {
  position: relative;
  color: var(--ink);
}
.rm-quote-range::before { content: "“"; color: var(--red); font-family: var(--hand); margin-right: 1px; font-weight: 600; }
.rm-quote-range::after  { content: "”"; color: var(--red); font-family: var(--hand); margin-left:  1px; font-weight: 600; }
.rm-apos-range {
  position: relative;
  color: var(--ink);
}
.rm-apos-range::before { content: "‘"; color: var(--red); font-family: var(--hand); margin-right: 1px; font-weight: 600; }
.rm-apos-range::after  { content: "’"; color: var(--red); font-family: var(--hand); margin-left:  1px; font-weight: 600; }

/* --- EDITORIAL LABELS (ww, wc, awk, wdy, R-O, rep, wf, lf, rom) -------
   Selected text is wrapped — either circled (ww, wc, awk, wdy, rep, rom)
   or underlined (R-O, wf, lf) — with a small red handwritten abbreviation
   trailing it, matching the proofreader chart. */
.rm-edit-note {
  position: relative;
  color: var(--ink);
  border-bottom: 1.4px solid var(--red);
}
.rm-edit-note::after {
  content: " " attr(data-label);
  font-family: var(--hand);
  font-size: 0.78em;
  color: var(--red);
  margin-left: 4px;
  vertical-align: 0.18em;
  letter-spacing: 0.02em;
}
.rm-edit-note.rm-edit-circled {
  border-bottom: none;
  border: 1.4px solid var(--red);
  border-radius: 999px;
  padding: 0 6px;
}

/* --- PUNCTUATION marks: INLINE circled glyph in the natural reading
   position + a small ∧ arrow BELOW the line pointing up at it.
   The glyph itself sits inline-block (in the text flow) at the insertion
   point, so the writer reads the document with the proposed punctuation
   visible right where it would go. --------------------------------- */
.rm-punct {
  display: inline-block;
  position: relative;
  color: var(--red);
  font-family: var(--hand);
  font-size: 0.92em;
  font-weight: 500;
  line-height: 1;
  border: 1.4px solid var(--red);
  border-radius: 999px;
  padding: 1px 5px 2px;
  margin: 0 1px;
  vertical-align: 0.05em;
  background: var(--paper);
}
.rm-punct::after {
  content: "∧";
  position: absolute;
  left: 50%;
  top: 100%;
  margin-top: 4px;
  transform: translateX(-50%);
  color: var(--red);
  font-family: var(--sans);
  font-size: 0.68em;
  line-height: 1;
  font-weight: 400;
}

/* --- HYPHEN: inline `-` with a LONG red underline beneath, forming the
   proofreader's "two stacked bars" symbol. ---------------------------- */
.rm-hyphen {
  display: inline-block;
  color: var(--red);
  font-family: var(--hand);
  font-weight: 700;
  font-size: 1.1em;
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.7px;
  text-underline-offset: 4px;
  padding: 0 6px;            /* makes the underline noticeably longer */
  margin: 0 2px;
  line-height: 0.95;
}

/* --- EN / EM DASH: the actual – / — character drops INLINE in red at
   the insertion point, with the N / M tag FLOATING just above the
   dash — same convention the PDF uses. The tag sits in the lower
   third of the inter-line gap (about 0.7em above the baseline) — not
   as high as a full insertion (~1.4em), just clearly over the line so
   it reads as a proofreader annotation rather than a superscript
   letter glued to the character. */
.rm-endash, .rm-emdash {
  position: relative;             /* containing box for the floated tag */
  display: inline-block;
  color: var(--red);
  font-weight: 700;
  font-size: 1.1em;                /* enlarge the dash so it's clearly visible
                                      under the floated N/M tag */
  margin: 0 2px;
  line-height: 1;
  vertical-align: baseline;
}
.rm-endash::after, .rm-emdash::after {
  position: absolute;
  left: 50%;                       /* centered horizontally over the dash */
  bottom: 0.95em;                  /* lifted clear of the dash, but still
                                      sitting close to the line — not as
                                      high as a full insertion */
  transform: translateX(-50%);
  font-family: var(--hand);
  font-weight: 500;
  font-size: 0.7em;                /* readable, smaller than the dash */
  color: var(--red);
  line-height: 1;
  pointer-events: none;
  white-space: nowrap;
}
.rm-endash::after { content: "N"; }
.rm-emdash::after { content: "M"; }

/* --- INDENT: small red ⌐ at the start of the paragraph -------------- */
.rm-indent-mark {
  display: inline-block;
  position: relative;
  width: 0;
  vertical-align: baseline;
}
.rm-indent-mark::before {
  content: "⌐";
  position: absolute;
  left: 0;
  bottom: 0;
  color: var(--red);
  font-family: var(--hand);
  font-size: 1.2em;
  line-height: 1;
}

/* --- NO PARAGRAPH: "no¶" notation telling the writer to RUN ON, removing
   a paragraph break at this caret. Same anchor pattern as .rm-para. ---- */
.rm-no-para {
  position: relative;
  display: inline-block;
  width: 0;
  color: var(--red);
}
.rm-no-para::before {
  content: "no¶";
  position: absolute;
  left: 50%;
  top: -1.5em;
  transform: translateX(-50%);
  font-family: var(--hand);
  font-size: 1.1em;
  line-height: 1;
  white-space: nowrap;
}
.rm-no-para::after {
  content: "∧";
  position: absolute;
  left: 50%;
  bottom: -0.1em;
  transform: translateX(-50%);
  font-size: 0.8em;
  line-height: 1;
}

/* --- PARAGRAPH mark: ¶ pilcrow + caret ---------------------------------- */
.rm-para {
  position: relative;
  display: inline-block;
  width: 0;
  color: var(--red);
}
.rm-para::before {
  content: "¶";
  position: absolute;
  left: 50%;
  top: -1.4em;
  transform: translateX(-50%);
  font-family: var(--hand);
  font-size: 1.6em;
  line-height: 1;
}
.rm-para::after {
  content: "∧";
  position: absolute;
  left: 50%;
  bottom: -0.1em;
  transform: translateX(-50%);
  font-size: 0.8em;
  line-height: 1;
}

/* --- Floating action buttons -----------------------------------------
   Pen FAB lives at the TOP of the right column — above the proofreader
   marks palette. Review FAB lives in the bottom-right corner. Both are
   independently positioned (no shared cluster). */
.fab {
  position: fixed;
  width: 52px; height: 52px;
  border-radius: 50%;
  border: 1.5px solid var(--red);
  background: var(--paper);
  color: var(--red);
  cursor: pointer;
  box-shadow: var(--shadow-2);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 22;
  transition: transform var(--t-fast), background var(--t-fast),
              color var(--t-fast), box-shadow var(--t-fast);
}
.fab:hover { transform: translateY(-2px); box-shadow: 0 14px 36px rgba(28,26,23,0.16); }
.fab[hidden] { display: none; }
.fab svg { width: 24px; height: 24px; }

/* Pen FAB — fixed at the top-LEFT, 24px below the toolbar so the gap
   matches the rest of the left-edge margins. */
.fab-pen {
  top: calc(var(--tb-h) + 24px);
  left: 24px;
}
/* Memo FAB — mirror of fab-pen on the RIGHT edge. Single-click access
   to the Editorial memo pane (which slides in from the right). Hidden
   in Write mode — memo is editorial context, not for composition. */
.fab-memo {
  top: calc(var(--tb-h) + 24px);
  right: 24px;
  background: var(--paper);
  color: var(--red);
  border-color: var(--red);
}
.fab-memo:hover { background: var(--red-wash); }
.fab-memo svg { width: 22px; height: 22px; }
/* Hide while the memo pane itself is open to avoid the FAB sitting on
   top of the pane. (Previously also hidden in Write mode, but Author
   and Student roles do their writing in Write mode and still need the
   memo — "Notes" for authors, "Assignment" for students. The label
   swaps per role via JS.) */
body.memo-open .fab-memo,
body.style-guide-open .fab-memo,
body.assignment-info-open .fab-memo { display: none; }
/* Pen FAB icon — mode-toggle semantics (role-aware in JS).
   - In "view" mode (Read): show the pencil icon = "switch to edit"
   - In "edit" mode (Mark up OR Write): show the glasses icon = "switch to read"
   Background flips so the FAB reads as a state indicator at a glance.
   The JS handler picks Mark up vs Write based on the user's role. */
.pen-icon { display: none; }
body[data-mode="read"]  .fab-pen .pen-icon-read { display: inline-block; }
body[data-mode="mark"]  .fab-pen .pen-icon-mark { display: inline-block; }
body[data-mode="write"] .fab-pen .pen-icon-mark { display: inline-block; }
.fab-pen {
  /* Read mode = red bg + white pencil ("click to edit").
     Inherits `position: fixed` from the `.fab` base — do NOT override
     it here or the FAB falls into normal layout flow. */
  background: var(--red);
  color: var(--paper);
  border-color: var(--red);
}
body[data-mode="mark"] .fab-pen,
body[data-mode="write"] .fab-pen {
  /* Edit modes = paper bg + red glasses ("you're editing, click to return to read"). */
  background: var(--paper);
  color: var(--red);
  border-color: var(--red);
}

/* Review FAB — bottom-LEFT corner, only in mark mode. Oblong pill
   with the dark-pen + red-squiggle icon and the live edit counter
   inline. Hidden whenever the review panel is open. */
.fab-review {
  bottom: 24px;
  left: 24px;
  display: none;                /* hidden until mark mode */
  width: auto;
  height: 48px;
  min-width: 120px;
  padding: 0 20px 0 16px;
  gap: 10px;
  border-radius: 999px;          /* pill shape */
}
body[data-mode="mark"] .fab-review { display: inline-flex; }
body.review-open .fab-review { display: none; }
.fab-review .review-icon { width: 52px; height: 26px; }
.fab-counter {
  font-family: var(--mono);
  font-size: 13.5px;
  font-weight: 600;
  color: var(--red);
  line-height: 1;
  letter-spacing: 0.02em;
  /* No background — counter sits inside the pill alongside the icon. */
}
.fab-counter[hidden] { display: none; }

/* --- Blinking red caret marker — shows exactly where a click landed ---- */
#rm-caret-marker {
  position: fixed;
  width: 2px;
  background: var(--red);
  pointer-events: none;
  z-index: 25;
  border-radius: 1px;
  box-shadow: 0 0 8px rgba(194,54,45,0.45);
  display: none;
  animation: rm-caret-blink 1.0s steps(2, end) infinite;
}
#rm-caret-marker.is-visible { display: block; }
@keyframes rm-caret-blink { 50% { opacity: 0; } }

/* --- Review panel: compact card anchored to the bottom-right ----------
   Sizes itself to whatever the current edit needs. Bottom-anchored so the
   apply/discard buttons stay in the same spot while the card content
   expands upward. */
.review-panel {
  position: fixed;
  /* Anchored to the bottom-LEFT corner with the same 24px margin as
     the FAB lives in. The review FAB hides while the panel is open, so
     the panel takes its spot exactly. Width matches the EXPANDED mark
     palette (340px) so the two cards stack vertically with flush left
     and right edges — important for visual balance. */
  left: 24px;
  bottom: 24px;
  width: 340px;
  max-width: calc(100vw - 48px);
  max-height: calc(100vh - var(--tb-h) - 60px);
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  z-index: 19;
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  /* Grows from the bottom-LEFT corner (where the Review FAB lives). */
  transform-origin: 0% 100%;
  opacity: 0;
  pointer-events: none;
  transform: scale(0.08);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1),
              opacity   180ms ease;
}
.review-panel.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: scale(1);
}
.review-panel header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 14px 8px;
  border-bottom: 1px solid var(--hair);
}
.review-panel header h2 {
  margin: 0;
  font-size: 13.5px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink);
}
.review-counter {
  padding: 8px 14px 0;
  font-size: 12px;
  color: var(--ink-fade);
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
}
.review-counter strong { font-family: var(--mono); color: var(--ink); font-weight: 500; }
.review-body {
  /* No fixed height — let it size to the card content. Caps via
     max-height on the panel so very long cards still scroll. */
  overflow-y: auto;
  padding: 10px 14px 0;
}
.review-card {
  border: 1px solid var(--hair);
  border-radius: 10px;
  padding: 12px 14px;
  background: var(--paper-edge);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.review-card-type {
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--red);
}
.review-card-context {
  font-family: var(--serif);
  font-size: 15px;
  color: var(--ink);
  line-height: 1.4;
  border-left: 2px solid var(--hair-strong);
  padding-left: 10px;
}
.review-card-context mark {
  background: var(--red-wash);
  color: var(--red);
  padding: 0 2px;
  border-radius: 2px;
}
.review-card-detail {
  font-family: var(--hand);
  font-size: 18px;
  color: var(--red);
  line-height: 1.2;
}
.review-empty {
  color: var(--ink-fade);
  font-style: italic;
  font-family: var(--serif);
  font-size: 14px;
  padding: 20px 0;
  text-align: center;
}
/* Author chip near the top of the review panel — shows the current
   mark's author with a colored dot. Sits between the header and the
   counter so the eye picks it up before scanning the mark text. */
.review-author-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 14px 0;
  font-size: 12px;
  color: var(--ink);
  font-family: var(--sans);
}
.review-author-dot {
  display: inline-block;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: #6b6b6b;
  flex-shrink: 0;
}
.review-author-name {
  font-weight: 500;
  letter-spacing: -0.005em;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* Row of distinct-author orbs at the bottom of the review panel.
   Acts as a legend (each color → author + count) and a future filter
   handle. Hidden when there are no items so the panel doesn't show
   an empty band. */
.review-author-orbs {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  padding: 8px 14px 0;
  border-top: 1px dashed var(--hair);
  margin-top: 8px;
}
.review-author-orbs[data-empty="true"] { display: none; }
.review-author-orb {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 7px 3px 5px;
  border-radius: 999px;
  border: 1px solid var(--hair);
  background: var(--paper);
  cursor: pointer;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink);
  line-height: 1;
  transition: background 120ms ease, border-color 120ms ease, box-shadow 120ms ease;
}
.review-author-orb:hover { background: var(--paper-edge); }
.review-author-orb.is-selected {
  border-color: var(--ink);
  box-shadow: 0 0 0 2px var(--paper) inset, 0 1px 2px rgba(28,26,23,0.10);
}
.review-author-orb-dot {
  display: inline-block;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #6b6b6b;
  flex-shrink: 0;
}
.review-author-orb-count {
  font-family: var(--mono);
  color: var(--ink-fade);
  font-size: 10.5px;
}
/* Author name — hidden by default (max-width:0), slides out smoothly
   on hover or when the orb is selected. Keeps the review-panel orb
   row compact while still letting the user confirm who's who. */
.review-author-orb-name {
  display: inline-block;
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  margin: 0;
  opacity: 0;
  transition:
    max-width 240ms cubic-bezier(.2, .7, .3, 1),
    margin    240ms ease,
    opacity   200ms ease;
}
.review-author-orb:hover .review-author-orb-name,
.review-author-orb.is-selected .review-author-orb-name,
.review-author-orb:focus-visible .review-author-orb-name {
  /* Tightly capped — wider than ~160px and a long name would push the
     orb row past the panel edge. CSS truncates with ellipsis if needed. */
  max-width: 160px;
  margin: 0 4px 0 4px;
  opacity: 1;
  text-overflow: ellipsis;
}

.review-panel footer {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 6px;
  padding: 12px 14px;
  border-top: 1px solid var(--hair);
  margin-top: 12px;
}
.review-panel footer button { width: 100%; }
.review-panel footer .row-2 { grid-column: 1 / 3; display: flex; gap: 6px; }
.review-panel footer .row-2 button { flex: 1; }
/* One-line keyboard-shortcut crib under the footer buttons. Reads
   like a sentence so editors can absorb the walker keys at a glance. */
.review-keys-hint {
  grid-column: 1 / 3;
  text-align: center;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
  letter-spacing: 0.04em;
  padding: 4px 0 0;
  user-select: none;
}
/* The little letter chip on each footer button (Apply A, Discard R, etc.).
   Monospaced, pale, hugs the right edge of the button label. */
.review-panel footer kbd.rk {
  display: inline-block;
  margin-left: 6px;
  padding: 1px 5px;
  font-family: var(--mono);
  font-size: 10px;
  line-height: 1.3;
  color: var(--ink-fade);
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: 4px;
  vertical-align: 1px;
}

/* Pattern-collapse banner — sits above the current card when ≥3
   adjacent marks share the same type. Subtle, not loud — it's a
   shortcut affordance, not an alert. */
.review-pattern-banner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 6px 14px 0;
  padding: 8px 12px;
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-left: 3px solid var(--red);
  border-radius: 8px;
  font-size: 12px;
  color: var(--ink-2);
}
.review-pattern-banner[hidden] { display: none; }
.review-pattern-text strong {
  font-family: var(--mono);
  font-weight: 600;
  color: var(--ink);
  margin-right: 2px;
}
.review-pattern-actions {
  display: flex;
  gap: 6px;
  flex: 0 0 auto;
}
.review-pattern-actions button {
  font-size: 11.5px;
  padding: 4px 8px;
  white-space: nowrap;
}

/* Inline reply field (C key opens it on the current card). Lives
   inside .review-card so it's visually attached to the mark it
   replies to. */
.review-reply {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--hair);
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.review-reply-input {
  width: 100%;
  resize: vertical;
  min-height: 48px;
  padding: 6px 8px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  background: var(--paper);
}
.review-reply-input:focus {
  outline: none;
  border-color: var(--red);
}
.review-reply-row {
  display: flex;
  justify-content: flex-end;
  gap: 6px;
}
.review-reply-row button {
  font-size: 11.5px;
  padding: 4px 10px;
}

/* Threaded replies — sub-comments rendered under the parent mark's
   card. Visually indented and connected with a subtle left rail so
   the hierarchy is unambiguous. */
.review-thread {
  margin-top: 10px;
  padding-top: 8px;
  padding-left: 10px;
  border-left: 2px solid var(--hair);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.review-thread-reply {
  display: grid;
  grid-template-columns: 12px auto 1fr auto;
  column-gap: 6px;
  row-gap: 2px;
  align-items: center;
  font-size: 12.5px;
  color: var(--ink-2);
}
.review-thread-orb {
  width: 9px; height: 9px;
  border-radius: 50%;
  display: inline-block;
  align-self: center;
}
.review-thread-author {
  font-weight: 600;
  color: var(--ink);
}
.review-thread-time {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
  justify-self: end;
}
.review-thread-text {
  grid-column: 2 / 5;
  color: var(--ink);
  line-height: 1.45;
}

/* Triage UI — opens inside the card when the user accepts a
   commentary mark (awk/ww/wc/etc.) that has no built-in text
   mutation. Three actions: replace text, mark resolved, defer. */
.review-triage {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--hair);
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.review-triage-prompt {
  font-size: 12px;
  color: var(--ink-2);
  font-weight: 500;
}
.review-triage-input {
  width: 100%;
  resize: vertical;
  min-height: 48px;
  padding: 6px 8px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  font-family: var(--serif);
  font-size: 13.5px;
  color: var(--ink);
  background: var(--paper);
  line-height: 1.45;
}
.review-triage-input:focus {
  outline: none;
  border-color: var(--red);
}
.review-triage-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  justify-content: flex-end;
}
.review-triage-row button {
  font-size: 11.5px;
  padding: 4px 10px;
}
.review-triage-hint {
  font-size: 10.5px;
  color: var(--ink-fade);
  font-family: var(--mono);
  line-height: 1.5;
}

/* Deferred badge — small monospace pill at the bottom of a review
   card noting the mark has been set aside for later. */
.review-card-deferred {
  margin-top: 8px;
  display: inline-block;
  align-self: flex-start;
  padding: 2px 8px;
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.08em;
  color: var(--ink-fade);
  border: 1px dashed var(--hair-strong);
  border-radius: 4px;
}

/* Briefly highlight a block being reviewed */
.block.review-flash {
  animation: rm-review-flash 1.6s ease;
}
@keyframes rm-review-flash {
  0%, 100% { background: transparent; }
  20%, 60% { background: var(--highlight); }
}

/* --- Voice-note anchor marker (where TTS paused) ------------------------ */
.rm-anchor {
  display: inline-block;
  width: 0;
  position: relative;
}
.rm-anchor::before {
  content: "🎙";
  position: absolute;
  left: 50%;
  top: -1.1em;
  transform: translateX(-50%);
  font-size: 0.85em;
  filter: hue-rotate(-10deg) saturate(1.4);
  pointer-events: none;
}

/* --- Small "Remove" action that anchors to a clicked mark ------------ */
.mark-action {
  position: fixed;
  z-index: 35;
  background: var(--paper);
  border: 1px solid var(--red);
  border-radius: 999px;
  box-shadow: var(--shadow-2);
  padding: 2px;
  display: flex;
  gap: 2px;
}
.mark-action[hidden] { display: none; }
.mark-action-btn {
  appearance: none;
  border: none;
  background: transparent;
  color: var(--red);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: 999px;
  cursor: pointer;
}
.mark-action-btn:hover { background: var(--red); color: white; }

/* Clickable marks get a subtle hover affordance so the user knows */
body[data-mode="mark"] [data-mark-id] { cursor: pointer; }
body[data-mode="mark"] [data-mark-id]:hover { filter: brightness(0.9); }

/* --- Right-click context menu (same marks as palette, with labels) ----- */
.rm-ctx-menu {
  position: fixed;
  z-index: 40;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 6px;
  min-width: 220px;
  font-family: var(--sans);
  font-size: 13px;
  color: var(--ink);
  display: flex;
  flex-direction: column;
  gap: 1px;
  /* Long menus scroll within the available viewport */
  max-height: calc(100vh - 80px);
  overflow-y: auto;
  overscroll-behavior: contain;
}
.rm-ctx-menu[hidden] { display: none; }
.rm-ctx-section {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-fade);
  padding: 6px 10px 2px;
}
.rm-ctx-item {
  appearance: none;
  background: transparent;
  border: none;
  text-align: left;
  padding: 6px 10px;
  border-radius: 6px;
  cursor: pointer;
  color: var(--ink);
  font-family: inherit;
  font-size: inherit;
  display: grid;
  grid-template-columns: 22px 1fr;
  align-items: center;
  gap: 8px;
}
.rm-ctx-item:hover { background: var(--red-wash); color: var(--red); }
.rm-ctx-item .rm-ctx-glyph {
  font-family: var(--hand);
  color: var(--red);
  font-size: 16px;
  text-align: center;
  line-height: 1;
}
.rm-ctx-item:hover .rm-ctx-glyph { color: var(--red); }

/* (Removed standalone .palette-help — explanations are now inline in the
   palette itself via the "Expand" toggle.) */

/* --- Mark Palette (vertical toolbar, visible only in mark-up mode) ------ */
.mark-palette {
  position: fixed;
  /* Symmetric spacing: pen FAB is at top: tb-h + 24, height 52 → its
     bottom edge sits at tb-h + 76. Palette starts 24px below = tb-h + 100. */
  top: calc(var(--tb-h) + 100px);
  /* Palette default bottom clears the Review FAB (48 tall + 24 margin
     below) plus a 24px gap so it doesn't tuck under the FAB. */
  bottom: 96px;
  width: 56px;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 0 6px 6px;
  z-index: 15;
  font-family: var(--sans);
  /* Hairline scrollbar comes from the global rule near the top of the
     file (body + *::-webkit-scrollbar). */
  overflow-y: auto;
  /* Smooth slide + grow when expanding/collapsing: left, width, opacity
     all animate together so one palette slides over the other cleanly. */
  transition: bottom 220ms cubic-bezier(.2,.7,.3,1),
              top    220ms cubic-bezier(.2,.7,.3,1),
              left   240ms cubic-bezier(.2,.7,.3,1),
              width  240ms cubic-bezier(.2,.7,.3,1),
              opacity 200ms ease,
              visibility 0s 240ms;
}
/* (palette scrollbar inherits the global 2px hairline rule near the
   top of the file) */
/* TWO-panel layout: Panel B (Punctuation + Spacing) on the far left,
   Panel A (Editorial + Typography) just to the right of it. */
#mark-palette-b { left: 24px; }
#mark-palette   { left: 88px; }
/* Whichever panel is expanded slides to left:24 (taking the far-left
   column) and grows to 320 wide. Panel A literally slides left over
   Panel B; Panel B just grows in place. */
#mark-palette.is-expanded,
#mark-palette-b.is-expanded {
  left: 24px;
}
/* Only one panel may be expanded at a time. When one is, the other
   fades out smoothly during the slide. The collapsed one's
   transition starts at the same time as the expanding one's. */
body.palette-a-expanded #mark-palette-b,
body.palette-b-expanded #mark-palette {
  visibility: hidden;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease, visibility 0s 220ms;
}
/* When the review panel is open, the palette retracts up to leave a
   uniform 16px gap above the panel. The actual `bottom` value is set
   from JS (syncPaletteToReview) after measuring the panel, since the
   panel's height depends on which mark is being reviewed. */
body.review-open .mark-palette { bottom: 360px; }
/* Very short viewports can't fit both — hide the palette while the
   panel is open. */
@media (max-height: 520px) {
  body.review-open .mark-palette { display: none; }
}
.mark-palette[hidden] { display: none; }
/* Lock the body text 24px to the right of the EXPANDED palette so the
   text position is identical whether the palette is collapsed/expanded
   AND whether the user is in read or mark mode — switching between
   modes never bumps the prose around.
   388px = 24 (page margin) + 340 (expanded palette width) + 24 (gap). */
.canvas {
  padding-left: 388px;
  padding-right: clamp(20px, 4vw, 64px);
}

/* (Spread-view 2-page CSS removed — couldn't deliver an editor-grade
   side-by-side layout with margin notes in the available column space.
   The PDF export retains the polished single-page proof.) */

/* Paper grain — always on. A subtle (~4% opacity) SVG fractal-noise
   tile multiplied over the cream canvas so the screen reads as paper
   instead of flat pixels. Zero network cost (inline data URI), one-shot
   rasterization that the browser caches. */
.canvas {
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 200 200' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 0.12  0 0 0 0 0.10  0 0 0 0 0.08  0 0 0 0.045 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  background-repeat: repeat;
  background-blend-mode: multiply;
}

.pal-divider {
  width: 26px;
  height: 1px;
  background: var(--hair);
  margin: 4px auto;
}
/* (See .pal-rule sticky rules further down — it's both visual divider
   and a pin so the marks scroll under the Expand button.) */
/* Section header — only visible when palette is expanded. */
.pal-section {
  display: none;
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-fade);
  padding: 8px 10px 2px;
}
.mark-palette.is-expanded .pal-section { display: block; }

.pal-btn {
  appearance: none;
  border: 1px solid transparent;
  background: transparent;
  border-radius: 8px;
  cursor: pointer;
  font-family: var(--sans);
  color: var(--ink-soft);
  transition: background var(--t-fast), border-color var(--t-fast);
  position: relative;
}
.pal-btn:hover { background: var(--red-wash); color: var(--red); border-color: var(--red); }
.pal-btn.is-active {
  background: var(--red);
  color: white;
  border-color: var(--red);
}

/* COLLAPSED palette (default): symbols only, narrow column, red glyphs. */
.mark-palette:not(.is-expanded) .pal-btn {
  width: 44px;
  height: 38px;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2px;
}
.mark-palette:not(.is-expanded) .pal-name,
.mark-palette:not(.is-expanded) .pal-desc {
  display: none;
}
.mark-palette:not(.is-expanded) .pal-btn .pal-glyph {
  font-family: var(--hand);
  font-size: 22px;
  line-height: 1;
  color: var(--red);
}
/* Multi-character / styled glyphs render smaller so they fit in the
   collapsed 44px button. Each gets the proofreader's notation:
   italic mark = "ital" in italic; bold = "~b"; underline = "u" with
   a red underline. */
.mark-palette:not(.is-expanded) .pal-btn[data-mark="italic"] .pal-glyph {
  font-size: 13px;
  font-style: italic;
}
.mark-palette:not(.is-expanded) .pal-btn[data-mark="bold"] .pal-glyph {
  font-size: 15px;
  font-weight: 500;
}
.mark-palette:not(.is-expanded) .pal-btn[data-mark="underline"] .pal-glyph {
  font-size: 16px;
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
}
/* Margin-note pencil (✎) — mirror horizontally so the writing tip
   points down-LEFT toward the page text (matches a right-handed
   editor's natural grip and the review-FAB nib direction). Applies in
   both collapsed and expanded palette, and in the right-click menu. */
.mark-palette .pal-btn[data-mark="margin"] .pal-glyph,
.rm-ctx-item[data-mark="margin"] .rm-ctx-glyph {
  display: inline-block;
  transform: scaleX(-1);
}
/* Bookmark palette glyph — inline SVG ribbon. Sized to match the
   ~22px hand-letter glyphs visually. Same red. */
.mark-palette .pal-btn[data-mark="bookmark"] .pal-glyph svg,
.rm-ctx-item[data-mark="bookmark"] .rm-ctx-glyph svg {
  display: inline-block;
  vertical-align: middle;
  color: var(--red);
}
.mark-palette:not(.is-expanded) .pal-btn[data-mark="bookmark"] .pal-glyph {
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* Write-palette Link button — the ⌘k glyph reads heavy at the default
   22px palette glyph size. Shrink so the ⌘ symbol matches the visual
   weight of the other write-palette letters. */
.mark-palette:not(.is-expanded) .pal-btn[data-write="link"] .pal-glyph {
  font-size: 14px;
  font-family: var(--mono);
  letter-spacing: -0.02em;
}
/* Delete: "Del" with a red strikethrough — clearly distinct from the
   indent `⌐` symbol that previously collided. */
.mark-palette .pal-btn[data-mark="del"] .pal-glyph,
.rm-ctx-item[data-mark="del"] .rm-ctx-glyph {
  font-family: var(--sans);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0.03em;
  text-decoration: line-through var(--red);
  text-decoration-thickness: 1.8px;
  color: var(--red);
}

/* Hyphen / en-dash / em-dash palette + right-click glyphs — must MATCH
   the inline body rendering so what the user picks looks like what
   will appear on the page. Same family (handwriting), same red, same
   underline (hyphen) or superscript N / M (en/em). */
.mark-palette .pal-btn[data-mark="hyphen"] .pal-glyph,
.rm-ctx-item[data-mark="hyphen"] .rm-ctx-glyph {
  display: inline-block;
  font-family: var(--hand);
  font-weight: 700;
  color: var(--red);
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.7px;
  text-underline-offset: 4px;
  padding: 0 4px;
  line-height: 0.95;
}
/* En/em dash palette + right-click glyphs match the live editor: the
   dash itself sits inline at body weight, and the N or M tag floats
   centered just above the dash — same convention the PDF uses. The
   palette button is small (44×44 collapsed), so we lift the tag a
   touch less than the body version uses. */
.mark-palette .pal-btn[data-mark="ensp"] .pal-glyph,
.mark-palette .pal-btn[data-mark="dash"] .pal-glyph,
.rm-ctx-item[data-mark="ensp"] .rm-ctx-glyph,
.rm-ctx-item[data-mark="dash"] .rm-ctx-glyph {
  position: relative;             /* containing box for the floated tag */
  display: inline-block;
  color: var(--red);
  font-weight: 700;
  font-size: 1.1em;
  line-height: 1;
  vertical-align: baseline;
}
.mark-palette .pal-btn[data-mark="ensp"] .pal-glyph::after,
.mark-palette .pal-btn[data-mark="dash"] .pal-glyph::after,
.rm-ctx-item[data-mark="ensp"] .rm-ctx-glyph::after,
.rm-ctx-item[data-mark="dash"] .rm-ctx-glyph::after {
  position: absolute;
  left: 50%;
  bottom: 0.85em;                  /* float just above the inline dash */
  transform: translateX(-50%);
  font-family: var(--hand);
  font-weight: 500;
  font-size: 0.65em;
  color: var(--red);
  line-height: 1;
  pointer-events: none;
  white-space: nowrap;
}
.mark-palette .pal-btn[data-mark="ensp"] .pal-glyph::after,
.rm-ctx-item[data-mark="ensp"] .rm-ctx-glyph::after { content: "N"; }
.mark-palette .pal-btn[data-mark="dash"] .pal-glyph::after,
.rm-ctx-item[data-mark="dash"] .rm-ctx-glyph::after { content: "M"; }

/* Right-click italic/bold/underline glyphs use the SAME notation as the
   palette so what the user picks visually matches what they'll see on
   the page: italic = "ital" in italic, bold = "~b", underline = "u"
   with a red underline. */
.rm-ctx-item[data-mark="italic"] .rm-ctx-glyph {
  font-family: var(--hand);
  font-style: italic;
  font-weight: 500;
  color: var(--red);
}
.rm-ctx-item[data-mark="bold"] .rm-ctx-glyph {
  font-family: var(--hand);
  font-weight: 500;
  color: var(--red);
}
.rm-ctx-item[data-mark="underline"] .rm-ctx-glyph,
.mark-palette .pal-btn[data-mark="underline"] .pal-glyph {
  text-decoration: underline var(--red);
  text-decoration-thickness: 1.5px;
  text-underline-offset: 2px;
  font-family: var(--hand);
  color: var(--red);
}
.mark-palette:not(.is-expanded) .pal-btn:hover .pal-glyph { color: var(--red); }
.mark-palette:not(.is-expanded) .pal-btn.is-active .pal-glyph { color: white; }

/* EXPANDED palette: glyph (col 1, both rows) + name (col 2 row 1) +
   shortcut (col 3 row 1, right-justified) + description (cols 2-3
   row 2). */
.mark-palette.is-expanded {
  width: 340px;
}
.mark-palette.is-expanded .pal-btn {
  display: grid;
  grid-template-columns: 36px 1fr auto;
  grid-template-rows: auto auto;
  align-items: start;
  column-gap: 10px;
  row-gap: 2px;
  text-align: left;
  padding: 10px 12px;
  width: 100%;
}
.mark-palette.is-expanded .pal-btn[data-shortcut]::after {
  content: attr(data-shortcut);
  grid-column: 3;
  grid-row: 1;
  align-self: start;
  justify-self: end;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
  letter-spacing: 0.02em;
  margin-top: 1px;
  white-space: nowrap;
}
.mark-palette.is-expanded .pal-btn .pal-glyph {
  grid-column: 1;
  grid-row: 1 / span 2;
  align-self: center;
  font-family: var(--hand);
  font-size: 24px;
  line-height: 1;
  color: var(--red);
  text-align: center;
}
.mark-palette.is-expanded .pal-btn:hover .pal-glyph { color: var(--red); }
.mark-palette.is-expanded .pal-btn.is-active .pal-glyph { color: white; }
.pal-name {
  display: block;
  grid-column: 2;
  grid-row: 1;
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  line-height: 1.25;
}
.mark-palette.is-expanded .pal-btn:hover .pal-name { color: var(--red); }
.mark-palette.is-expanded .pal-btn.is-active .pal-name { color: white; }
.pal-desc {
  display: block;
  grid-column: 2 / 4;            /* span name + shortcut columns */
  grid-row: 2;
  font-family: var(--serif);
  font-size: 11.5px;
  color: var(--ink-soft);
  line-height: 1.35;
  margin-top: 2px;
}
.mark-palette.is-expanded .pal-btn.is-active .pal-desc { color: rgba(255,255,255,0.85); }
/* Section headers span the full width — they're not grid items themselves. */
.mark-palette.is-expanded .pal-section { padding: 12px 14px 4px; }
/* The Expand toggle uses a black, standard sans chevron — visually
   distinct from the red handwritten proofreader glyphs below it. */
.pal-expand {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 8px 12px;
  width: 100%;
  background: var(--paper);
}
.pal-expand:hover { background: var(--paper-edge); color: var(--ink); border-color: transparent; }
.pal-expand-chevron {
  font-family: var(--sans);
  font-weight: 500;
  color: var(--ink);
  font-size: 18px;
  line-height: 1;
}
.pal-expand-title {
  font-family: var(--sans);
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  letter-spacing: -0.01em;
  display: none;
}
/* Collapsed: chevron only, centered. Expanded: title + chevron pushed
   to the right with space-between. */
.mark-palette.is-expanded .pal-expand {
  justify-content: space-between;
  padding: 12px 14px;
}
.mark-palette.is-expanded .pal-expand-title { display: block; }
/* Make sure the expand button itself never inherits the grid layout
   that the regular .pal-btn uses in expanded mode. */
.mark-palette.is-expanded .pal-expand {
  display: flex !important;
  grid-template-columns: none !important;
}

/* Tooltip on hover (collapsed only — expanded already shows the description) */
.mark-palette:not(.is-expanded) .pal-btn[data-tip]::after {
  content: attr(data-tip);
  position: absolute;
  right: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  background: var(--ink);
  color: var(--paper);
  padding: 4px 8px;
  font-size: 11px;
  font-family: var(--sans);
  border-radius: 4px;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.18s 0.4s;
  z-index: 50;
}
.mark-palette:not(.is-expanded) .pal-btn:hover[data-tip]::after { opacity: 1; }

/* The Expand button stays pinned to the top of the palette while the
   marks below scroll. */
.pal-expand {
  position: sticky;
  top: 0;
  z-index: 3;
  background: var(--paper);
  border-bottom: 1px solid var(--hair);
  border-radius: 14px 14px 0 0;
}
/* The divider directly under it — pinned just below, so the marks scroll
   underneath both the button and the rule. */
.pal-rule {
  position: sticky;
  top: 38px;
  z-index: 2;
  height: 1px;
  background: var(--hair-strong);
  margin: 0 6px;
}
.mark-palette.is-expanded .pal-expand { top: 0; }
.mark-palette.is-expanded .pal-rule   { top: 50px; }

/* Expanded palette is allowed to overlay the prose — DO NOT shift the
   canvas. The page text stays exactly where it was. */

/* Sidebar gutter "+" button — kept for adding margin notes by hand */
.gutter-add-note {
  position: absolute;
  right: -28px; top: 4px;
  width: 22px; height: 22px;
  border-radius: 50%;
  border: 1px dashed var(--red-soft);
  color: var(--red);
  background: transparent;
  font-family: var(--sans);
  font-size: 14px;
  line-height: 18px;
  text-align: center;
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast), background var(--t-fast);
}
body[data-mode="mark"] .prose .block:hover .gutter-add-note { opacity: 0.7; }
.gutter-add-note:hover { background: var(--red); color: white; opacity: 1 !important; }

/* Legacy inline margin note (now hidden — notes live in the right
   column `#margin-notes` instead). Kept as a non-display fallback in
   case some older save state still injects them. */
.rm-margin { display: none; }
.rm-margin-legacy {
  display: block;
  font-family: var(--hand);
  color: var(--red);
  font-size: 1.18em;
  line-height: 1.35;
  margin: 4px 0 8px 28px;
  padding: 2px 8px 2px 10px;
  border-left: 2px solid var(--red);
  position: relative;
}
.rm-margin .rm-mic {
  position: absolute;
  left: -22px; top: 4px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--red);
  opacity: 0.7;
}
.rm-margin .rm-margin-arrow {
  position: absolute;
  left: -18px;
  top: -10px;
  color: var(--red);
  font-size: 14px;
  opacity: 0.7;
}
.rm-margin .rm-x {
  float: right;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--red);
  opacity: 0;
  padding: 0 4px;
  transition: opacity var(--t-fast);
}
.rm-margin:hover .rm-x { opacity: 0.8; }

/* Currently-being-spoken paragraph */
.is-speaking {
  background: var(--highlight);
  border-radius: 4px;
  transition: background var(--t-fast);
  padding-left: 6px;
  margin-left: -6px;
  box-shadow: -4px 0 0 var(--highlight);
}

/* =========================================================================
   Voice annotation bubble
   ========================================================================= */

.voice-bubble {
  position: fixed;
  bottom: 56px;
  left: 50%;
  transform: translateX(-50%);
  width: min(560px, 92vw);
  background: var(--paper);
  border: 1px solid var(--red);
  border-radius: 14px;
  box-shadow: var(--shadow-2);
  padding: 14px 16px 12px;
  z-index: 20;
  font-family: var(--sans);
}
.voice-bubble[hidden] { display: none; }
.vb-head {
  display: flex; align-items: center; gap: 8px;
  font-size: 12.5px;
  color: var(--ink-soft);
  margin-bottom: 6px;
}
.vb-dot {
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--red);
  animation: pulse 1.2s infinite;
}
.vb-hint { color: var(--ink-fade); margin-left: auto; font-size: 11.5px; }
.vb-text {
  font-family: var(--hand);
  font-size: 22px;
  line-height: 1.3;
  color: var(--red);
  min-height: 1.3em;
  padding: 6px 4px 10px;
  border-bottom: 1px dashed var(--hair-strong);
  white-space: pre-wrap;
  word-break: break-word;
}
.vb-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 10px;
}

/* =========================================================================
   Status bar
   ========================================================================= */

.status-bar {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 18px;
  border-top: 1px solid var(--hair);
  background: var(--paper);
  font-family: var(--sans);
  font-size: 11.5px;
  color: var(--ink-fade);
  /* Quiet chrome: fade out after a few seconds of inactivity.
     Any mousemove / keydown / scroll restores it (see app.js). */
  opacity: 1;
  transition: opacity 380ms ease;
}
.status-bar:hover,
body.chrome-active .status-bar {
  opacity: 1;
}
body.chrome-idle .status-bar {
  opacity: 0;
  pointer-events: none;
}
.status-bar .dot { color: var(--hair-strong); }
.status-bar .grow { flex: 1; }
#status-tts.is-playing { color: var(--red); }
#status-autosave {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-fade);
  font-style: normal;
}
#status-autosave:empty { display: none; }
#status-autosave:empty + .dot { display: none; }
#status-autosave.is-error { color: var(--red); }

kbd {
  font-family: var(--mono);
  font-size: 10.5px;
  background: var(--paper-edge);
  border: 1px solid var(--hair-strong);
  border-radius: 3px;
  padding: 1px 5px;
}

/* =========================================================================
   Empty state
   ========================================================================= */

.empty-state {
  text-align: center;
  padding: 80px 20px;
  color: var(--ink-fade);
  font-family: var(--serif);
  font-style: italic;
  font-size: 17px;
}

/* Print: clean reader view with edits preserved */
@media print {
  .sidebar, .toolbar, .status-bar, .voice-bubble { display: none !important; }
  body { grid-template-columns: 1fr; }
  .canvas { overflow: visible; padding: 0 20px; }
  .prose { max-width: 100%; }
}

/* Small screens: collapse sidebar */
@media (max-width: 820px) {
  body { grid-template-columns: 0 1fr; }
  .sidebar { transform: translateX(-100%); }
  body.sidebar-open { grid-template-columns: 240px 1fr; }
  body.sidebar-open .sidebar { transform: translateX(0); }
  .tts .rate { display: none; }
  .canvas { padding: 36px 22px 200px; }
}

/* =========================================================================
   Profile chip + modal — author identity for tracked-change exports
   ========================================================================= */

.profile-chip {
  appearance: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Match the toolbar bubble size (icon-btn = 32×32 circle). */
  width: 32px;
  height: 32px;
  padding: 0;
  border: 1px solid var(--hair-strong);
  border-radius: 50%;
  background: var(--paper);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  cursor: pointer;
  transition: border-color 120ms ease, color 120ms ease, background 120ms ease;
}
.profile-chip:hover {
  border-color: var(--red);
  color: var(--red);
}
.profile-chip.is-unset {
  color: var(--ink-fade);
  border-style: dashed;
}

/* --- Profile dropdown menu ------------------------------------------------
   Anchored beneath the profile chip. Tiny, two-line entries with a glyph
   on the left. Opens via chip click; closes on outside click or Esc. */
.profile-wrap { position: relative; }
.profile-menu {
  position: absolute;
  top: calc(100% + 6px);
  right: 0;
  z-index: 100;
  min-width: 220px;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: var(--shadow-2);
  padding: 6px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  font-family: var(--sans);
}
.profile-menu[hidden] { display: none; }
.profile-menu-item {
  appearance: none;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 10px;
  background: transparent;
  border: 0;
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  color: var(--ink);
  font-family: inherit;
  font-size: 13px;
}
.profile-menu-item:hover { background: var(--paper-edge); }
/* Locked state — used by the Provenance toggle when a recording can't
   be stopped (assignment doc, or session started on the current doc).
   Faded + cursor change + no hover background so it reads as inactive,
   but the red dot glyph still pulses so the student knows recording
   is genuinely on. */
.profile-menu-item.is-locked,
.profile-menu-item:disabled {
  opacity: 0.55;
  cursor: not-allowed;
}
.profile-menu-item.is-locked:hover,
.profile-menu-item:disabled:hover { background: transparent; }
.profile-menu-item .pm-glyph {
  font-size: 16px;
  color: var(--red);
  width: 20px;
  text-align: center;
  flex-shrink: 0;
}
.profile-menu-item .pm-label {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.profile-menu-item .pm-label-main { font-weight: 500; }
.profile-menu-item .pm-label-sub  { font-size: 11px; color: var(--ink-fade); }

/* DEV-only quick role switcher inside the profile menu. Sandwiched by
   a faint top + bottom border so it visually separates from regular
   menu items, with a small "DEV · switch role" label on top.
   display:flex column so the dev menu items stretch full-width to
   match the rest of the menu — without this they shrink to content
   width because the parent isn't a flex container. */
.profile-menu-dev-block {
  margin: 4px 0;
  padding: 4px 0;
  border-top: 1px dashed var(--hair);
  border-bottom: 1px dashed var(--hair);
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.profile-menu-section-label {
  padding: 6px 12px 2px;
  font-size: 9.5px;
  letter-spacing: 0.08em;
  font-weight: 600;
  color: var(--accent, #2b4a6f);
  text-transform: uppercase;
  font-family: var(--sans);
}
.profile-menu-item-dev .pm-label-main { font-weight: 500; font-size: 13px; }
.profile-menu-item-dev .pm-label-sub  { font-size: 10.5px; }
.profile-menu-item-dev.is-active {
  background: var(--paper-edge);
}
.profile-menu-item-dev.is-active .pm-label-main {
  color: var(--red);
}

/* --- Hidden palette items ------------------------------------------------- */
/* When a user toggles a built-in mark off in Customizations, we add this
   class to its palette button AND its right-click menu item. */
.rm-pal-hidden { display: none !important; }

/* --- Settings drawer ------------------------------------------------------
   Slides in from the right edge. Holds palette customization (Marks tab)
   and the custom-mark creation form (Add tab). */
.settings-panel {
  position: fixed;
  top: var(--tb-h);
  right: 0;
  bottom: 0;
  width: 460px;
  max-width: 100vw;
  z-index: 60;
  background: var(--paper);
  border-left: 1px solid var(--hair-strong);
  box-shadow: -2px 0 12px rgba(28,26,23,0.06);
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1);
}
.settings-panel[hidden] {
  display: flex;             /* keep flex layout so transform plays */
  transform: translateX(100%);
  pointer-events: none;
}
.settings-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.settings-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-2);
  flex: 0 0 auto;
}
.settings-tabs {
  display: flex;
  gap: 4px;
  flex: 1;
  margin-left: 8px;
}
.settings-tab {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 4px 10px;
  font-family: inherit;
  font-size: 12px;
  color: var(--ink-fade);
  cursor: pointer;
  border-bottom: 2px solid transparent;
}
.settings-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--red);
}
.settings-tab-panel {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px 16px;
}
.settings-tab-panel[hidden] { display: none; }
.settings-hint {
  margin: 0 0 12px;
  font-size: 12px;
  color: var(--ink-fade);
  line-height: 1.5;
}
.settings-section {
  margin: 14px 0 4px;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.settings-section:first-child { margin-top: 0; }
.settings-rows {
  list-style: none;
  margin: 0;
  padding: 0;
}
.settings-row {
  display: grid;
  /* handle · toggle · glyph · label · autonote · delete */
  grid-template-columns: 18px 36px 32px auto 1fr auto;
  align-items: center;
  gap: 10px;
  padding: 8px 4px;
  border-radius: 6px;
  border-bottom: 1px solid var(--hair);
}
.settings-row:last-child { border-bottom: 0; }
.settings-row.is-dragging { opacity: 0.4; }
.settings-row.is-hidden .settings-glyph,
.settings-row.is-hidden .settings-label,
.settings-row.is-hidden .settings-autonote { opacity: 0.4; }

/* Drag handle — six-dot grip glyph, sized for visibility and tinted
   toward the ink color so it reads at a glance. Hover bumps it to red
   so it's clear it's interactive. */
.settings-handle {
  cursor: grab;
  color: var(--ink-2);
  user-select: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.7;
  transition: color 120ms ease, opacity 120ms ease;
}
.settings-handle:hover { color: var(--red); opacity: 1; }
.settings-handle:active { cursor: grabbing; }

/* Visibility toggle — slider switch (iOS-style pill). Track is muted
   when off, red when on. Thumb glides left↔right. */
.settings-vis {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 0;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
}
.settings-vis-track {
  position: relative;
  display: inline-block;
  width: 30px;
  height: 16px;
  border-radius: 999px;
  background: var(--hair-strong);
  transition: background 160ms ease;
}
.settings-vis-thumb {
  position: absolute;
  top: 2px;
  left: 2px;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(0,0,0,0.25);
  transition: transform 160ms cubic-bezier(.2,.7,.3,1);
}
.settings-vis[aria-pressed="true"] .settings-vis-track { background: var(--red); }
.settings-vis[aria-pressed="true"] .settings-vis-thumb { transform: translateX(14px); }
.settings-glyph {
  font-family: var(--hand);
  font-size: 18px;
  color: var(--red);
  text-align: center;
}
.settings-label {
  font-size: 13px;
  color: var(--ink);
}
.settings-autonote {
  grid-column: 1 / -1;
  margin-top: 4px;
  width: 100%;
  padding: 6px 8px;
  border: 1px solid var(--hair);
  border-radius: 5px;
  font-family: var(--sans);
  font-size: 12px;
  background: var(--paper);
  color: var(--ink);
}
.settings-autonote:focus {
  outline: none;
  border-color: var(--red);
}
.settings-delete {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--ink-fade);
  font-size: 14px;
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.settings-delete:hover { color: var(--red); background: var(--paper-edge); }
.settings-footer-row {
  margin-top: 16px;
  padding-top: 12px;
  border-top: 1px solid var(--hair);
}

/* --- Add custom mark form ------------------------------------------------- */
.settings-add-form {
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.settings-field {
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
  color: var(--ink-2);
}
.settings-field > span {
  font-size: 11.5px;
  color: var(--ink-fade);
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.settings-field > span small {
  text-transform: none;
  letter-spacing: 0;
  font-size: 11px;
  color: var(--ink-fade);
  margin-left: 4px;
}
.settings-field input,
.settings-field select,
.settings-field textarea {
  appearance: none;
  width: 100%;
  padding: 7px 9px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 13px;
  background: var(--paper);
  color: var(--ink);
}
.settings-field input:focus,
.settings-field select:focus,
.settings-field textarea:focus {
  outline: none;
  border-color: var(--red);
}
.settings-add-actions {
  display: flex;
  justify-content: flex-end;
  margin-top: 4px;
}

/* Add-custom-mark disclosure — collapsed by default at the bottom of
   the marks list; expands to show the form inline. */
.settings-add-disclosure {
  margin-top: 14px;
  padding: 8px 4px;
  border-top: 1px solid var(--hair);
}
.settings-add-trigger {
  cursor: pointer;
  padding: 6px 8px;
  border-radius: 6px;
  font-size: 12.5px;
  color: var(--ink-2);
  font-weight: 500;
  list-style: none;
  user-select: none;
}
.settings-add-trigger::-webkit-details-marker { display: none; }
.settings-add-trigger:hover { background: var(--paper-edge); color: var(--red); }
.settings-add-disclosure[open] .settings-add-trigger {
  color: var(--red);
}

/* Preference row — label on the left, control on the right. Used for
   the theme picker and the PDF page-size dropdown. */
.settings-pref-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 8px 4px;
  border-bottom: 1px solid var(--hair);
}
.settings-pref-row:last-child { border-bottom: 0; }
/* Stack variant — used by sliders where the label needs to sit above
   the full-width input instead of beside it. */
.settings-pref-row-stack {
  flex-direction: column;
  align-items: stretch;
}
.settings-pref-row-stack .settings-label {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}
.settings-pref-meta {
  font-weight: 400;
  font-size: 12px;
  color: var(--ink-fade);
  font-variant-numeric: tabular-nums;
}
.settings-pref-slider {
  width: 100%;
  margin: 6px 0 2px;
  accent-color: var(--red);
}
.settings-pref-select {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  padding: 5px 10px;
  font-family: var(--sans);
  font-size: 12.5px;
  color: var(--ink);
  cursor: pointer;
}

/* Three-button theme picker (Light / Dark / Auto). */
.settings-theme-picker {
  display: inline-flex;
  background: var(--paper-edge);
  border: 1px solid var(--hair-strong);
  border-radius: 999px;
  padding: 2px;
  gap: 2px;
}
.settings-theme-opt {
  appearance: none;
  background: transparent;
  border: 0;
  padding: 4px 12px;
  font-family: var(--sans);
  font-size: 12px;
  color: var(--ink-2);
  cursor: pointer;
  border-radius: 999px;
}
.settings-theme-opt:hover { color: var(--ink); }
.settings-theme-opt.is-active {
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 1px 2px rgba(28,26,23,0.06);
}

/* Feature toggle: TTS visibility — hide the toolbar TTS cluster when
   the user has unchecked it in User Preferences. */
/* Hide the toolbar TTS bubble + its dropdown panel when the user
   has turned off "Text to Speech" in Customizations (or it's the
   default-off state for student/teacher roles). The wrapper is
   .tts-wrap; the trigger button + dropdown both live inside it. */
body.feature-tts-off .tts-wrap { display: none !important; }

/* Setup tab — role presets stacked vertically. Each preset shows its
   distinguishing features so the user understands what they're picking,
   not just a label. */
.settings-role-presets {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 16px;
}
.settings-role-preset {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  padding: 10px 12px;
  text-align: left;
  font-family: var(--sans);
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
  transition: border-color 120ms ease, background 120ms ease;
}
.settings-role-preset[hidden] { display: none !important; }
.settings-role-preset:hover { border-color: var(--ink-2); }
.settings-role-preset.is-active {
  border-color: var(--red);
  background: var(--red-wash);
}
.settings-role-head {
  display: flex;
  align-items: center;
  gap: 10px;
}
.settings-role-glyph {
  font-size: 16px;
  width: 24px;
  text-align: center;
  flex-shrink: 0;
  color: var(--red);
}
.settings-role-name {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
  flex: 1;
}
.settings-role-tabs {
  font-size: 10.5px;
  color: var(--ink-fade);
  font-family: var(--mono);
  letter-spacing: 0.04em;
  flex-shrink: 0;
}
.settings-role-desc {
  font-size: 11.5px;
  color: var(--ink-2);
  line-height: 1.45;
  padding-left: 34px;     /* align with name, past the glyph column */
}
.settings-role-desc strong { color: var(--ink); font-weight: 600; }

.settings-tab-toggles {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.settings-tab-toggle-row {
  display: grid;
  grid-template-columns: 36px auto 1fr;
  align-items: center;
  gap: 10px;
  padding: 6px 4px;
  border-bottom: 1px solid var(--hair);
}
.settings-tab-toggle-row:last-child { border-bottom: 0; }
.settings-tab-toggle-row .settings-label {
  font-size: 13px;
  font-weight: 500;
}
.settings-tab-desc {
  font-size: 11.5px;
  color: var(--ink-fade);
}

/* =========================================================================
   Teacher Provenance Dashboard — role-gated, login-gated slide-in panel
   ========================================================================= */
.teacher-dashboard,
.student-dashboard {
  position: fixed;
  top: var(--tb-h);
  right: 0;
  bottom: 0;
  width: 560px;
  max-width: 100vw;
  z-index: 65;
  background: var(--paper);
  border-left: 1px solid var(--hair-strong);
  box-shadow: -2px 0 12px rgba(28,26,23,0.06);
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1);
}
.teacher-dashboard[hidden],
.student-dashboard[hidden] {
  display: flex;
  transform: translateX(100%);
  pointer-events: none;
}
/* Student dashboard reuses the teacher header chrome via a parallel
   selector. Header layout is shared, so we just match the structure. */
.student-dashboard-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.student-dashboard-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  flex: 1;
}
.student-header-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}
.student-header-actions .primary-btn { padding: 6px 12px; font-size: 12px; }
.student-dashboard-content {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px;
}
.teacher-dashboard-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.teacher-dashboard-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-2);
  flex: 1;
}
.teacher-login-gate {
  flex: 1;
  overflow-y: auto;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 30px 16px;
}
.teacher-login-card {
  max-width: 380px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.teacher-login-card h3 {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
}
.teacher-dashboard-content {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px 16px;
}

/* ── Pending / rejected teacher status page ───────────────────────── */
.teacher-pending-view {
  flex: 1;
  overflow-y: auto;
  padding: 24px 16px;
  display: flex;
  justify-content: center;
}
.teacher-pending-card {
  max-width: 540px;
  width: 100%;
  background: #fff;
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
  border-radius: 12px;
  padding: 28px 32px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.04);
}
.teacher-pending-card-rejected {
  border-color: rgba(184, 80, 80, 0.25);
  background: #fff8f6;
}
.teacher-pending-eyebrow {
  font-size: 11px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-fade, #8a8580);
  font-weight: 600;
}
.teacher-pending-card h2 {
  margin: 0;
  font-size: 22px;
  line-height: 1.3;
  font-weight: 600;
}
.teacher-pending-identity {
  font-size: 13px;
  color: var(--ink-fade);
  padding-bottom: 10px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.teacher-pending-detail {
  margin: 0;
  font-size: 14px;
  line-height: 1.55;
  color: var(--ink);
}
.teacher-pending-reason {
  margin: 4px 0;
  padding: 12px 14px;
  background: rgba(184, 80, 80, 0.07);
  border-left: 3px solid rgba(184, 80, 80, 0.6);
  font-size: 13.5px;
  line-height: 1.5;
  color: var(--ink);
  font-style: italic;
}
.teacher-pending-checklist {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin: 4px 0;
}
.teacher-pending-step {
  display: flex;
  gap: 12px;
  align-items: flex-start;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(0,0,0,0.02);
}
.teacher-pending-step-done {
  background: rgba(70, 140, 90, 0.07);
}
.teacher-pending-step-current {
  background: rgba(220, 175, 80, 0.10);
  outline: 1px solid rgba(220, 175, 80, 0.25);
}
.teacher-pending-tick {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  background: rgba(0,0,0,0.08);
  color: var(--ink);
  font-weight: 700;
  font-size: 13px;
  flex-shrink: 0;
}
.teacher-pending-step-done .teacher-pending-tick {
  background: rgba(70, 140, 90, 0.85);
  color: #fff;
}
.teacher-pending-step strong {
  display: block;
  font-size: 13.5px;
  margin-bottom: 2px;
}
.teacher-pending-step span:not(.teacher-pending-tick) {
  display: block;
  font-size: 12.5px;
  color: var(--ink-fade);
  line-height: 1.45;
}
.teacher-pending-meanwhile {
  margin-top: 8px;
  padding-top: 16px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.teacher-pending-meanwhile h3 {
  margin: 0 0 8px 0;
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.teacher-pending-meanwhile ul {
  margin: 0;
  padding-left: 20px;
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-fade);
}
.teacher-pending-meanwhile a {
  color: var(--accent, #b1564a);
  text-decoration: underline;
}
.teacher-pending-actions {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  margin-top: 6px;
}
.teacher-pending-fineprint {
  margin: 0;
  font-size: 11.5px;
  color: var(--ink-fade);
  line-height: 1.5;
}

/* ── Admin queue ──────────────────────────────────────────────────── */
.admin-queue-card {
  max-width: 720px;
  width: 100%;
  max-height: 80vh;
  display: flex;
  flex-direction: column;
}
.admin-queue-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 28px 8px 28px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.admin-queue-header h2 {
  margin: 0;
  font-size: 18px;
}
.admin-queue-tabs {
  display: flex;
  gap: 0;
  padding: 0 28px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
  background: rgba(0,0,0,0.015);
}
.admin-queue-tab {
  background: none;
  border: none;
  padding: 12px 14px;
  font-size: 13px;
  cursor: pointer;
  color: var(--ink-fade);
  border-bottom: 2px solid transparent;
  display: flex;
  align-items: center;
  gap: 6px;
}
.admin-queue-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--accent, #b1564a);
}
.admin-queue-tab-count {
  font-size: 11px;
  background: rgba(0,0,0,0.08);
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 600;
}
.admin-queue-body {
  overflow-y: auto;
  padding: 16px 28px 24px 28px;
  flex: 1;
}
.admin-queue-loading,
.admin-queue-error {
  color: var(--ink-fade);
  font-style: italic;
  text-align: center;
  padding: 24px;
}
.admin-queue-help {
  margin: 0 0 14px 0;
  font-size: 12.5px;
  color: var(--ink-fade);
  line-height: 1.5;
}
.admin-queue-empty {
  text-align: center;
  padding: 32px 16px;
  color: var(--ink-fade);
}
.admin-queue-empty h3 {
  margin: 0 0 6px 0;
  font-size: 16px;
  color: var(--ink);
}
.admin-queue-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.admin-queue-row {
  background: #fff;
  border: 1px solid var(--rule, rgba(0,0,0,0.10));
  border-radius: 10px;
  padding: 12px 14px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.admin-queue-row-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 10px;
}
.admin-queue-row-name { font-size: 14px; }
.admin-queue-row-email { color: var(--ink-fade); font-size: 13px; }
.admin-queue-row-domain {
  font-size: 11px;
  background: rgba(0,0,0,0.04);
  padding: 2px 8px;
  border-radius: 4px;
  color: var(--ink-fade);
  font-family: var(--mono, ui-monospace, monospace);
}
.admin-queue-row-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  font-size: 11.5px;
  color: var(--ink-fade);
}
.admin-queue-row-note {
  margin: 4px 0;
  padding: 8px 12px;
  background: rgba(0,0,0,0.025);
  border-left: 3px solid rgba(0,0,0,0.15);
  font-size: 12.5px;
  font-style: italic;
}
.admin-queue-row-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.admin-queue-status-pill {
  font-size: 10.5px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.admin-queue-status-approved {
  background: rgba(70, 140, 90, 0.12);
  color: rgb(50, 110, 70);
}
.admin-queue-status-rejected {
  background: rgba(184, 80, 80, 0.12);
  color: rgb(150, 60, 60);
}
.admin-queue-su-add {
  display: flex;
  gap: 8px;
  margin-bottom: 16px;
  flex-wrap: wrap;
}
.admin-queue-su-add input {
  flex: 1;
  min-width: 180px;
  padding: 8px 10px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-size: 13px;
}

/* ── Phase 2: classroom roster controls ─────────────────────────── */

.teacher-people-toolbar {
  margin-bottom: 14px;
  padding: 12px 14px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.teacher-people-add {
  display: flex;
  gap: 8px;
  align-items: center;
  flex-wrap: wrap;
}
.teacher-people-add input[type="email"] {
  flex: 1;
  min-width: 200px;
  padding: 8px 10px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-size: 13px;
}
#teacher-people-add-help {
  margin-top: 8px;
  margin-bottom: 0;
  font-size: 11.5px;
  transition: color 0.2s ease;
}

/* Roster row — now has a per-row Remove button. */
.teacher-people-row {
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 4px 12px;
  padding: 10px 12px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.teacher-people-row .teacher-people-name {
  font-size: 13.5px;
}
.teacher-people-row .teacher-people-meta {
  grid-column: 1 / 2;
  font-size: 11.5px;
  color: var(--ink-fade);
}
.teacher-people-remove {
  grid-row: 1 / 3;
  grid-column: 2 / 3;
  font-size: 11.5px;
  padding: 5px 12px;
  opacity: 0.6;
  transition: opacity 0.15s ease;
}
.teacher-people-row:hover .teacher-people-remove {
  opacity: 1;
}

/* Classroom grid filter — show/hide archived */
.teacher-classrooms-filter {
  padding: 0 4px 12px;
  display: flex;
  justify-content: flex-end;
}
.teacher-classrooms-filter-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-fade);
  cursor: pointer;
  user-select: none;
}

/* Reusable modal layout (used by edit-info + defaults modals).
   These reuse .rm-modal but I'm adding header / body / footer
   variants so the inline modals don't have to redefine layout. */
.rm-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 24px 8px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.rm-modal-header h2 {
  margin: 0;
  font-size: 17px;
}
.rm-modal-body {
  padding: 18px 24px;
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.rm-modal-body .rm-field {
  display: flex;
  flex-direction: column;
  gap: 5px;
}
.rm-modal-body .rm-field > span {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-fade);
}
.rm-modal-body input[type="text"],
.rm-modal-body input[type="email"],
.rm-modal-body input[type="number"],
.rm-modal-body select {
  padding: 9px 11px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-size: 14px;
  font-family: inherit;
  width: 100%;
}
.rm-modal-footer {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  padding: 12px 24px 20px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
}

/* ── Phase 3: assignment modal ────────────────────────────────────── */

.teacher-classwork-toolbar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 4px 14px 4px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
  margin-bottom: 14px;
}
.teacher-classwork-toolbar-spacer { flex: 1; }
.teacher-classwork-new-btn { font-weight: 600; }

.rm-modal-card-tall {
  max-height: 92vh;
  display: flex;
  flex-direction: column;
}
.assignment-modal-card {
  max-width: 1140px;
  width: 96vw;
}
.assignment-modal-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 18px 24px 12px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.assignment-modal-header h2 { margin: 0; font-size: 18px; }
.assignment-modal-headbtns {
  display: flex;
  align-items: center;
  gap: 8px;
}
.assignment-modal-body {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 0;
  flex: 1;
  overflow: hidden;
}
.assignment-form {
  overflow-y: auto;
  padding: 18px 24px 0;
  display: flex;
  flex-direction: column;
  gap: 14px;
  border-right: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.assignment-form .rm-field { margin: 0; }
.rm-field-group {
  border: 1px solid var(--hair-strong, rgba(0,0,0,0.10));
  border-radius: 8px;
  padding: 10px 14px;
  margin: 0;
}
.rm-field-group legend {
  font-size: 11.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-fade);
  padding: 0 6px;
}
.rm-field-radio {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 6px 0;
  cursor: pointer;
  font-size: 13.5px;
}
.rm-field-radio input { margin-top: 3px; }
.rm-field-radio strong { font-weight: 600; }

.assignment-section {
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
  padding-top: 12px;
}
.assignment-section > summary {
  cursor: pointer;
  font-weight: 600;
  font-size: 13px;
  padding: 6px 0;
  user-select: none;
}
.assignment-section > summary small {
  font-weight: 400;
  color: var(--ink-fade);
  margin-left: 6px;
}

.assignment-attachments-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 10px 0;
}
.assignment-attachment-chip {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 8px 10px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  font-size: 12.5px;
}
.assignment-attachment-kind {
  font-size: 10px;
  background: rgba(0,0,0,0.08);
  padding: 2px 7px;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.assignment-attachment-name {
  grid-column: 2 / 3;
  font-weight: 500;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.assignment-attachment-label-input {
  grid-column: 1 / 3;
  font-size: 11.5px;
  padding: 4px 8px;
  border: 1px solid var(--hair, rgba(0,0,0,0.08));
  border-radius: 4px;
}
.assignment-attachment-remove {
  grid-column: 3 / 4;
  grid-row: 1 / 3;
  background: none;
  border: none;
  font-size: 16px;
  cursor: pointer;
  color: var(--ink-fade);
  padding: 2px 8px;
}
.assignment-attachment-remove:hover { color: var(--red); }
.assignment-attachments-add {
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
}
#assignment-attachments-help {
  font-size: 11.5px;
}

#assignment-starter-body {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 13px;
  margin-top: 8px;
  resize: vertical;
}

.assignment-modal-footer {
  position: sticky;
  bottom: 0;
  background: var(--paper);
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
  padding: 14px 0;
  margin: 14px -24px 0;
  padding-left: 24px;
  padding-right: 24px;
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}

.assignment-preview {
  overflow-y: auto;
  background: rgba(0,0,0,0.015);
  display: flex;
  flex-direction: column;
}
.assignment-preview-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 14px 20px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.assignment-preview-eyebrow {
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--ink-fade);
  font-weight: 600;
}
.assignment-preview-body {
  padding: 20px 24px;
  flex: 1;
}
.assignment-preview-article h1 {
  margin: 0 0 6px;
  font-size: 22px;
}
.assignment-preview-article h2 { font-size: 16px; margin: 18px 0 6px; }
.assignment-preview-article h3 { font-size: 13.5px; margin: 14px 0 4px; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-fade); }
.assignment-preview-meta {
  display: flex;
  gap: 10px;
  font-size: 12px;
  color: var(--ink-fade);
  margin-bottom: 12px;
}
.assignment-preview-pill {
  background: rgba(70, 140, 90, 0.12);
  color: rgb(50, 110, 70);
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  font-weight: 600;
}
.assignment-preview-instructions {
  font-size: 14px;
  line-height: 1.6;
}
.assignment-preview-instructions blockquote {
  margin: 10px 0;
  padding: 8px 14px;
  background: rgba(0,0,0,0.03);
  border-left: 3px solid rgba(0,0,0,0.15);
  font-style: italic;
}
.assignment-preview-instructions pre,
.assignment-preview-instructions code {
  background: rgba(0,0,0,0.05);
  padding: 1px 5px;
  border-radius: 3px;
  font-family: var(--mono, ui-monospace, monospace);
  font-size: 13px;
}
.assignment-preview-attachments {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.assignment-preview-attachments ul {
  list-style: none;
  padding: 0;
  margin: 6px 0 0;
}
.assignment-preview-attachment {
  display: flex;
  gap: 10px;
  align-items: center;
  padding: 6px 0;
  font-size: 13px;
}
.assignment-preview-attach-kind {
  font-size: 10px;
  background: rgba(0,0,0,0.08);
  padding: 2px 8px;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 600;
  letter-spacing: 0.04em;
}
.assignment-preview-starter {
  margin-top: 20px;
  padding-top: 14px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.assignment-preview-starter pre {
  background: rgba(0,0,0,0.025);
  padding: 12px;
  border-radius: 6px;
  font-size: 13px;
  white-space: pre-wrap;
  word-break: break-word;
}

/* ── LMS binding section ─────────────────────────────────────────── */
.assignment-lms-body {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.assignment-lms-status {
  font-size: 13px;
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.assignment-lms-pill {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 600;
}
.assignment-lms-pill-deep-link { background: rgba(70, 140, 90, 0.12); color: rgb(50, 110, 70); }
.assignment-lms-pill-post-hoc  { background: rgba(70, 100, 170, 0.12); color: rgb(50, 80, 140); }
.assignment-lms-inst { color: var(--ink-fade); font-size: 12px; }
.assignment-lms-meta {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.assignment-lms-actions {
  display: flex;
  gap: 8px;
  margin-top: 4px;
}
.assignment-lms-lineitems {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* L3 — multi-binding list */
.assignment-lms-bindings-list {
  list-style: none;
  padding: 0;
  margin: 0 0 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.assignment-lms-binding-row {
  padding: 12px 14px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.assignment-lms-binding-row .assignment-lms-status { margin-bottom: 2px; }
.assignment-lms-binding-row .assignment-lms-actions {
  margin-top: 6px;
  display: flex;
  gap: 6px;
}
/* LMS-picker (multi-LMS classroom) */
.assignment-lms-picker {
  list-style: none;
  padding: 0;
  margin: 10px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.assignment-lms-picker-row {
  padding: 12px 14px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}
.assignment-lms-lineitem {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  background: rgba(0,0,0,0.025);
  border-radius: 6px;
}

/* ── Sync failures inbox ─────────────────────────────────────────── */
.sync-failures-list { list-style: none; padding: 0; margin: 0; display: flex; flex-direction: column; gap: 10px; }
.sync-failure-row {
  background: #fff;
  border: 1px solid var(--rule, rgba(184, 80, 80, 0.25));
  border-radius: 8px;
  padding: 12px 14px;
}
.sync-failure-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 4px;
}
.sync-failure-when { font-size: 11.5px; color: var(--ink-fade); }
.sync-failure-meta { font-size: 11.5px; color: var(--ink-fade); }
.sync-failure-error {
  margin: 8px 0;
  padding: 8px 12px;
  background: rgba(184, 80, 80, 0.07);
  border-left: 3px solid rgba(184, 80, 80, 0.5);
  font-size: 12.5px;
  font-style: italic;
}
.sync-failure-actions { display: flex; gap: 8px; }

/* Responsive — collapse the preview pane on narrow screens. */
@media (max-width: 900px) {
  .assignment-modal-body { grid-template-columns: 1fr; }
  .assignment-preview { border-top: 1px solid var(--rule, rgba(0,0,0,0.06)); border-right: none; }
}

/* ── Phase 3 deferred batch ──────────────────────────────────────── */

/* Reference link chips on the teacher modal */
.assignment-reflinks-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
.assignment-reflink-chip {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  font-size: 12.5px;
}
.assignment-reflink-kind {
  font-size: 10px;
  background: rgba(60, 90, 150, 0.10);
  color: rgb(60, 90, 150);
  padding: 2px 7px;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 600;
}
.assignment-reflink-url { text-decoration: none; color: var(--accent, #b1564a); font-weight: 500; word-break: break-all; }
.assignment-reflink-url:hover { text-decoration: underline; }
.assignment-reflink-remove { background: none; border: none; cursor: pointer; padding: 2px 8px; color: var(--ink-fade); font-size: 16px; }
.assignment-reflink-remove:hover { color: var(--red); }
.assignment-reflinks-add {
  display: grid;
  grid-template-columns: 2fr 2fr 1fr auto;
  gap: 6px;
}
.assignment-reflinks-add input,
.assignment-reflinks-add select {
  padding: 7px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-size: 12.5px;
}

/* Self-assessment prompt rows */
.assignment-self-list { display: flex; flex-direction: column; gap: 8px; margin-bottom: 10px; }
.assignment-self-row {
  display: grid;
  grid-template-columns: 1fr auto auto;
  gap: 8px;
  align-items: center;
  padding: 8px 10px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
}
.assignment-self-prompt {
  width: 100%;
  padding: 6px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-size: 12.5px;
}
.assignment-self-required {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: 11.5px;
  color: var(--ink-fade);
  white-space: nowrap;
}
.assignment-self-remove { background: none; border: none; cursor: pointer; padding: 2px 8px; color: var(--ink-fade); font-size: 16px; }
.assignment-self-remove:hover { color: var(--red); }

/* Preview pane additions */
.assignment-preview-reflinks ul { list-style: none; padding: 0; margin: 6px 0 0; }
.assignment-preview-reflinks li { display: flex; gap: 8px; align-items: center; padding: 4px 0; font-size: 13px; }
.assignment-preview-targets ul {
  list-style: none;
  padding: 0;
  margin: 6px 0 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}
.assignment-preview-selfprompts ol { padding-left: 20px; margin: 6px 0 0; font-size: 13px; line-height: 1.55; }
.assignment-preview-required { font-size: 10px; color: var(--red); text-transform: uppercase; letter-spacing: 0.05em; }

/* Student-side info panel additions */
.assignment-info-targets {
  list-style: none;
  padding: 0;
  margin: 6px 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 13px;
}
.targets-progress {
  margin-top: 8px;
  padding: 6px 10px;
  border-radius: 6px;
  font-size: 12px;
  font-weight: 500;
}
.targets-progress-under {
  background: rgba(220, 175, 80, 0.15);
  color: rgb(140, 100, 20);
}
.targets-progress-in-range {
  background: rgba(70, 140, 90, 0.12);
  color: rgb(50, 110, 70);
}
.targets-progress-over {
  background: rgba(184, 80, 80, 0.10);
  color: rgb(150, 60, 60);
}

.assignment-info-reflinks { list-style: none; padding: 0; margin: 6px 0; }
.assignment-info-reflinks li { display: flex; gap: 8px; align-items: center; padding: 4px 0; font-size: 13.5px; }
.assignment-info-reflink-kind {
  font-size: 10px;
  background: rgba(60, 90, 150, 0.10);
  color: rgb(60, 90, 150);
  padding: 2px 7px;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 600;
}
.assignment-info-attachments { list-style: none; padding: 0; margin: 6px 0; }
.assignment-info-attachment {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 6px 0;
  font-size: 13.5px;
}
.assignment-info-attach-kind {
  font-size: 10px;
  background: rgba(0,0,0,0.06);
  padding: 2px 7px;
  border-radius: 4px;
  text-transform: uppercase;
  font-weight: 600;
}
.assignment-info-attach-link { color: var(--accent, #b1564a); text-decoration: none; font-size: 12px; }
.assignment-info-attach-link:hover { text-decoration: underline; }

.assignment-info-self .rm-field { margin-bottom: 12px; }
.assignment-info-self-saved {
  color: rgb(50, 110, 70);
  margin-left: 12px;
  font-weight: 500;
}

/* ── S7: sub-tasks (teacher modal + student checklist) ───────────── */

.assignment-subtasks-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-bottom: 10px;
}
.assignment-subtask-row {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  padding: 12px 14px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
}
.assignment-subtask-handle {
  width: 28px;
  height: 28px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0,0,0,0.08);
  border-radius: 50%;
  font-weight: 700;
  font-size: 13px;
}
.assignment-subtask-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.assignment-subtask-title {
  padding: 7px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-size: 13.5px;
  font-weight: 500;
}
.assignment-subtask-desc {
  padding: 7px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-size: 12.5px;
  font-family: inherit;
  resize: vertical;
}
.assignment-subtask-meta {
  display: flex;
  gap: 10px;
  align-items: center;
  font-size: 11.5px;
}
.assignment-subtask-meta label {
  display: flex;
  align-items: center;
  gap: 6px;
  color: var(--ink-fade);
}
.assignment-subtask-meta input[type="date"] {
  padding: 4px 8px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 4px;
  font-size: 12px;
}
.assignment-subtask-up,
.assignment-subtask-down,
.assignment-subtask-remove {
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 2px 7px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--ink-fade);
}
.assignment-subtask-up:hover,
.assignment-subtask-down:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
.assignment-subtask-remove:hover { color: var(--red); }

/* Preview pane parts */
.assignment-preview-subtasks ol { padding-left: 20px; margin: 6px 0 0; font-size: 13px; line-height: 1.55; }
.assignment-preview-subtasks li { padding: 4px 0; }
.assignment-preview-subtask-due {
  margin-left: 8px;
  font-size: 11px;
  color: var(--ink-fade);
}
.assignment-preview-subtask-desc {
  font-size: 12px;
  color: var(--ink-fade);
  margin-top: 2px;
}

/* Student-side checklist */
.assignment-info-subtasks {
  list-style: none;
  padding: 0;
  margin: 6px 0;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.assignment-info-subtask {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 10px;
  padding: 10px 12px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
  transition: background 120ms ease;
}
.assignment-info-subtask-done {
  background: rgba(70, 140, 90, 0.10);
}
.assignment-info-subtask-in-progress {
  background: rgba(220, 175, 80, 0.10);
}
.assignment-info-subtask-toggle {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(0,0,0,0.08);
  border: none;
  cursor: pointer;
  font-size: 14px;
  font-weight: 700;
  color: var(--ink);
  transition: background 120ms ease, transform 80ms ease;
}
.assignment-info-subtask-done .assignment-info-subtask-toggle {
  background: rgba(70, 140, 90, 0.85);
  color: #fff;
}
.assignment-info-subtask-in-progress .assignment-info-subtask-toggle {
  background: rgba(220, 175, 80, 0.85);
  color: #fff;
}
.assignment-info-subtask-toggle:hover { transform: scale(1.08); }
.assignment-info-subtask-toggle:active { transform: scale(0.96); }
.assignment-info-subtask-body { display: flex; flex-direction: column; gap: 4px; }
.assignment-info-subtask-head {
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
}
.assignment-info-subtask-due {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.assignment-info-subtask-desc {
  font-size: 12.5px;
  color: var(--ink-fade);
  line-height: 1.5;
}

/* ── S6: variants (teacher modal + student pill) ─────────────────── */

.assignment-variants-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
  margin-bottom: 10px;
}
.assignment-variant-row {
  padding: 14px 16px;
  background: rgba(60, 90, 150, 0.05);
  border: 1px solid rgba(60, 90, 150, 0.20);
  border-radius: 10px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.assignment-variant-head {
  display: grid;
  grid-template-columns: 1fr auto auto auto;
  gap: 6px;
  align-items: center;
}
.assignment-variant-label {
  padding: 7px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-size: 14px;
  font-weight: 600;
}
.assignment-variant-up,
.assignment-variant-down,
.assignment-variant-remove {
  background: none;
  border: 1px solid transparent;
  cursor: pointer;
  padding: 4px 8px;
  border-radius: 4px;
  font-size: 13px;
  color: var(--ink-fade);
}
.assignment-variant-up:hover,
.assignment-variant-down:hover { background: rgba(0,0,0,0.06); color: var(--ink); }
.assignment-variant-remove:hover { color: var(--red); }
.assignment-variant-tags-row {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}
.assignment-variant-tags-label {
  font-size: 11.5px;
  color: var(--ink-fade);
  font-weight: 500;
}
.assignment-variant-tags-chips {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-wrap: wrap;
}
.assignment-variant-tag-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 11px;
  background: rgba(60, 90, 150, 0.15);
  color: rgb(50, 70, 130);
  padding: 3px 9px;
  border-radius: 999px;
  font-weight: 500;
}
.assignment-variant-tag-remove {
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  padding: 0 0 0 2px;
  font-size: 14px;
  line-height: 1;
}
.assignment-variant-tag-input {
  font-size: 11.5px;
  padding: 4px 8px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 4px;
  min-width: 100px;
}
.assignment-variant-row textarea {
  width: 100%;
  padding: 8px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-family: inherit;
  font-size: 12.5px;
  resize: vertical;
}

/* Per-student tag chips on the People tab */
.teacher-people-tags {
  grid-column: 1 / 2;
  grid-row: 3 / 4;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  align-items: center;
  margin-top: 4px;
}
.teacher-people-tag {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 10.5px;
  background: rgba(60, 90, 150, 0.12);
  color: rgb(50, 70, 130);
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 500;
}
.teacher-people-tag-remove {
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  padding: 0;
  font-size: 12px;
  line-height: 1;
}
.teacher-people-tag-input {
  font-size: 10.5px;
  padding: 2px 8px;
  border: 1px dashed var(--hair, rgba(0,0,0,0.15));
  border-radius: 999px;
  min-width: 70px;
  width: 80px;
}
.teacher-people-row {
  grid-template-rows: auto auto auto;
}

/* ── S10: peer reviews ───────────────────────────────────────────── */

/* Teacher's manage table */
.peer-review-mgr-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.peer-review-mgr-table th,
.peer-review-mgr-table td {
  padding: 10px 12px;
  vertical-align: top;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.peer-review-mgr-table th {
  text-align: left;
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-fade);
}
.pr-mgr-reviewers {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.pr-mgr-reviewers li {
  display: flex;
  gap: 6px;
  align-items: center;
  font-size: 12.5px;
}
.pr-mgr-remove {
  margin-left: auto;
  padding: 0 6px;
}
.pr-status {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  padding: 2px 7px;
  border-radius: 999px;
  font-weight: 600;
}
.pr-status-assigned    { background: rgba(0,0,0,0.08); color: var(--ink-fade); }
.pr-status-in-progress { background: rgba(220, 175, 80, 0.15); color: rgb(140, 100, 20); }
.pr-status-submitted   { background: rgba(70, 140, 90, 0.15); color: rgb(50, 110, 70); }
.pr-status-responded   { background: rgba(60, 90, 150, 0.15); color: rgb(50, 70, 130); }
.pr-mgr-reviewer-pick {
  padding: 6px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-size: 12.5px;
  margin-right: 6px;
}

/* Reviewer workspace */
.peer-review-workspace {
  display: grid;
  grid-template-columns: 1.2fr 1fr;
  gap: 0;
  flex: 1;
  overflow: hidden;
}
.peer-review-doc {
  overflow-y: auto;
  padding: 18px 24px;
  border-right: 1px solid var(--rule, rgba(0,0,0,0.06));
  background: rgba(0,0,0,0.015);
}
.peer-review-doc h3 { margin: 0 0 4px; font-size: 17px; }
.peer-review-doc hr { margin: 18px 0; border: none; border-top: 1px solid var(--rule, rgba(0,0,0,0.08)); }
.peer-review-doc-instructions { font-size: 13.5px; color: var(--ink-fade); line-height: 1.55; }
.peer-review-doc-body { font-size: 14.5px; line-height: 1.7; }
.peer-review-form {
  padding: 18px 24px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.peer-review-form textarea {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--hair-strong, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-family: inherit;
  font-size: 14px;
  line-height: 1.55;
  resize: vertical;
  min-height: 200px;
}
.peer-review-form textarea[readonly] {
  background: rgba(0,0,0,0.025);
  cursor: default;
}
.peer-review-form-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
}
.peer-review-author-response {
  margin-top: 10px;
  padding: 12px 14px;
  background: rgba(60, 90, 150, 0.06);
  border-left: 3px solid rgba(60, 90, 150, 0.4);
  border-radius: 6px;
}
.peer-review-author-response h4 {
  margin: 0 0 6px 0;
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink-fade);
}

/* Author's view of feedback (inline on assignment info panel) */
.peer-feedback-list {
  list-style: none;
  padding: 0;
  margin: 6px 0 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
}
.peer-feedback-row {
  padding: 12px 14px;
  background: rgba(0,0,0,0.025);
  border-radius: 8px;
}
.peer-feedback-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  margin-bottom: 6px;
}
.peer-feedback-when {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.peer-feedback-body {
  font-size: 13.5px;
  line-height: 1.6;
}
.peer-feedback-response {
  margin-top: 8px;
  padding: 8px 12px;
  background: rgba(0,0,0,0.04);
  border-left: 3px solid rgba(0,0,0,0.15);
  border-radius: 4px;
  font-size: 12.5px;
}
.peer-feedback-response strong { display: block; margin-bottom: 4px; }
.peer-feedback-reply-form {
  margin-top: 10px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.peer-feedback-reply-form textarea {
  padding: 8px 10px;
  border: 1px solid var(--hair, rgba(0,0,0,0.10));
  border-radius: 6px;
  font-family: inherit;
  font-size: 12.5px;
  resize: vertical;
}
.peer-feedback-reply-form button {
  align-self: flex-end;
}

@media (max-width: 900px) {
  .peer-review-workspace { grid-template-columns: 1fr; }
  .peer-review-doc { border-right: none; border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06)); }
}

/* Student-side variant pill */
.assignment-info-variant-row {
  padding-bottom: 8px;
  margin-bottom: 8px;
  border-bottom: 1px dashed var(--rule, rgba(0,0,0,0.08));
}
.assignment-info-variant-pill {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 11px;
  background: rgba(60, 90, 150, 0.12);
  color: rgb(50, 70, 130);
  padding: 4px 10px;
  border-radius: 999px;
  font-weight: 600;
  letter-spacing: 0.03em;
}

/* Profile menu pending badge — also reused by the admin item. */
.pm-badge {
  margin-left: auto;
  background: rgba(184, 80, 80, 0.85);
  color: #fff;
  font-size: 10px;
  font-weight: 700;
  padding: 2px 7px;
  border-radius: 999px;
}
.teacher-signed-as {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 8px 10px;
  background: var(--paper-edge);
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-2);
  margin-bottom: 12px;
}
.teacher-signed-as strong { color: var(--ink); font-weight: 600; }
.teacher-empty {
  padding: 16px 12px 18px;
  border: 1px dashed var(--hair-strong);
  border-radius: 8px;
  background: var(--paper);
  text-align: left;
  margin-bottom: 16px;
}
.teacher-empty p { margin: 0 0 6px; font-size: 13px; color: var(--ink-2); }
.teacher-empty button { margin-top: 10px; }

/* ═══ Step 19 — Teacher classroom UI ═════════════════════════════
   Two-level navigation:
     1. Classrooms grid (cards). Default landing of the teacher
        dashboard.
     2. Per-classroom view (header + tabs). Replaces the grid when
        a card is clicked. Back button returns to the grid. */

/* Top-level nav for the Teacher dashboard — Classrooms vs Messages */
.teacher-toplevel-nav {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--hair);
  margin-bottom: 12px;
}
.teacher-toplevel-tab {
  background: transparent;
  border: 0;
  padding: 8px 14px;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.teacher-toplevel-tab:hover { color: var(--ink); }
.teacher-toplevel-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--red);
  font-weight: 600;
}
.teacher-inbox-badge {
  background: var(--red);
  color: var(--paper);
  font-size: 10px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 999px;
  min-width: 16px;
  text-align: center;
}

/* Teacher inbox list */
.teacher-inbox-view { display: block; }
.teacher-inbox-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.teacher-inbox-row {
  position: relative;
  text-align: left;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 10px 14px 10px 14px;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.teacher-inbox-row:hover { border-color: var(--ink-2); }
.teacher-inbox-row.is-unread { background: color-mix(in srgb, var(--red) 3%, var(--paper) 97%); }
.teacher-inbox-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11.5px;
  color: var(--ink-fade);
}
.teacher-inbox-row-student { font-weight: 600; color: var(--ink-soft); }
.teacher-inbox-row-assignment {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink);
}
.teacher-inbox-row-snippet {
  font-size: 12.5px;
  color: var(--ink-soft);
  line-height: 1.4;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.teacher-inbox-row-badge {
  position: absolute;
  top: 10px;
  right: 14px;
  background: var(--red);
  color: var(--paper);
  font-size: 10px;
  font-weight: 600;
  padding: 1px 7px;
  border-radius: 999px;
}

/* Classrooms grid — header row with view toggle */
.teacher-classrooms-view { display: block; }
.teacher-section-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}
.teacher-view-toggle {
  display: inline-flex;
  border: 1px solid var(--hair);
  border-radius: 6px;
  overflow: hidden;
  background: var(--paper);
}
.teacher-view-toggle-btn {
  background: transparent;
  border: 0;
  padding: 4px 10px;
  font-size: 14px;
  cursor: pointer;
  color: var(--ink-fade);
  border-right: 1px solid var(--hair);
}
.teacher-view-toggle-btn:last-child { border-right: 0; }
.teacher-view-toggle-btn:hover { color: var(--ink); }
.teacher-view-toggle-btn.is-active {
  background: var(--paper-edge);
  color: var(--ink);
}
.teacher-classrooms-grid.is-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}
.teacher-classrooms-grid.is-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 12px;
}
/* Fallback when no view class is applied (initial render). */
.teacher-classrooms-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
  gap: 12px;
  margin-bottom: 12px;
}

/* List-row layout */
.teacher-class-listrow {
  display: grid;
  grid-template-columns: 28px 1fr auto auto;
  align-items: center;
  gap: 12px;
  padding: 8px 12px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
  cursor: pointer;
  outline: none;
}
.teacher-class-listrow:hover,
.teacher-class-listrow:focus-visible {
  border-color: var(--ink-2);
  background: color-mix(in srgb, var(--paper-edge) 80%, var(--paper) 20%);
}
.teacher-class-listrow-chip {
  width: 16px;
  height: 16px;
  border-radius: 4px;
}
.teacher-class-listrow-main { min-width: 0; }
.teacher-class-listrow-name {
  font-size: 13.5px;
  font-weight: 600;
  color: var(--ink);
}
.teacher-class-listrow-sub {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.teacher-class-listrow-meta,
.teacher-class-listrow-stats {
  font-size: 11.5px;
  color: var(--ink-soft);
  white-space: nowrap;
}
.teacher-empty-full { padding: 20px 0; }
.teacher-class-card {
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 10px;
  overflow: hidden;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  transition: transform 100ms ease, box-shadow 100ms ease, border-color 100ms ease;
  outline: none;
}
.teacher-class-card:hover,
.teacher-class-card:focus-visible {
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0,0,0,0.06);
  border-color: var(--ink-2);
}
.teacher-class-card-stripe { height: 36px; }
.teacher-class-card-body   { padding: 10px 12px 12px; }
.teacher-class-card-name {
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 2px;
  display: flex;
  align-items: center;
  gap: 6px;
}
.teacher-class-card-archived {
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--paper-edge);
  color: var(--ink-fade);
}
.teacher-class-card-sub {
  font-size: 11.5px;
  color: var(--ink-fade);
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.teacher-class-card-sub span:not(:last-child)::after {
  content: '·';
  margin-left: 6px;
  color: var(--ink-fade);
}
.teacher-class-card-meta {
  margin-bottom: 6px;
}
.teacher-class-card-code {
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  background: var(--paper-edge);
  padding: 3px 7px;
  border-radius: 4px;
}
.teacher-class-card-code-label {
  font-family: var(--sans);
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-fade);
  margin-right: 4px;
}
.teacher-class-card-stats {
  font-size: 11.5px;
  color: var(--ink-soft);
  display: flex;
  gap: 4px;
}

/* Per-classroom view */
.teacher-classroom-view { display: block; }
.teacher-classroom-back {
  background: none;
  border: none;
  color: var(--ink-soft);
  font-size: 13px;
  padding: 4px 0;
  cursor: pointer;
  margin-bottom: 8px;
}
.teacher-classroom-back:hover { color: var(--ink); }

.teacher-classroom-header {
  position: relative;
  border: 1px solid var(--hair);
  border-radius: 10px;
  background: var(--paper);
  overflow: hidden;
  margin-bottom: 14px;
}
.teacher-classroom-stripe { height: 8px; }
.teacher-classroom-headbody { padding: 12px 14px; }
.teacher-classroom-name {
  margin: 0 0 4px;
  font-size: 18px;
  font-weight: 600;
  color: var(--ink);
}
.teacher-classroom-meta {
  font-size: 12px;
  color: var(--ink-fade);
  display: flex;
  gap: 6px;
  margin-bottom: 10px;
}
.teacher-classroom-share {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.teacher-classroom-share-row {
  display: flex;
  align-items: center;
  gap: 8px;
}
.teacher-classroom-share-label {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-fade);
  min-width: 70px;
}
.teacher-classroom-share-value {
  flex: 1;
  background: var(--paper-edge);
  padding: 4px 8px;
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 12px;
  color: var(--ink-soft);
  white-space: nowrap;
  overflow-x: auto;
}
.teacher-classroom-share-link { font-size: 11px; }

/* Color picker swatches */
.teacher-classroom-swatches {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.teacher-classroom-swatch {
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 2px solid var(--paper);
  outline: 1px solid var(--hair);
  cursor: pointer;
  padding: 0;
  transition: transform 100ms ease;
}
.teacher-classroom-swatch:hover { transform: scale(1.1); }
.teacher-classroom-swatch.is-active {
  outline: 2px solid var(--ink);
  outline-offset: 1px;
}

/* Create-assignment form — full-width variant */
.teacher-create-form-wide textarea {
  width: 100%;
  font-family: var(--sans);
  /* Vertical-only resize — the textarea sits in a fixed-width modal,
     so horizontal drag would push past the modal's chrome. Users can
     still grow / shrink the height as needed. */
  resize: vertical;
}
.teacher-form-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.teacher-form-row .rm-field { margin: 0; }
.teacher-form-row input[type="date"],
.teacher-form-row input[type="datetime-local"] {
  width: 100%;
}

/* Status pills on assignment rows */
.teacher-assignment-pill {
  display: inline-block;
  margin-left: 6px;
  font-size: 9.5px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  padding: 2px 6px;
  border-radius: 4px;
  font-weight: 600;
  vertical-align: 2px;
}
.teacher-assignment-pill-draft {
  background: var(--paper-edge);
  color: var(--ink-fade);
  border: 1px solid var(--hair);
}
.teacher-assignment-pill-scheduled {
  background: color-mix(in srgb, var(--accent, #2b4a6f) 12%, var(--paper));
  color: var(--accent, #2b4a6f);
  border: 1px solid color-mix(in srgb, var(--accent, #2b4a6f) 30%, transparent);
}

.teacher-assignment-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-bottom: 6px;
}
.teacher-assignment-actions button {
  font-size: 11.5px;
  padding: 4px 10px;
}

/* Tabs */
.teacher-classroom-tabs {
  display: flex;
  gap: 4px;
  border-bottom: 1px solid var(--hair);
  margin-bottom: 12px;
}
.teacher-classroom-tab {
  background: none;
  border: none;
  padding: 8px 14px;
  font-size: 13px;
  color: var(--ink-soft);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
}
.teacher-classroom-tab:hover { color: var(--ink); }
.teacher-classroom-tab.is-active {
  color: var(--ink);
  border-bottom-color: var(--red);
  font-weight: 600;
}
.teacher-classroom-tab-panel { display: none; }
.teacher-classroom-tab-panel.is-active { display: block; }
.teacher-classroom-tab-panel[hidden] { display: none !important; }

/* Stream feed */
.teacher-stream-feed {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.teacher-stream-row {
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
  padding: 12px 14px;
  /* Left stripe in the parent classroom's color so every assignment
     + update visually belongs to its class. The CSS var is set
     inline on each row by renderStreamItem. */
  border-left: 4px solid var(--rm-class-color, var(--accent, #2b4a6f));
}
.teacher-stream-row-update {
  background: color-mix(in srgb, var(--rm-class-color, var(--red)) 4%, var(--paper) 96%);
}
/* Clickable assignment cards in the Stream — whole card jumps to
   the Classwork tab + scrolls to the matching row. */
.teacher-stream-row-clickable {
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast);
}
.teacher-stream-row-clickable:hover {
  background: color-mix(in srgb, var(--rm-class-color, var(--red)) 5%, var(--paper) 95%);
  border-color: var(--rm-class-color, var(--ink-fade));
}
.teacher-stream-row-clickable:focus {
  outline: 2px solid var(--red);
  outline-offset: 2px;
}
/* Brief flash on the target row in Classwork after navigation lands. */
.teacher-assignment-row.row-focus-flash {
  animation: rm-row-focus-flash 1.4s ease;
}
@keyframes rm-row-focus-flash {
  0%   { background: transparent; box-shadow: 0 0 0 0 rgba(184, 56, 41, 0); }
  25%  { background: var(--red-wash); box-shadow: 0 0 0 4px rgba(184, 56, 41, 0.25); }
  100% { background: transparent; box-shadow: 0 0 0 0 rgba(184, 56, 41, 0); }
}
.teacher-stream-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-bottom: 4px;
}
.teacher-stream-kind {
  font-weight: 600;
  color: var(--ink-soft);
}
.teacher-stream-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
  margin-bottom: 4px;
}
.teacher-stream-body {
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
  white-space: pre-wrap;
}

/* Update composer (on each Stream assignment row) */
.teacher-update-disclosure { margin-top: 10px; }
.teacher-update-disclosure summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--ink-soft);
  padding: 4px 0;
}
.teacher-update-disclosure summary:hover { color: var(--ink); }
.teacher-update-form {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.teacher-update-form textarea {
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
}
.teacher-update-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-color: transparent;
}

/* People tab */
.teacher-people-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 0;
  border-bottom: 1px solid var(--hair);
}
.teacher-people-header strong {
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.teacher-people-self {
  font-size: 13px;
  color: var(--ink);
}
.teacher-roster-toggle {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-soft);
  cursor: pointer;
}
.teacher-people-list {
  margin-top: 8px;
  display: flex;
  flex-direction: column;
}
.teacher-people-row {
  padding: 8px 0;
  border-bottom: 1px solid var(--hair);
}
.teacher-people-row:last-child { border-bottom: 0; }
.teacher-people-name { font-size: 13px; font-weight: 500; color: var(--ink); }
.teacher-people-meta { font-size: 11.5px; color: var(--ink-fade); margin-top: 2px; }

/* ═══ Top-bar dashboard button ═════════════════════════════════════
   Replaces the audio button as the primary right-side icon for
   student/teacher roles. Editor/Author still see the audio bubble. */
.topbar-bell-btn,
.topbar-dashboard-btn {
  position: relative;
}
.topbar-bell-glyph { display: inline-flex; align-items: center; justify-content: center; }

/* Notifications flyout — popover anchored under the bell. */
.notifications-flyout {
  position: fixed;
  top: calc(var(--tb-h) + 8px);
  right: 12px;
  width: 360px;
  max-width: calc(100vw - 24px);
  max-height: calc(100vh - var(--tb-h) - 24px);
  z-index: 90;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(28,26,23,0.10);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.notifications-flyout-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 12px;
  border-bottom: 1px solid var(--hair);
  font-size: 13px;
}
.notifications-flyout-header .ghost-btn { font-size: 11.5px; padding: 4px 10px; }
.notifications-list {
  overflow-y: auto;
  padding: 4px 0;
}
.notifications-empty {
  padding: 20px;
  text-align: center;
  color: var(--ink-soft);
}
.notification-row {
  display: grid;
  /* glyph | body | unread-dot | dismiss-X */
  grid-template-columns: 24px 1fr 8px 20px;
  align-items: start;
  gap: 8px;
  width: 100%;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  border-top: 1px solid var(--hair);
  cursor: pointer;
  text-align: left;
  position: relative;
}
.notification-row-count {
  display: inline-block;
  margin-left: 6px;
  background: var(--red);
  color: var(--paper);
  font-size: 9.5px;
  font-weight: 600;
  padding: 1px 6px;
  border-radius: 999px;
  vertical-align: 1px;
}
.notification-row-dismiss {
  align-self: center;
  background: transparent;
  border: 0;
  color: var(--ink-fade);
  font-size: 14px;
  line-height: 1;
  padding: 2px 4px;
  border-radius: 4px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 100ms ease, background 100ms ease, color 100ms ease;
}
.notification-row:hover .notification-row-dismiss,
.notification-row:focus-within .notification-row-dismiss {
  opacity: 1;
}
.notification-row-dismiss:hover {
  background: var(--paper-edge);
  color: var(--ink);
}
.notification-row:first-child { border-top: 0; }
.notification-row:hover { background: var(--paper-edge); }
.notification-row.is-unread { background: color-mix(in srgb, var(--red) 4%, var(--paper) 96%); }
.notification-row-glyph { font-size: 14px; padding-top: 1px; }
.notification-row-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.notification-row-title {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.notification-row-snippet {
  font-size: 12px;
  color: var(--ink-soft);
  line-height: 1.35;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.notification-row-when { font-size: 10.5px; color: var(--ink-fade); }
.notification-row-dot {
  width: 8px;
  height: 8px;
  background: var(--red);
  border-radius: 50%;
  margin-top: 6px;
}
.topbar-dashboard-glyph { font-size: 16px; line-height: 1; }
.topbar-dashboard-badge {
  position: absolute;
  top: 2px;
  right: 2px;
  min-width: 16px;
  height: 16px;
  padding: 0 4px;
  border-radius: 8px;
  background: var(--red);
  color: var(--paper);
  font-size: 10px;
  font-weight: 600;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  line-height: 1;
}

/* ═══ Style Guide panel (Consistency Layer v1) ═════════════════════
   Sibling of the editorial memo. Right-edge slide-in for editor +
   author roles. Hosts the Decisions list + the Run-consistency-pass
   action. See CONSISTENCY_LAYER_SPEC.md §9 for the layout spec. */
.style-guide-panel {
  position: fixed;
  top: var(--tb-h);
  right: 0;
  bottom: 0;
  width: 440px;
  max-width: 100vw;
  z-index: 64;
  background: var(--paper);
  border-left: 1px solid var(--hair-strong);
  box-shadow: -2px 0 12px rgba(28,26,23,0.06);
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1);
}
.style-guide-panel[hidden] {
  display: flex;
  transform: translateX(100%);
  pointer-events: none;
}
.style-guide-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.style-guide-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.style-guide-toolbar {
  padding: 12px 16px;
  border-bottom: 1px solid var(--hair);
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.style-guide-preset summary {
  cursor: pointer;
  /* Strip the default disclosure triangle — entire summary is the
     toggle target instead of a small arrow icon. */
  list-style: none;
  font-size: 12.5px;
  color: var(--ink-soft);
  padding: 6px 8px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: transparent;
  border: 1px solid transparent;
  transition: background 100ms ease, border-color 100ms ease;
}
.style-guide-preset summary::-webkit-details-marker { display: none; }
.style-guide-preset summary:hover {
  color: var(--ink);
  background: var(--paper-edge);
  border-color: var(--hair);
}
.style-guide-preset[open] summary {
  background: var(--paper-edge);
  border-color: var(--hair);
  color: var(--ink);
  font-weight: 600;
}
.style-guide-preset-summary-label { font-weight: 600; font-size: 13px; }
.style-guide-preset-summary-hint {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-fade);
  font-weight: 500;
}
.style-guide-preset[open] .style-guide-preset-summary-hint { display: none; }

/* "?" info button next to each preset label */
.style-guide-preset-help {
  margin-left: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  border: 1px solid var(--hair-strong);
  background: var(--paper);
  color: var(--ink-fade);
  font-size: 10px;
  font-weight: 600;
  cursor: help;
  padding: 0;
  line-height: 1;
}
.style-guide-preset-help:hover {
  color: var(--ink);
  border-color: var(--ink-2);
  background: var(--paper-edge);
}
.style-guide-preset-help.is-active {
  color: var(--paper);
  background: var(--ink);
  border-color: var(--ink);
}
.style-guide-preset-help-text {
  margin: 4px 0 8px 88px; /* indent to align under preset row buttons */
  padding: 8px 12px;
  background: var(--paper-edge);
  border-left: 3px solid var(--accent, #2b4a6f);
  border-radius: 0 6px 6px 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.style-guide-preset-help-text strong { color: var(--ink); font-weight: 600; }
.style-guide-preset-body {
  margin-top: 8px;
  padding: 10px 12px;
  background: var(--paper-edge);
  border-radius: 6px;
}
.style-guide-preset-body p {
  margin: 0 0 8px;
}
.style-guide-preset-actions {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
}
.style-guide-preset-row {
  display: grid;
  grid-template-columns: 80px 1fr 1fr;
  gap: 6px;
  align-items: center;
  padding: 4px 0;
}
.style-guide-preset-row .ghost-btn { font-size: 11.5px; padding: 4px 8px; }
.style-guide-preset-label {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-soft);
}
.style-guide-footer-actions {
  display: flex;
  gap: 6px;
  align-items: center;
}
.style-guide-footer-actions .ghost-btn { font-size: 11.5px; padding: 4px 10px; }
.style-guide-filters {
  display: flex;
  gap: 8px;
  align-items: center;
}
.style-guide-filters input[type="search"] {
  flex: 1;
  font-family: var(--sans);
  font-size: 13px;
  padding: 6px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}
.style-guide-filters select {
  font-family: var(--sans);
  font-size: 12.5px;
  padding: 6px 8px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}
.style-guide-list {
  flex: 1;
  overflow-y: auto;
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.style-guide-decision-row {
  padding: 10px 12px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
}
.style-guide-decision-row.is-pending {
  border-color: color-mix(in srgb, var(--red) 30%, var(--hair) 70%);
  background: color-mix(in srgb, var(--red) 3%, var(--paper) 97%);
}
.style-guide-decision-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-fade);
  margin-bottom: 4px;
}
.style-guide-decision-category { font-weight: 600; color: var(--ink-soft); }
.style-guide-decision-source   { font-style: italic; }
.style-guide-decision-question {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 4px;
}
.style-guide-decision-notes {
  font-size: 12px;
  color: var(--ink-soft);
  font-style: italic;
  margin-bottom: 8px;
  line-height: 1.4;
}
.style-guide-decision-variants {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 8px;
}
.style-guide-variant-btn {
  font-family: var(--sans);
  font-size: 12.5px;
  padding: 4px 10px;
  border: 1px solid var(--hair-strong);
  background: var(--paper);
  color: var(--ink-soft);
  border-radius: 999px;
  cursor: pointer;
}
.style-guide-variant-btn:hover { border-color: var(--ink-2); color: var(--ink); }
.style-guide-variant-btn.is-active {
  background: var(--ink);
  color: var(--paper);
  border-color: var(--ink);
}
.style-guide-decision-actions {
  display: flex;
  justify-content: space-between;
  align-items: center;
  font-size: 11.5px;
}
.style-guide-decision-actions .ghost-btn {
  padding: 3px 10px;
  font-size: 11.5px;
}
.style-guide-pending-pill {
  display: inline-block;
  padding: 2px 8px;
  background: var(--red);
  color: var(--paper);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  border-radius: 4px;
}
.style-guide-footer {
  padding: 12px 16px;
  border-top: 1px solid var(--hair);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
}
.style-guide-status {
  font-size: 11.5px;
  color: var(--ink-fade);
}

/* FAB picker caret + popover menu — kept in CSS only so legacy markup
   still renders cleanly; the elements were removed from the HTML and
   are no longer used. Tab strip in the panel handles pane switching. */
.fab-picker-caret { display: none !important; }
.right-pane-picker {
  position: fixed;
  /* FAB sits at top:calc(var(--tb-h) + 24px) right:24px and is 52px
     wide. Picker drops just below it, right-aligned with the FAB. */
  top: calc(var(--tb-h) + 84px);
  right: 24px;
  z-index: 70;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 10px;
  box-shadow: 0 8px 24px rgba(28,26,23,0.10);
  min-width: 240px;
  overflow: hidden;
}
.right-pane-picker-item {
  display: flex;
  width: 100%;
  align-items: flex-start;
  gap: 10px;
  padding: 10px 12px;
  background: transparent;
  border: 0;
  cursor: pointer;
  text-align: left;
}
.right-pane-picker-item:hover { background: var(--paper-edge); }
.right-pane-picker-item.is-active { background: color-mix(in srgb, var(--ink) 6%, var(--paper) 94%); }
.right-pane-picker-item .rpp-glyph {
  width: 22px;
  height: 22px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 14px;
  color: var(--red);
}
.right-pane-picker-item .rpp-label {
  display: flex;
  flex-direction: column;
  gap: 1px;
}
.right-pane-picker-item .rpp-main { font-size: 13px; font-weight: 500; color: var(--ink); }
.right-pane-picker-item .rpp-sub  { font-size: 11px; color: var(--ink-fade); }

/* ═══ Assignment info panel (student-side) ═════════════════════════ */
.assignment-info-panel {
  position: fixed;
  top: var(--tb-h);
  right: 0;
  bottom: 0;
  width: 380px;
  max-width: 100vw;
  z-index: 64;
  background: var(--paper);
  border-left: 1px solid var(--hair-strong);
  box-shadow: -2px 0 12px rgba(28,26,23,0.06);
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1);
}
.assignment-info-panel[hidden] {
  display: flex;
  transform: translateX(100%);
  pointer-events: none;
}
.assignment-info-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.assignment-info-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}
.assignment-info-body {
  flex: 1;
  overflow-y: auto;
  padding: 14px 16px;
}
.assignment-info-header-block {
  display: grid;
  grid-template-columns: 6px 1fr;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 12px;
}
.assignment-info-stripe { width: 6px; }
.assignment-info-headbody { padding: 10px 12px; }
.assignment-info-class {
  font-size: 11.5px;
  letter-spacing: 0.04em;
  color: var(--ink-fade);
  font-weight: 600;
  text-transform: uppercase;
  margin-bottom: 2px;
}
.assignment-info-title {
  font-size: 16px;
  font-weight: 600;
  color: var(--ink);
  margin-bottom: 2px;
}
.assignment-info-due {
  font-size: 12px;
  color: var(--ink-soft);
}
.assignment-info-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 5px;
  margin-top: 6px;
}
.assignment-info-chip {
  display: inline-block;
  font-size: 10.5px;
  font-family: var(--mono);
  letter-spacing: 0.02em;
  color: var(--ink-soft);
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-radius: 999px;
  padding: 2px 8px;
}

/* =========================================================================
   Submission block at the bottom of the student's Assignment tab —
   status pill, attempt counter, primary Submit / Resubmit button.
   ========================================================================= */
.assignment-info-submit-section h3 { margin-bottom: 8px; }
.assignment-submit-block {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 12px 14px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
}
.assignment-submit-state {
  display: flex;
  align-items: center;
  gap: 10px;
}
.assignment-submit-status {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 3px 10px;
  border-radius: 999px;
  text-transform: uppercase;
}
.assignment-submit-status.status-not-started { background: var(--paper-edge); color: var(--ink-fade); }
.assignment-submit-status.status-in-progress { background: rgba(201, 138, 26, 0.12); color: #c98a1a; }
.assignment-submit-status.status-submitted   { background: rgba(74, 138, 74, 0.12); color: #4a8a4a; }
.assignment-submit-status.status-graded      { background: rgba(60, 100, 180, 0.12); color: #3c64b4; }
.assignment-submit-attempts {
  font-size: 11.5px;
  color: var(--ink-soft);
  font-family: var(--mono);
}
.assignment-submit-meta {
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-top: -2px;
}
.assignment-submit-btn {
  align-self: stretch;
  margin-top: 4px;
}
.assignment-submit-btn[disabled] {
  opacity: 0.5;
  cursor: not-allowed;
}
.assignment-submit-help {
  font-size: 11px;
  color: var(--ink-fade);
  text-align: center;
  margin-top: -2px;
}

/* =========================================================================
   Sources to cite — checklist of every citation mark in the doc with
   click-to-jump rows. Lives in the student's Assignment tab.
   ========================================================================= */
.citations-count {
  display: inline-block;
  font-family: var(--mono);
  font-size: 11px;
  color: var(--red);
  background: var(--red-wash);
  padding: 1px 8px;
  border-radius: 999px;
  vertical-align: 2px;
  margin-left: 6px;
  font-weight: 500;
}
.citations-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
  margin-top: 8px;
}
.citations-row {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 6px;
  padding: 8px 10px;
  display: grid;
  grid-template-columns: 24px 1fr;
  gap: 8px;
  align-items: baseline;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.citations-row:hover {
  border-color: var(--red);
  background: var(--paper-edge);
}
.citations-num {
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  color: var(--red);
  text-align: center;
}
.citations-snippet {
  font-family: var(--serif);
  font-size: 13px;
  color: var(--ink);
  line-height: 1.35;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* =========================================================================
   Rubric editor — collapsible block on the teacher's create-assignment form.
   ========================================================================= */
.rubric-editor-wrap {
  margin-top: 8px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 8px 12px;
  background: var(--paper);
}
.rubric-editor-summary {
  font-size: 12.5px;
  color: var(--ink-soft);
  cursor: pointer;
  user-select: none;
}
.rubric-editor-wrap[open] .rubric-editor-summary {
  margin-bottom: 8px;
  color: var(--ink);
  font-weight: 500;
}
.rubric-editor-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.rubric-editor-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.rubric-editor-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.5fr) auto;
  gap: 6px;
  align-items: center;
}
.rubric-editor-row input[type="text"] {
  padding: 6px 8px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  font-size: 12.5px;
  font-family: var(--sans);
}
.rubric-editor-remove {
  padding: 4px 10px;
  font-size: 14px;
  line-height: 1;
}
.rubric-apply-row {
  display: flex;
  gap: 6px;
  margin-bottom: 6px;
}
.rubric-apply-row select {
  padding: 6px 8px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  font-size: 12.5px;
  font-family: var(--sans);
  background: var(--paper);
  width: 100%;
}

/* =========================================================================
   Rubric SCORER — teacher fills this in inside the doc workspace after
   reviewing a submission. Each criterion gets a 4-button level picker.
   ========================================================================= */
.rubric-scorer {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 4px 0;
}
.rubric-scorer-empty {
  font-size: 12px;
  color: var(--ink-fade);
  font-style: italic;
}
.rubric-scorer-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 4px;
  padding: 6px 8px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
}
.rubric-scorer-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
}
.rubric-scorer-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
}
.rubric-scorer-desc {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.rubric-scorer-levels {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  margin-top: 4px;
}
.rubric-scorer-level {
  appearance: none;
  border: 1px solid var(--hair);
  border-radius: 999px;
  background: var(--paper);
  font-family: var(--sans);
  font-size: 11px;
  padding: 3px 10px;
  cursor: pointer;
  color: var(--ink-soft);
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.rubric-scorer-level:hover { border-color: var(--ink-fade); color: var(--ink); }
.rubric-scorer-level.is-chosen {
  background: var(--red);
  border-color: var(--red);
  color: white;
}
.rubric-scorer-level[data-level="1"].is-chosen { background: #b34a3a; border-color: #b34a3a; }
.rubric-scorer-level[data-level="2"].is-chosen { background: #c98a1a; border-color: #c98a1a; }
.rubric-scorer-level[data-level="3"].is-chosen { background: #5d9a4a; border-color: #5d9a4a; }
.rubric-scorer-level[data-level="4"].is-chosen { background: #3a6b8a; border-color: #3a6b8a; }

/* =========================================================================
   Student-facing rubric display — what they see after the teacher scores.
   Same rows, but read-only and the chosen level is the only visible one.
   ========================================================================= */
.rubric-score-display {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.rubric-score-row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 8px;
  align-items: center;
  padding: 6px 10px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
}
.rubric-score-name {
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
}
.rubric-score-level {
  font-family: var(--mono);
  font-size: 10.5px;
  letter-spacing: 0.04em;
  padding: 2px 10px;
  border-radius: 999px;
  white-space: nowrap;
  color: white;
}
.rubric-score-level[data-level="1"] { background: #b34a3a; }
.rubric-score-level[data-level="2"] { background: #c98a1a; }
.rubric-score-level[data-level="3"] { background: #5d9a4a; }
.rubric-score-level[data-level="4"] { background: #3a6b8a; }
.rubric-score-level.is-unscored { background: var(--hair); color: var(--ink-fade); }
.assignment-info-section {
  margin-top: 16px;
}
.assignment-info-section h3 {
  margin: 0 0 8px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.assignment-info-instructions {
  margin: 0;
  font-size: 13px;
  line-height: 1.5;
  white-space: pre-wrap;
  color: var(--ink);
}
.assignment-info-updates {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.assignment-info-update {
  border-left: 3px solid var(--red);
  background: color-mix(in srgb, var(--red) 4%, var(--paper) 96%);
  padding: 8px 12px;
  border-radius: 0 6px 6px 0;
}
.assignment-info-update-meta {
  font-size: 11px;
  color: var(--ink-fade);
  margin-bottom: 2px;
}
.assignment-info-update-body {
  font-size: 13px;
  line-height: 1.45;
  white-space: pre-wrap;
  color: var(--ink);
}
.assignment-info-messages {
  max-height: 280px;
  min-height: 80px;
  padding: 6px 0;
}
.assignment-info-msg-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding: 12px 16px;
  border-top: 1px solid var(--hair);
}
.assignment-info-msg-form textarea {
  flex: 1;
  resize: vertical;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}
.assignment-info-msg-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-color: transparent;
}

/* Assignment messages modal */
.assignment-messages-list {
  flex: 1;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 8px 0;
  max-height: 50vh;
  min-height: 200px;
}
.assignment-message-row {
  display: flex;
  flex-direction: column;
  max-width: 80%;
}
.assignment-message-row.is-mine {
  align-self: flex-end;
  align-items: flex-end;
}
.assignment-message-bubble {
  padding: 8px 12px;
  border-radius: 12px;
  font-size: 13px;
  line-height: 1.45;
  background: var(--paper-edge);
  color: var(--ink);
  white-space: pre-wrap;
}
.assignment-message-row.is-mine .assignment-message-bubble {
  background: var(--red);
  color: var(--paper);
}
.assignment-message-meta {
  font-size: 10.5px;
  color: var(--ink-fade);
  margin-top: 2px;
}
.assignment-messages-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  margin-top: 12px;
  border-top: 1px solid var(--hair);
  padding-top: 12px;
}
.assignment-messages-form textarea {
  flex: 1;
  resize: vertical;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}
.assignment-messages-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-color: transparent;
}

/* Student assignment row — extend with actions row for Messages */
.student-assignment-actions {
  display: flex;
  gap: 6px;
  margin-top: 8px;
}
.student-assignment-actions .ghost-btn {
  font-size: 11.5px;
  padding: 4px 10px;
}

/* ═══ Student dashboard ════════════════════════════════════════
   Filter chips, sort menu, assignment cards, join-class preview. */

.student-assignments-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 10px;
  flex-wrap: wrap;
}
.student-filter-chips {
  display: inline-flex;
  border: 1px solid var(--hair);
  border-radius: 999px;
  overflow: hidden;
  background: var(--paper);
}
.student-filter-chip {
  background: transparent;
  border: 0;
  padding: 6px 14px;
  font-size: 12px;
  color: var(--ink-soft);
  cursor: pointer;
  border-right: 1px solid var(--hair);
}
.student-filter-chip:last-child { border-right: 0; }
.student-filter-chip:hover { color: var(--ink); }
.student-filter-chip.is-active {
  background: var(--ink);
  color: var(--paper);
}
.student-sort-menus {
  display: flex;
  gap: 12px;
  align-items: center;
  font-size: 12px;
  color: var(--ink-soft);
}
.student-sort-menus label {
  display: flex;
  align-items: center;
  gap: 6px;
}
.student-sort-menus select {
  font-family: var(--sans);
  font-size: 12.5px;
  padding: 4px 8px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}
.student-clear-class-chip {
  display: inline-block;
  margin-bottom: 8px;
  background: var(--paper-edge);
  color: var(--ink-soft);
  border: 1px solid var(--hair);
  font-size: 11.5px;
  padding: 4px 10px;
  border-radius: 999px;
  cursor: pointer;
}
.student-clear-class-chip:hover { color: var(--ink); border-color: var(--ink-2); }

/* Assignment rows */
.student-assignments-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.student-assignment-row {
  display: grid;
  grid-template-columns: 6px 1fr;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
  cursor: pointer;
  outline: none;
  transition: border-color 100ms ease, box-shadow 100ms ease;
}
.student-assignment-row:hover,
.student-assignment-row:focus-visible {
  border-color: var(--ink-2);
  box-shadow: 0 2px 8px rgba(0,0,0,0.04);
}
.student-assignment-stripe { width: 6px; }
.student-assignment-body { padding: 10px 14px; }
.student-assignment-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-bottom: 3px;
}
.student-assignment-class {
  font-weight: 600;
  color: var(--ink-soft);
}
.student-assignment-due { white-space: nowrap; }
.student-assignment-title {
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
}
.student-assignment-snippet {
  margin: 4px 0 0;
  font-size: 12.5px;
  line-height: 1.45;
  color: var(--ink-soft);
}

/* Join class preview */
.student-join-preview {
  display: grid;
  grid-template-columns: 6px 1fr;
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
  margin: 10px 0 4px;
}
.student-join-preview-stripe { width: 6px; }
.student-join-preview-body { padding: 10px 12px; }
.student-join-preview-name { font-weight: 600; font-size: 14px; color: var(--ink); }
.student-join-preview-sub  { font-size: 12px; color: var(--ink-fade); }
.student-join-preview-teacher {
  font-size: 12.5px;
  color: var(--ink-soft);
  margin-top: 4px;
}
.student-join-error {
  font-size: 12.5px;
  color: var(--red);
  background: color-mix(in srgb, var(--red) 6%, var(--paper) 94%);
  border: 1px solid color-mix(in srgb, var(--red) 30%, transparent);
  padding: 8px 10px;
  border-radius: 6px;
  margin: 8px 0 4px;
}

/* Teacher dashboard — assignments + submissions list */
.teacher-assignments-list {
  display: flex;
  flex-direction: column;
  gap: 8px;
  margin-bottom: 12px;
}
.teacher-assignment-row {
  position: relative;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
  padding: 10px 12px 10px 18px;
  overflow: hidden;
}
/* Color stripe along the left edge tying the assignment to its
   parent classroom's color. Inline --rm-class-color is set by
   renderTeacherAssignmentRow. */
.teacher-assignment-stripe {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 6px;
  background: var(--rm-class-color, var(--accent, #2b4a6f));
}
.teacher-assignment-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
  margin-bottom: 6px;
}
.teacher-assignment-title { font-weight: 600; font-size: 13.5px; color: var(--ink); }
/* Title-as-button — used in the Classwork tab. Clicking jumps to the
   teacher workspace for that assignment (resumes the last submission
   they were grading, or picks the next one up to review). Visual is
   a plain text link so the row stays calm; hover gives it a soft red
   underline + cursor so the click affordance is unmistakable. */
button.teacher-assignment-title-link {
  background: transparent;
  border: 0;
  padding: 0;
  margin: 0;
  text-align: left;
  font: inherit;
  font-weight: 600;
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  transition: color var(--t-fast), text-decoration-color var(--t-fast);
  text-decoration: underline transparent solid 1.5px;
  text-underline-offset: 3px;
}
button.teacher-assignment-title-link:hover,
button.teacher-assignment-title-link:focus-visible {
  color: var(--red);
  text-decoration-color: var(--red);
  outline: none;
}
button.teacher-assignment-title-link:focus-visible {
  outline: 2px solid rgba(184, 56, 41, 0.35);
  outline-offset: 3px;
  border-radius: 4px;
}
.teacher-assignment-meta  { font-size: 11.5px; color: var(--ink-fade); }
.teacher-assignment-link-row {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-bottom: 6px;
}
.teacher-assignment-link {
  flex: 1;
  background: var(--paper-edge);
  padding: 4px 8px;
  border-radius: 4px;
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-soft);
  overflow-x: auto;
  white-space: nowrap;
}
.teacher-assignment-copy {
  font-size: 11.5px;
  padding: 4px 10px;
  white-space: nowrap;
}
.teacher-assignment-submissions summary {
  cursor: pointer;
  font-size: 12px;
  color: var(--ink-soft);
  padding: 4px 0;
}
.teacher-assignment-submissions summary:hover { color: var(--ink); }
.teacher-assignment-submissions-list {
  margin-top: 6px;
  padding-left: 12px;
  border-left: 2px solid var(--hair);
}
.teacher-submission-row {
  padding: 6px 0;
  border-bottom: 1px solid var(--hair);
  font-size: 12px;
}
.teacher-submission-row:last-child { border-bottom: 0; }
.teacher-submission-meta {
  display: flex;
  gap: 4px;
  flex-wrap: wrap;
  color: var(--ink-soft);
}
.teacher-submission-meta strong { color: var(--ink); font-weight: 600; }

/* Create-assignment disclosure */
.teacher-create-disclosure {
  margin: 8px 0 16px;
}
.teacher-create-trigger {
  cursor: pointer;
  font-size: 13px;
  color: var(--ink-soft);
  padding: 6px 0;
}
.teacher-create-trigger:hover { color: var(--ink); }
.teacher-create-form {
  padding: 12px;
  margin-top: 8px;
  background: var(--paper-edge);
  border-radius: 8px;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.teacher-create-form textarea {
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
  resize: vertical;
}
.teacher-create-form textarea:focus {
  outline: 2px solid var(--accent);
  outline-offset: -2px;
  border-color: transparent;
}

/* Review panel — signals list, summary, scrubbable replay. (Class
   names retain the legacy `provenance-review-*` prefix so JS selectors keep
   working without a refactor; only user-visible text was renamed.) */
.provenance-review-host { margin-bottom: 16px; }
.provenance-review-host > .settings-hint { margin-bottom: 12px; }
.provenance-review-title {
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--ink);
  margin: 14px 0 4px;
}
.provenance-review-summary {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  margin: 12px 0;
  background: var(--paper);
}
/* New events-to-review summary tile (Q1 resolved). Replaces the
   aggregate %-score circle with a clearer count of discrete events. */
.provenance-review-summary-events {
  width: 86px;
  height: 86px;
  border-radius: 12px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 2px solid var(--hair-strong);
  font-family: var(--sans);
}
.provenance-review-summary-events[data-level="green"]  { border-color: #4a8a4a; color: #4a8a4a; background: rgba(74,138,74,0.06); }
.provenance-review-summary-events[data-level="yellow"] { border-color: #c98a1a; color: #c98a1a; background: rgba(201,138,26,0.06); }
.provenance-review-summary-events[data-level="red"]    { border-color: var(--red); color: var(--red); background: rgba(184,56,41,0.08); }
.provenance-review-summary-events .provenance-review-summary-value {
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
}
.provenance-review-summary-events .provenance-review-summary-label {
  font-size: 9px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: 4px;
  text-align: center;
  padding: 0 4px;
}
.provenance-review-summary-meta {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  font-size: 12px;
  color: var(--ink-2);
}
.provenance-review-summary-meta strong { color: var(--ink); font-weight: 600; }

/* Clean session — no items to review. */
.provenance-review-clean {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  background: rgba(74,138,74,0.05);
  border: 1px solid rgba(74,138,74,0.3);
  border-radius: 8px;
  font-size: 13px;
  color: var(--ink-2);
  line-height: 1.5;
  margin-bottom: 16px;
}
.provenance-review-clean-glyph {
  color: #4a8a4a;
  font-size: 20px;
  font-weight: 700;
  flex-shrink: 0;
}

/* Flagged events list. */
.provenance-review-flagged {
  list-style: none;
  margin: 0 0 16px;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.provenance-review-flagged-item {
  display: grid;
  grid-template-columns: 60px 1fr;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
}
.provenance-review-flagged-item[data-severity="high"]   { border-left: 3px solid var(--red); }
.provenance-review-flagged-item[data-severity="medium"] { border-left: 3px solid #c98a1a; }
.provenance-review-flagged-stamp {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-fade);
  align-self: flex-start;
  padding-top: 2px;
}
.provenance-review-flagged-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 4px;
}
.provenance-review-flagged-category {
  font-size: 12.5px;
  font-weight: 600;
  color: var(--ink);
}
.provenance-review-flagged-jump {
  appearance: none;
  background: transparent;
  border: 0;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--red);
  cursor: pointer;
  padding: 2px 4px;
}
.provenance-review-flagged-jump:hover { text-decoration: underline; }
.provenance-review-flagged-reason {
  font-size: 12px;
  color: var(--ink-2);
  line-height: 1.45;
}

/* Context excerpt — the actual prose around the suspect paste site.
   The teacher's primary review surface: "what content is the system
   pointing at?" The highlighted span is the recorded paste range
   (approximate — positions drift after edits). Compact serif body so
   it reads like a real document quote, not a debug dump. */
.provenance-review-flagged-context {
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--rule, #d8d2c3);
}
.provenance-review-flagged-context-label {
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--ink-fade);
  margin-bottom: 4px;
}
.provenance-review-flagged-context-quote {
  margin: 0;
  padding: 8px 12px;
  background: rgba(0, 0, 0, 0.025);
  border-left: 2px solid var(--rule, #d8d2c3);
  border-radius: 0 4px 4px 0;
  font-family: var(--serif);
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ink);
  white-space: pre-wrap;
  word-wrap: break-word;
  max-height: 240px;
  overflow-y: auto;
}
.provenance-review-flagged-context-mark {
  background: rgba(184, 56, 41, 0.18);
  color: var(--ink);
  border-radius: 2px;
  padding: 0 1px;
  box-shadow: inset 0 -1px 0 rgba(184, 56, 41, 0.5);
}
.provenance-review-flagged-context-ellipsis {
  color: var(--ink-fade);
  font-style: italic;
}
.provenance-review-flagged-context-trunc {
  display: inline-block;
  margin: 0 4px;
  padding: 0 6px;
  font-size: 10.5px;
  font-family: var(--sans);
  color: var(--ink-fade);
  background: rgba(0, 0, 0, 0.04);
  border-radius: 4px;
  vertical-align: middle;
}
.provenance-review-flagged-context-hint {
  margin-top: 6px;
  font-size: 10.5px;
  color: var(--ink-fade);
  font-style: italic;
  line-height: 1.5;
}
/* High-severity flags get a slightly louder mark colour so the eye
   lands on the chunk that matters most. */
.provenance-review-flagged-item[data-severity="high"] .provenance-review-flagged-context-mark {
  background: rgba(184, 56, 41, 0.26);
}

/* Cursor-trajectory mini-map — drawn under straight-cursor flags so
   the teacher can SEE the path the system thought was robotic.
   Start dot = green, end dot = red, samples = small dots, line
   between them. Uniform scaling preserves actual geometry. */
.prov-path-wrap {
  display: flex;
  align-items: center;
  gap: 14px;
  background: rgba(0, 0, 0, 0.025);
  border-left: 2px solid var(--rule, #d8d2c3);
  border-radius: 0 4px 4px 0;
  padding: 10px 12px;
}
.prov-path-svg {
  width: 280px;
  height: 140px;
  flex: 0 0 auto;
}
.prov-path-frame {
  fill: rgba(255, 255, 255, 0.6);
  stroke: var(--rule, #d8d2c3);
  stroke-width: 1;
}
.prov-path-line {
  fill: none;
  stroke: var(--red, #b83829);
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.85;
}
.prov-path-sample {
  fill: var(--red, #b83829);
  opacity: 0.55;
}
.prov-path-start { fill: #2f8a4a; stroke: #FAF8F2; stroke-width: 1.5; }
.prov-path-end   { fill: #b83829; stroke: #FAF8F2; stroke-width: 1.5; }
.prov-path-legend {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-2);
}
.prov-path-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.prov-path-legend-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
}
.prov-path-legend-start { background: #2f8a4a; }
.prov-path-legend-end   { background: #b83829; }
.prov-path-legend-stat {
  font-size: 10.5px;
  color: var(--ink-fade);
  font-style: italic;
}

/* "Non issue / Confirmed issue / Reset" decision row. Persists per
   flag so the teacher can triage through a long list without losing
   their place. Triaged items get .is-triaged on the parent which
   fades the card and shrinks the chrome a touch. */
.provenance-review-flagged-decision {
  display: flex;
  gap: 8px;
  align-items: center;
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px dashed var(--rule, #d8d2c3);
}
.provenance-review-flagged-decision-btn {
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 500;
  padding: 5px 12px;
  border-radius: 999px;
  border: 1px solid var(--rule, #d8d2c3);
  background: var(--paper, #FAF8F2);
  color: var(--ink-2);
  cursor: pointer;
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
}
.provenance-review-flagged-decision-btn:hover {
  background: rgba(0, 0, 0, 0.04);
  border-color: var(--ink-fade);
  color: var(--ink);
}
.provenance-review-flagged-decision-btn.is-active {
  background: rgba(47, 138, 74, 0.12);
  border-color: #2f8a4a;
  color: #2f8a4a;
  font-weight: 600;
}
.provenance-review-flagged-decision-btn-warn.is-active {
  background: rgba(184, 56, 41, 0.12);
  border-color: var(--red, #b83829);
  color: var(--red, #b83829);
}
.provenance-review-flagged-decision-clear {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 500;
  padding: 4px 8px;
  border: 0;
  background: transparent;
  color: var(--ink-fade);
  cursor: pointer;
  margin-left: auto;
  border-radius: 4px;
}
.provenance-review-flagged-decision-clear:hover {
  background: rgba(0, 0, 0, 0.05);
  color: var(--ink-2);
}
/* Triaged flags fade so the eye finds the unreviewed ones first. */
.provenance-review-flagged-item.is-triaged {
  opacity: 0.55;
  transition: opacity var(--t-fast);
}
.provenance-review-flagged-item.is-triaged:hover {
  opacity: 1;
}

/* ═══ Provenance replay overlay ═══════════════════════════════════
   Body-level overlay that draws the cursor + trail OVER the canvas
   when a teacher clicks "Jump to replay" on a flag. Recording
   coordinates are mapped uniformly to the current window so the
   geometry of the original motion is preserved on screen. */
.prov-replay-overlay {
  position: fixed;
  inset: 0;
  pointer-events: none;     /* clicks pass through to the canvas */
  z-index: 100;             /* over canvas + memo panel content */
}
.prov-replay-overlay-trail {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
}
.prov-replay-overlay-trail polyline {
  fill: none;
  stroke: var(--red, #b83829);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.35;
  filter: drop-shadow(0 0 6px rgba(184, 56, 41, 0.4));
}
.prov-replay-overlay-cursor {
  position: absolute;
  top: 0;
  left: 0;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--red, #b83829);
  border: 3px solid rgba(255, 255, 255, 0.85);
  box-shadow:
    0 0 0 2px rgba(184, 56, 41, 0.5),
    0 4px 18px rgba(184, 56, 41, 0.45);
  margin-left: -9px;        /* center on the recorded point */
  margin-top:  -9px;
  transition: transform 60ms linear;
  will-change: transform;
}
/* When the overlay is freshly shown, briefly pulse the cursor so
   the eye finds it. */
@keyframes prov-replay-pulse {
  0%, 100% { transform: scale(1); box-shadow: 0 0 0 2px rgba(184, 56, 41, 0.5), 0 4px 18px rgba(184, 56, 41, 0.45); }
  50%      { transform: scale(1.5); box-shadow: 0 0 0 8px rgba(184, 56, 41, 0.0), 0 4px 18px rgba(184, 56, 41, 0.6); }
}
.prov-replay-overlay:not([hidden]) .prov-replay-overlay-cursor {
  animation: prov-replay-pulse 1.4s ease-out 1;
}
.prov-replay-overlay-caption {
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  background: rgba(20, 18, 16, 0.88);
  color: #FAF8F2;
  font-family: var(--sans);
  font-size: 12px;
  padding: 6px 12px;
  border-radius: 999px;
  pointer-events: none;
  max-width: 80vw;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* ═══ Provenance PIP replay ════════════════════════════════════════
   A floating, picture-in-picture replay surface that pops up over the
   document canvas when a teacher clicks "Jump to replay" on a flag.
   Unlike the body-level overlay (which projects onto the live
   canvas), the PIP draws into its OWN small stage so the teacher
   sees the recorded motion in isolation — and the actual document
   text stays visible behind it. Sized to roughly the size of an
   annotation popover; draggable-out-of-the-way feel without the
   weight of a modal. */
.prov-pip-replay {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: clamp(300px, 28vw, 380px);
  background: var(--paper, #FAF8F2);
  color: var(--ink, #1a1714);
  border: 1px solid var(--rule, rgba(0,0,0,0.12));
  border-radius: 14px;
  box-shadow:
    0 24px 60px rgba(0,0,0,0.22),
    0 4px 12px rgba(0,0,0,0.12);
  font-family: var(--sans);
  z-index: 200;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  transition: all 200ms cubic-bezier(.2,.6,.2,1);
}
.prov-pip-replay[hidden] { display: none; }
/* Fullscreen mode — true full-bleed. Stage takes ALL remaining
   vertical space after the header, scrubber, and log, so the page
   mirror gets the full viewport to spread out in. The log itself
   gets a higher max-height so paste events with many cursor moves
   don't truncate. */
.prov-pip-replay.is-fullscreen {
  right: 8px;
  bottom: 8px;
  top: 8px;
  left: 8px;
  width: auto;
  border-radius: 14px;
}
.prov-pip-replay.is-fullscreen .prov-pip-replay-stage {
  flex: 1 1 auto;
  min-height: 50vh;
  max-height: none;        /* let the stage grow to fill */
}
.prov-pip-replay.is-fullscreen .prov-pip-replay-log {
  max-height: 22vh;        /* was 160px — give it more breathing room */
}
.prov-pip-replay.is-fullscreen .prov-pip-text-paste-body {
  font-size: 14px;
}

.prov-pip-replay-head-btns {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}
.prov-pip-replay-head-left {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-width: 0;
}
.prov-pip-replay-nav {
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: var(--paper, #FAF8F2);
  color: var(--ink-2, #2a2520);
  font-family: inherit;
  font-size: 13px;
  font-weight: 600;
  line-height: 1;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: background 120ms ease;
}
.prov-pip-replay-nav:hover:not(:disabled) {
  background: rgba(0,0,0,0.05);
  color: var(--ink, #1a1714);
}
.prov-pip-replay-nav:disabled {
  opacity: 0.3;
  cursor: not-allowed;
}
.prov-pip-replay-counter {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10px;
  color: var(--ink-fade, #6a655e);
  letter-spacing: 0.04em;
  white-space: nowrap;
}
.prov-pip-replay-expand {
  appearance: none;
  border: 0;
  background: transparent;
  font-size: 14px;
  line-height: 1;
  color: var(--ink-fade, #6a655e);
  cursor: pointer;
  padding: 2px 6px;
  border-radius: 4px;
}
.prov-pip-replay-expand:hover {
  background: rgba(0,0,0,0.06);
  color: var(--ink, #1a1714);
}

/* ── Provenance review progress + bulk-dismiss bar ──
   Sits above the flagged list. Shows the teacher their triage
   progress at a glance and offers a one-click bulk dismissal for
   noisy categories. Updated live via refreshProgressIndicator(). */
.provenance-review-progress {
  margin: 0 0 14px;
  padding: 10px 12px;
  background: rgba(0, 0, 0, 0.025);
  border-radius: 8px;
}
.provenance-review-progress-bar {
  position: relative;
  height: 6px;
  background: var(--paper-edge, rgba(0,0,0,0.08));
  border-radius: 3px;
  overflow: hidden;
  margin-bottom: 8px;
}
.provenance-review-progress-fill {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: linear-gradient(90deg, #2c7d4d, #4e9d6e);
  border-radius: 3px;
  transition: width 220ms cubic-bezier(.2,.6,.2,1);
}
.provenance-review-progress-summary {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-2, #2a2520);
}
.provenance-review-progress-count {
  font-weight: 600;
  color: var(--ink, #1a1714);
}
.provenance-review-progress-confirmed { color: #b83829; }
.provenance-review-progress-nonissue  { color: #2c7d4d; }
.provenance-review-progress-pending   { color: var(--ink-fade, #6a655e); }
.provenance-review-progress-dot {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--ink-fade, #6a655e);
  opacity: 0.4;
}
.provenance-review-progress-actions {
  margin-left: auto;
  display: inline-flex;
  gap: 6px;
}
.provenance-review-bulk-btn {
  appearance: none;
  border: 1px solid rgba(0,0,0,0.15);
  background: var(--paper, #FAF8F2);
  color: var(--ink-2, #2a2520);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 500;
  padding: 4px 10px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 120ms ease;
}
.provenance-review-bulk-btn:hover {
  background: rgba(0,0,0,0.04);
  color: var(--ink, #1a1714);
}
.provenance-review-export-btn {
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
  border-color: var(--ink, #1a1714);
}
.provenance-review-export-btn:hover {
  background: var(--ink-2, #2a2520);
  color: var(--paper, #FAF8F2);
}

/* style-shift marker color — purple/violet so it visually
   distinguishes from paste (red), focus (amber), cursor (teal). */
.provenance-review-marker.replay-marker-style { background: #6b46c1; }

/* ── Composition fingerprint panel ──
   Shown above the flagged list. Gives the teacher a "at a glance"
   verdict on natural-vs-suspect composition behaviors, plus a
   chain-integrity badge proving the session history hasn't been
   tampered with. Collapsed by default to keep the dashboard tidy. */
.provenance-review-fingerprint {
  margin: 14px 0;
  padding: 10px 14px;
  background: rgba(0,0,0,0.025);
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
  border-radius: 8px;
  font-family: var(--sans);
}
.provenance-review-fingerprint > summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  cursor: pointer;
  list-style: none;
  font-size: 11px;
  letter-spacing: 0.04em;
  gap: 12px;
}
.provenance-review-fingerprint > summary::-webkit-details-marker { display: none; }
.cf-title {
  font-weight: 600;
  text-transform: uppercase;
  color: var(--ink-2, #2a2520);
  font-size: 10.5px;
  letter-spacing: 0.08em;
}
.cf-chain {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  padding: 3px 10px;
  border-radius: 999px;
}
.cf-chain-ok     { background: rgba(46,125,77,0.10);   color: #2c7d4d; }
.cf-chain-broken { background: rgba(184,56,41,0.10);   color: #b83829; font-weight: 600; }

.cf-bullets {
  list-style: none;
  padding: 0;
  margin: 12px 0 8px;
}
.cf-bullets li { padding: 4px 0; font-size: 12px; line-height: 1.5; }
.cf-bullet {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 4px;
  font-size: 11.5px;
}
.cf-green  { background: rgba(46,125,77,0.10);  color: #2c7d4d; }
.cf-yellow { background: rgba(201,138,26,0.12); color: #8a5d10; }
.cf-red    { background: rgba(184,56,41,0.12);  color: #b83829; font-weight: 500; }

.cf-detail {
  margin-top: 12px;
  padding-top: 10px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.08));
  font-size: 11px;
  color: var(--ink-2, #2a2520);
  line-height: 1.6;
}
.cf-detail > div { padding: 2px 0; }
.cf-hash {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  background: rgba(0,0,0,0.04);
  padding: 1px 6px;
  border-radius: 3px;
  color: var(--ink-fade, #6a655e);
}

/* Distinguish the new full-export and import buttons from the
   review-only export so the teacher can tell them apart. */
.provenance-review-export-full-btn {
  background: var(--ink-2, #2a2520);
  border-color: var(--ink-2, #2a2520);
}
.provenance-review-import-btn {
  background: var(--paper, #FAF8F2);
  color: var(--ink-2, #2a2520);
  border: 1px dashed var(--ink-2, #2a2520);
}
.provenance-review-import-btn:hover {
  background: rgba(0,0,0,0.04);
  color: var(--ink, #1a1714);
}

/* ── Provenance import round-trip modal ── */
.prov-import-overlay {
  position: fixed;
  inset: 0;
  background: rgba(20, 18, 16, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 300;
  padding: 24px;
}
.prov-import-modal {
  width: min(640px, 100%);
  max-height: 86vh;
  background: var(--paper, #FAF8F2);
  border-radius: 12px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.32);
  font-family: var(--sans);
  display: flex;
  flex-direction: column;
  overflow: hidden;
}
.prov-import-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 18px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.prov-import-title {
  font-weight: 600;
  font-size: 13px;
  color: var(--ink-2, #2a2520);
  letter-spacing: 0.02em;
}
.prov-import-close {
  appearance: none;
  border: 0;
  background: transparent;
  font-size: 20px;
  color: var(--ink-fade, #6a655e);
  cursor: pointer;
  padding: 2px 6px;
  line-height: 1;
}
.prov-import-meta {
  padding: 12px 18px;
  background: rgba(0,0,0,0.025);
  font-size: 11.5px;
  color: var(--ink-2, #2a2520);
  line-height: 1.6;
}
.prov-import-meta code {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
}
.prov-import-checks {
  list-style: none;
  margin: 0;
  padding: 14px 18px;
  overflow-y: auto;
}
.prov-import-check {
  display: flex;
  gap: 12px;
  padding: 12px;
  border-radius: 8px;
  margin-bottom: 8px;
}
.prov-import-check.ok    { background: rgba(46,125,77,0.08); }
.prov-import-check.fail  { background: rgba(184,56,41,0.10); }
.prov-import-badge {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-weight: 700;
  flex-shrink: 0;
}
.prov-import-check.ok   .prov-import-badge { background: #2c7d4d; color: #fff; }
.prov-import-check.fail .prov-import-badge { background: #b83829; color: #fff; }
.prov-import-label  {
  font-size: 13px;
  font-weight: 600;
  color: var(--ink, #1a1714);
  margin-bottom: 4px;
}
.prov-import-detail {
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  line-height: 1.5;
}
.prov-import-foot {
  padding: 14px 18px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.08));
  display: flex;
  justify-content: flex-end;
}
.prov-import-close-btn {
  appearance: none;
  border: 0;
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 500;
  padding: 8px 18px;
  border-radius: 999px;
  cursor: pointer;
}

/* ── Sort + filter controls ── */
.provenance-review-filters {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 10px;
  margin-top: 10px;
  padding-top: 10px;
  border-top: 1px dashed var(--rule, rgba(0,0,0,0.10));
}
.provenance-review-sort {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-2, #2a2520);
}
.provenance-review-sort-select {
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: var(--paper, #FAF8F2);
  color: var(--ink, #1a1714);
  font-family: inherit;
  font-size: 11px;
  padding: 3px 22px 3px 8px;
  border-radius: 4px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M0 0 L5 6 L10 0' fill='none' stroke='%236a655e' stroke-width='1.4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
}
.provenance-review-filter-chips {
  display: inline-flex;
  flex-wrap: wrap;
  gap: 4px;
}
.provenance-review-filter-chip {
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: var(--paper, #FAF8F2);
  color: var(--ink-2, #2a2520);
  font-family: var(--sans);
  font-size: 10.5px;
  padding: 3px 9px;
  border-radius: 999px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  transition: background 120ms ease;
}
.provenance-review-filter-chip:hover { background: rgba(0,0,0,0.04); }
.provenance-review-filter-chip[data-active="false"] {
  opacity: 0.4;
  text-decoration: line-through;
}
.provenance-review-filter-count {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 9.5px;
  background: rgba(0,0,0,0.05);
  padding: 0 5px;
  border-radius: 999px;
}
/* CSS-only hide of items the teacher has filtered out */
.provenance-review-flagged-item[data-filtered="true"] { display: none; }

/* ── Severity icon ── */
.provenance-review-flagged-sev {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 16px;
  height: 16px;
  margin-right: 6px;
  font-size: 11px;
  vertical-align: middle;
  cursor: help;
}
.provenance-review-flagged-sev[data-severity="high"]   { color: #b83829; }
.provenance-review-flagged-sev[data-severity="medium"] { color: #c98a1a; }
.provenance-review-flagged-sev[data-severity="low"]    { color: #6a655e; }

/* Make category chip a tooltip target */
.provenance-review-flagged-category[title] {
  cursor: help;
  text-decoration: underline dotted rgba(0,0,0,0.25);
  text-underline-offset: 2px;
}

/* ── Baseline match block ── */
.cf-baseline {
  margin: 14px 0 10px;
  padding: 12px 14px;
  border-radius: 8px;
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
  background: var(--paper, #FAF8F2);
}
.cf-baseline-thin {
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  font-style: italic;
}
.cf-baseline-ok   { border-left: 4px solid #2c7d4d; background: rgba(46,125,77,0.04); }
.cf-baseline-warn { border-left: 4px solid #c98a1a; background: rgba(201,138,26,0.05); }
.cf-baseline-fail { border-left: 4px solid #b83829; background: rgba(184,56,41,0.06); }

.cf-baseline-head {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin-bottom: 4px;
}
.cf-baseline-score {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-weight: 700;
  font-size: 18px;
}
.cf-baseline-ok   .cf-baseline-score { color: #2c7d4d; }
.cf-baseline-warn .cf-baseline-score { color: #8a5d10; }
.cf-baseline-fail .cf-baseline-score { color: #b83829; }
.cf-baseline-verdict {
  font-size: 12px;
  font-weight: 600;
  color: var(--ink-2, #2a2520);
}
.cf-baseline-meta {
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  margin-bottom: 10px;
}
.cf-baseline-metrics {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
}
.cf-baseline-metric {
  display: grid;
  grid-template-columns: 120px 1fr 70px;
  align-items: center;
  gap: 10px;
  font-size: 11px;
  color: var(--ink-2, #2a2520);
}
.cf-baseline-metric-label { font-family: var(--sans); }
.cf-baseline-metric-bar {
  height: 6px;
  background: rgba(0,0,0,0.06);
  border-radius: 3px;
  overflow: hidden;
}
.cf-baseline-metric-bar > span {
  display: block;
  height: 100%;
  border-radius: 3px;
}
.cf-baseline-metric-bar.ok   > span { background: #2c7d4d; }
.cf-baseline-metric-bar.warn > span { background: #c98a1a; }
.cf-baseline-metric-bar.fail > span { background: #b83829; }
.cf-baseline-metric-value {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10px;
  color: var(--ink-fade, #6a655e);
  text-align: right;
}

/* ── Notify-student CTA + status ── */
.provenance-review-notify-btn {
  appearance: none;
  border: 1px solid var(--ink, #1a1714);
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 500;
  padding: 6px 12px;
  border-radius: 999px;
  cursor: pointer;
  margin-left: 10px;
  transition: background 120ms ease;
}
.provenance-review-notify-btn:hover { background: var(--ink-2, #2a2520); }
.provenance-review-flagged-notification {
  margin-top: 10px;
  padding: 10px 12px;
  background: rgba(0,0,0,0.025);
  border-radius: 6px;
  font-size: 11.5px;
  color: var(--ink-2, #2a2520);
  width: 100%;
}
.provenance-review-notification-status {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
}
.provenance-review-notification-pending {
  font-style: italic;
  color: var(--ink-fade, #6a655e);
  font-size: 10.5px;
}
.provenance-review-notification-view-appeal {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--red, #b83829);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline;
}
.provenance-review-notification-appeal {
  margin: 8px 0 0;
  padding: 8px 12px;
  border-left: 3px solid #2c7d4d;
  background: rgba(46,125,77,0.05);
  border-radius: 0 6px 6px 0;
  font-style: normal;
}
.provenance-review-notification-appeal em {
  color: var(--ink-fade, #6a655e);
  font-size: 10.5px;
}
.provenance-review-notification-appeal p {
  margin: 4px 0 0;
  font-size: 12px;
  line-height: 1.5;
  color: var(--ink, #1a1714);
}

/* Notify modal — extends the import-modal styles for consistency */
.prov-notify-modal { max-width: 540px; }
.prov-notify-body  { padding: 14px 18px; overflow-y: auto; }
.prov-notify-meta  {
  padding: 8px 12px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  font-size: 11px;
  color: var(--ink-2, #2a2520);
  margin-bottom: 12px;
  line-height: 1.6;
}
.prov-notify-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--ink-2, #2a2520);
}
.prov-notify-textarea {
  width: 100%;
  padding: 10px 12px;
  font-family: var(--serif, Georgia, serif);
  font-size: 13px;
  line-height: 1.5;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  background: var(--paper, #FAF8F2);
  color: var(--ink, #1a1714);
  resize: vertical;
  box-sizing: border-box;
}
.prov-notify-hint {
  margin-top: 8px;
  font-size: 10.5px;
  font-style: italic;
  color: var(--ink-fade, #6a655e);
  line-height: 1.5;
}
.prov-notify-send {
  background: var(--red, #b83829) !important;
}

/* ── Student banner ── */
.student-provenance-banner {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 18px;
  margin: 16px 0;
  background: linear-gradient(135deg, rgba(184, 56, 41, 0.06), rgba(201, 138, 26, 0.06));
  border-left: 4px solid var(--red, #b83829);
  border-radius: 8px;
  font-family: var(--sans);
}
.spb-icon {
  font-size: 24px;
  flex-shrink: 0;
}
.spb-body { flex: 1; }
.spb-body strong {
  display: block;
  font-size: 13px;
  color: var(--ink, #1a1714);
  margin-bottom: 4px;
}
.spb-body p {
  margin: 0;
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  line-height: 1.5;
}
.spb-respond-btn {
  appearance: none;
  border: 0;
  background: var(--red, #b83829);
  color: var(--paper, #FAF8F2);
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
  white-space: nowrap;
  transition: background 120ms ease;
}
.spb-respond-btn:hover { background: #c64534; }

/* ── Student appeal modal ── */
.student-appeal-modal { max-width: 640px; }
.student-appeal-body {
  padding: 0 18px 14px;
  overflow-y: auto;
}
.student-appeal-intro {
  padding: 12px;
  margin: 12px 0;
  background: rgba(0,0,0,0.025);
  border-radius: 6px;
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  line-height: 1.55;
}
.student-appeal-item {
  margin: 14px 0;
  padding: 14px;
  border: 1px solid var(--rule, rgba(0,0,0,0.12));
  border-radius: 8px;
}
.student-appeal-flag {
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  margin-bottom: 10px;
}
.student-appeal-teacher-msg {
  padding: 10px 12px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  margin-bottom: 12px;
  font-size: 12px;
  line-height: 1.55;
}
.student-appeal-teacher-msg em {
  color: var(--ink-fade, #6a655e);
  font-size: 10.5px;
}
.student-appeal-teacher-msg p {
  margin: 6px 0 0;
  color: var(--ink, #1a1714);
}
.student-appeal-label {
  display: block;
  font-size: 11px;
  font-weight: 600;
  margin-bottom: 6px;
  color: var(--ink-2, #2a2520);
}
.student-appeal-input {
  width: 100%;
  padding: 10px 12px;
  font-family: var(--serif, Georgia, serif);
  font-size: 13px;
  line-height: 1.55;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  background: var(--paper, #FAF8F2);
  color: var(--ink, #1a1714);
  resize: vertical;
  box-sizing: border-box;
}
.student-appeal-submit {
  background: #2c7d4d !important;
}

/* ── Privacy info button + disclosure modal ── */
.provenance-info-btn {
  appearance: none;
  border: 1px solid currentColor;
  background: transparent;
  color: inherit;
  width: 16px;
  height: 16px;
  border-radius: 50%;
  font-size: 10px;
  font-weight: 700;
  line-height: 1;
  margin-left: 6px;
  cursor: pointer;
  padding: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  opacity: 0.7;
  transition: opacity 120ms ease;
}
.provenance-info-btn:hover { opacity: 1; }

.prov-privacy-modal { max-width: 580px; }
.prov-privacy-body {
  padding: 0 20px 16px;
  overflow-y: auto;
  font-family: var(--sans);
  font-size: 12px;
  line-height: 1.6;
  color: var(--ink, #1a1714);
}
.prov-privacy-intro {
  padding: 12px;
  margin: 12px 0 16px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  font-size: 12.5px;
  line-height: 1.6;
}
.prov-privacy-section {
  margin-bottom: 14px;
  padding: 10px 12px;
  border-radius: 6px;
  border-left: 3px solid transparent;
}
.prov-privacy-section ul {
  margin: 6px 0 0;
  padding-left: 18px;
}
.prov-privacy-section li { padding: 2px 0; }
.prov-privacy-section p { margin: 6px 0 0; }

.prov-privacy-label {
  font-weight: 600;
  font-size: 11px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: 4px;
}
.prov-privacy-yes     { border-left-color: #2c7d4d; background: rgba(46,125,77,0.05); }
.prov-privacy-yes     .prov-privacy-label, .prov-privacy-section.prov-privacy-yes > .prov-privacy-label { color: #2c7d4d; }
.prov-privacy-no      { border-left-color: #b83829; background: rgba(184,56,41,0.05); }
.prov-privacy-no      .prov-privacy-label, .prov-privacy-section.prov-privacy-no > .prov-privacy-label { color: #b83829; }
.prov-privacy-who     { border-left-color: #c98a1a; background: rgba(201,138,26,0.05); }
.prov-privacy-who     .prov-privacy-label, .prov-privacy-section.prov-privacy-who > .prov-privacy-label { color: #8a5d10; }
.prov-privacy-purpose { border-left-color: #6b46c1; background: rgba(107,70,193,0.05); }
.prov-privacy-purpose .prov-privacy-label, .prov-privacy-section.prov-privacy-purpose > .prov-privacy-label { color: #6b46c1; }
.prov-privacy-close   { background: #2c7d4d !important; }

/* Replace the previous compound selector — color the label inside
   each section explicitly. */
.prov-privacy-section.prov-privacy-yes     > .prov-privacy-label { color: #2c7d4d; }
.prov-privacy-section.prov-privacy-no      > .prov-privacy-label { color: #b83829; }
.prov-privacy-section.prov-privacy-who     > .prov-privacy-label { color: #8a5d10; }
.prov-privacy-section.prov-privacy-purpose > .prov-privacy-label { color: #6b46c1; }

/* ── Cross-doc comparison modal ── */
.cross-doc-modal { max-width: 720px; }
.cross-doc-body { padding: 16px 18px; overflow-y: auto; }
.cross-doc-empty {
  padding: 24px;
  text-align: center;
  color: var(--ink-fade, #6a655e);
  font-style: italic;
}
.cross-doc-intro {
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  line-height: 1.55;
  margin-bottom: 14px;
}
.cross-doc-label {
  display: block;
  font-size: 12px;
  font-weight: 600;
  margin-bottom: 16px;
}
.cross-doc-select {
  margin-left: 8px;
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: var(--paper, #FAF8F2);
  padding: 5px 24px 5px 10px;
  font-family: inherit;
  font-size: 12px;
  border-radius: 4px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6' viewBox='0 0 10 6'><path d='M0 0 L5 6 L10 0' fill='none' stroke='%236a655e' stroke-width='1.4'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
}
.cross-doc-verdict {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 10px 14px;
  border-radius: 8px;
  margin-bottom: 16px;
  border-left: 4px solid;
}
.cross-doc-verdict-good { background: rgba(46,125,77,0.06);  border-left-color: #2c7d4d; }
.cross-doc-verdict-warn { background: rgba(201,138,26,0.07); border-left-color: #c98a1a; }
.cross-doc-verdict-bad  { background: rgba(184,56,41,0.07);  border-left-color: #b83829; }
.cross-doc-score {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 22px;
  font-weight: 700;
}
.cross-doc-verdict-good .cross-doc-score { color: #2c7d4d; }
.cross-doc-verdict-warn .cross-doc-score { color: #8a5d10; }
.cross-doc-verdict-bad  .cross-doc-score { color: #b83829; }
.cross-doc-verdict-text { font-size: 12px; color: var(--ink-2, #2a2520); }
.cross-doc-spark-block {
  padding: 12px 14px;
  background: var(--paper, #FAF8F2);
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
  border-radius: 8px;
  margin-bottom: 14px;
}
.cross-doc-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2, #2a2520);
  margin-bottom: 8px;
}
.cross-doc-hist { width: 100%; max-width: 480px; height: auto; }
.cross-doc-table {
  width: 100%;
  margin-top: 4px;
  border-collapse: collapse;
  font-size: 12px;
}
.cross-doc-table th, .cross-doc-table td {
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.cross-doc-table th {
  font-weight: 600;
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-fade, #6a655e);
}
.cross-doc-drift[data-pct] { font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 11px; }

/* Cross-doc launcher button in the fingerprint panel */
.cf-cross-doc-row { margin-top: 12px; text-align: right; }
.cf-cross-doc-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--red, #b83829);
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
  text-decoration: underline dotted;
  text-underline-offset: 3px;
}
.cf-cross-doc-btn:hover { color: #c64534; }

/* ── Settings modal ── */
.review-settings-modal { max-width: 540px; }
.review-settings-body { padding: 16px 18px; overflow-y: auto; }
.review-settings-intro {
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  margin: 0 0 16px;
  line-height: 1.5;
}
.review-settings-section {
  border: 1px solid var(--rule, rgba(0,0,0,0.10));
  border-radius: 8px;
  padding: 12px 14px;
  margin-bottom: 12px;
}
.review-settings-section legend {
  font-size: 12px;
  font-weight: 600;
  padding: 0 6px;
  color: var(--ink, #1a1714);
}
.review-settings-hint {
  margin: 0 0 8px;
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  font-style: italic;
}
.review-settings-radio, .review-settings-check {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 0;
  font-size: 12px;
  color: var(--ink-2, #2a2520);
  cursor: pointer;
}
.review-settings-radio input, .review-settings-check input { margin: 0; }
.review-settings-radio-label { font-size: 12px; }

.provenance-review-settings-btn {
  padding: 4px 8px !important;
  font-size: 14px !important;
  line-height: 1;
}

/* ── Peer-review provenance hint ──
   When a student is reviewing another student's work, surface the
   ORIGINAL author's composition fingerprint as authenticity
   context. Quick, opt-in chip — clicking expands. */
.peer-review-author-chip {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 4px 10px;
  background: rgba(46,125,77,0.08);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: 11px;
  color: var(--ink-2, #2a2520);
  cursor: pointer;
  border: 1px solid rgba(46,125,77,0.20);
  margin-left: 8px;
}
.peer-review-author-chip:hover { background: rgba(46,125,77,0.14); }
.peer-review-author-chip .peer-icon { font-size: 13px; }

/* ── Group collaboration chips ── */
.group-submit-chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin-left: 12px;
  padding: 5px 12px;
  border: 0;
  background: rgba(107, 70, 193, 0.10);
  border-radius: 999px;
  font-family: var(--sans);
  font-size: 11.5px;
  color: #4c2da3;
  cursor: pointer;
  transition: background 120ms ease;
}
.group-submit-chip:hover { background: rgba(107, 70, 193, 0.18); }
.group-submit-chip strong { font-weight: 600; }

/* Per-block authorship chips in the group doc */
.block.has-group-attribution {
  position: relative;
  padding-right: 36px;
}
.group-block-author-chip {
  position: absolute;
  right: 4px;
  top: 4px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  border: 0;
  background: rgba(107, 70, 193, 0.16);
  color: #4c2da3;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 700;
  cursor: help;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  letter-spacing: 0.04em;
}
.group-block-author-chip:hover {
  background: #4c2da3;
  color: white;
}

/* ── Teacher's group-manager modal ── */
.ag-create-row {
  display: flex;
  gap: 8px;
  margin-bottom: 14px;
}
.ag-new-name {
  flex: 1;
  padding: 7px 12px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 13px;
}
.ag-row {
  padding: 12px 14px;
  border: 1px solid var(--rule, rgba(0,0,0,0.10));
  border-radius: 8px;
  margin-bottom: 8px;
}
.ag-row-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 8px;
}
.ag-row-head strong { font-size: 13px; }
.ag-row-meta { font-size: 11px; color: var(--ink-fade, #6a655e); }
.ag-members {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin-bottom: 10px;
  min-height: 24px;
}
.ag-member-chip {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 4px 3px 10px;
  background: rgba(107, 70, 193, 0.10);
  color: #4c2da3;
  border-radius: 999px;
  font-size: 11px;
}
.ag-member-chip em {
  color: var(--ink-fade, #6a655e);
  font-size: 10px;
  margin-left: 4px;
}
.ag-member-remove {
  appearance: none;
  border: 0;
  background: transparent;
  color: inherit;
  cursor: pointer;
  font-size: 14px;
  line-height: 1;
  padding: 0 4px;
  opacity: 0.6;
}
.ag-member-remove:hover { opacity: 1; }
.ag-add-row {
  display: flex;
  gap: 6px;
  align-items: center;
}
.ag-add-email {
  flex: 1;
  padding: 5px 10px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 4px;
  font-size: 11.5px;
  font-family: var(--sans);
}
.ag-add-role {
  padding: 5px 8px;
  font-size: 11.5px;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 4px;
  background: white;
}
.ag-add-btn {
  appearance: none;
  border: 0;
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
  font-size: 11px;
  padding: 5px 12px;
  border-radius: 999px;
  cursor: pointer;
}

/* ── Group lead controls bar ── */
.group-lead-controls {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  margin: 12px 0;
  background: rgba(107, 70, 193, 0.05);
  border: 1px solid rgba(107, 70, 193, 0.18);
  border-radius: 8px;
  font-family: var(--sans);
  font-size: 12px;
}
.group-status {
  font-weight: 600;
  color: #4c2da3;
}
.group-lead-btn {
  appearance: none;
  border: 1px solid rgba(107, 70, 193, 0.25);
  background: white;
  color: #4c2da3;
  font-family: inherit;
  font-size: 11.5px;
  padding: 5px 12px;
  border-radius: 999px;
  cursor: pointer;
  transition: background 120ms ease;
}
.group-lead-btn:hover { background: rgba(107, 70, 193, 0.10); }
.group-lead-submit {
  background: #4c2da3 !important;
  color: white !important;
  border-color: #4c2da3 !important;
  margin-left: auto;
}
.group-lead-submit:hover { background: #5b3bb5 !important; }

/* Lock state on the prose */
.group-doc-locked {
  background-image: repeating-linear-gradient(
    45deg,
    rgba(107, 70, 193, 0.025),
    rgba(107, 70, 193, 0.025) 10px,
    rgba(107, 70, 193, 0.045) 10px,
    rgba(107, 70, 193, 0.045) 20px
  );
  cursor: not-allowed;
}
.group-doc-locked::before {
  content: '🔒 Locked for finalization — no further edits';
  display: block;
  padding: 8px 12px;
  margin-bottom: 12px;
  background: rgba(107, 70, 193, 0.10);
  color: #4c2da3;
  border-radius: 6px;
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 600;
}

/* ── Group authorship breakdown (teacher review) ── */
.group-authorship-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 16px;
  margin-top: 12px;
}
.group-authorship-label {
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2, #2a2520);
  margin-bottom: 6px;
}
.group-authorship-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 11.5px;
}
.group-authorship-table th, .group-authorship-table td {
  padding: 5px 8px;
  text-align: left;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.group-authorship-table th {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-fade, #6a655e);
  font-weight: 600;
}
.group-authorship-trail-label {
  margin-top: 14px;
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--ink-2, #2a2520);
}
.group-authorship-trail-list {
  list-style: none;
  padding: 0;
  margin: 8px 0 0;
  max-height: 240px;
  overflow-y: auto;
}
.group-authorship-trail-item {
  padding: 8px 10px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
  font-size: 11px;
  color: var(--ink-2, #2a2520);
}
.group-authorship-trail-block { font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 10px; color: var(--ink-fade, #6a655e); margin-bottom: 3px; }
.group-authorship-trail-edit  { color: var(--ink-fade, #6a655e); }
@media (max-width: 720px) {
  .group-authorship-grid { grid-template-columns: 1fr; }
}

/* ───────────────────────────────────────────────────────────────────
   Writing Profile — refined editorial aesthetic
   Cream paper · ink · red pencil accents
   Hand-drawn-feeling charts, subtle paper texture, warm shadows
   ─────────────────────────────────────────────────────────────────── */

.mwp-modal-v2 {
  --mwp-paper:    #fcf9f1;
  --mwp-paper-2:  #f6f0e3;
  --mwp-ink:      #2a2622;
  --mwp-ink-2:    #6a635a;
  --mwp-ink-3:    #9a9088;
  --mwp-red:      #b83829;
  --mwp-red-soft: rgba(184, 56, 41, 0.12);
  --mwp-rule:     rgba(42, 38, 34, 0.10);
  --mwp-rule-strong: rgba(42, 38, 34, 0.22);

  max-width: 940px !important;
  width: 96vw;
  max-height: 92vh;
  background: var(--mwp-paper);
  background-image:
    radial-gradient(at 18% 12%, rgba(120, 95, 60, 0.04), transparent 50%),
    radial-gradient(at 78% 88%, rgba(180, 120, 80, 0.05), transparent 55%),
    repeating-linear-gradient(0deg, transparent 0, transparent 27px, rgba(120, 80, 50, 0.012) 28px, transparent 29px);
  color: var(--mwp-ink);
  border-radius: 6px;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, 0.5) inset,
    0 12px 40px rgba(60, 40, 20, 0.18),
    0 2px 6px rgba(60, 40, 20, 0.08);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  font-family: 'Charter', 'Iowan Old Style', 'Palatino', 'Georgia', serif;
}

.mwp-modal-head {
  padding: 20px 32px 12px;
  border-bottom: 1px solid var(--mwp-rule);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
}
.mwp-modal-headline {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.mwp-modal-title {
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--mwp-ink);
  font-family: inherit;
}
.mwp-modal-sub {
  font-size: 12px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-modal-close {
  width: 32px;
  height: 32px;
  background: none;
  border: none;
  font-size: 22px;
  color: var(--mwp-ink-2);
  cursor: pointer;
  border-radius: 50%;
  transition: background 120ms ease;
}
.mwp-modal-close:hover { background: rgba(0,0,0,0.06); }

.mwp-tabs {
  display: flex;
  gap: 0;
  padding: 0 32px;
  border-bottom: 1px solid var(--mwp-rule);
  background: var(--mwp-paper-2);
}
.mwp-tab {
  background: none;
  border: none;
  padding: 11px 18px;
  font-size: 13px;
  font-family: inherit;
  letter-spacing: 0.02em;
  cursor: pointer;
  color: var(--mwp-ink-2);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color 120ms ease, border-color 120ms ease;
}
.mwp-tab:hover { color: var(--mwp-ink); }
.mwp-tab.is-active {
  color: var(--mwp-ink);
  border-bottom-color: var(--mwp-red);
}

.mwp-body {
  overflow-y: auto;
  padding: 24px 32px 32px;
  flex: 1;
  background-image:
    radial-gradient(at 50% 0%, rgba(180, 120, 60, 0.025), transparent 60%);
}

/* ── Timeline tab ─────────────────────────────────────────────── */

.mwp-timeline-summary {
  display: flex;
  gap: 28px;
  margin-bottom: 22px;
  padding-bottom: 18px;
  border-bottom: 1px dashed var(--mwp-rule-strong);
}
.mwp-timeline-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.mwp-stat-num {
  font-size: 26px;
  font-weight: 600;
  font-family: inherit;
  letter-spacing: -0.01em;
  color: var(--mwp-ink);
}
.mwp-stat-label {
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-filter-chips {
  display: flex;
  gap: 6px;
  margin-bottom: 22px;
}
.mwp-filter-chip {
  background: transparent;
  border: 1px solid var(--mwp-rule-strong);
  border-radius: 999px;
  padding: 5px 13px;
  font-size: 12px;
  font-family: inherit;
  color: var(--mwp-ink-2);
  cursor: pointer;
  transition: all 120ms ease;
}
.mwp-filter-chip:hover { background: rgba(0,0,0,0.025); }
.mwp-filter-chip.is-active {
  background: var(--mwp-ink);
  color: var(--mwp-paper);
  border-color: var(--mwp-ink);
}
.mwp-feed {
  display: flex;
  flex-direction: column;
  gap: 22px;
}
.mwp-feed-group { display: flex; flex-direction: column; gap: 10px; }
.mwp-feed-label {
  margin: 0 0 4px;
  font-size: 13px;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-card {
  display: grid;
  grid-template-columns: 4px 1fr;
  background: rgba(243, 237, 224, 0.45);
  border: 1px solid var(--mwp-rule);
  border-radius: 4px;
  overflow: hidden;
  transition: background 120ms ease, box-shadow 120ms ease;
}
.mwp-card:hover {
  background: rgba(243, 237, 224, 0.75);
  box-shadow: 0 2px 8px rgba(60, 40, 20, 0.08);
}
.mwp-card-strip {
  background: var(--mwp-red);
  opacity: 0.85;
}
.mwp-card-body {
  padding: 12px 16px;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.mwp-card-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 12px;
  flex-wrap: wrap;
}
.mwp-card-title {
  margin: 0;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.mwp-card-when {
  font-size: 11px;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
  letter-spacing: 0.04em;
}
.mwp-card-stats {
  display: flex;
  gap: 14px;
  font-size: 12.5px;
  color: var(--mwp-ink-2);
}
.mwp-card-stats strong { color: var(--mwp-ink); font-weight: 600; }
.mwp-card-chain { color: rgba(50, 110, 70, 0.85); font-size: 11.5px; }
.mwp-card-voice {
  display: flex;
  gap: 6px;
  margin-top: 4px;
}
.mwp-micro {
  width: 50px;
  height: 5px;
  background: rgba(42, 38, 34, 0.08);
  border-radius: 999px;
  overflow: hidden;
  display: inline-block;
}
.mwp-micro-fill {
  display: block;
  height: 100%;
  background: var(--mwp-ink);
  opacity: 0.55;
}

/* ── Voice tab ────────────────────────────────────────────────── */

.mwp-archetype {
  display: grid;
  grid-template-columns: 80px 1fr;
  gap: 24px;
  padding: 28px 30px;
  background: linear-gradient(135deg, rgba(184, 56, 41, 0.05), rgba(120, 80, 50, 0.04));
  border: 1px solid var(--mwp-rule-strong);
  border-left: 3px solid var(--mwp-red);
  border-radius: 4px;
  margin-bottom: 26px;
  position: relative;
}
.mwp-archetype::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image: repeating-linear-gradient(0deg, transparent 0, transparent 26px, rgba(120, 80, 50, 0.025) 27px, transparent 28px);
  border-radius: inherit;
}
.mwp-archetype-glyph {
  font-size: 60px;
  line-height: 1;
  color: var(--mwp-red);
  font-family: 'Iowan Old Style', 'Georgia', serif;
  align-self: center;
  text-align: center;
}
.mwp-archetype-body { position: relative; z-index: 1; }
.mwp-archetype-name {
  font-size: 28px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin-bottom: 4px;
}
.mwp-archetype-vibe {
  font-size: 14px;
  color: var(--mwp-ink-2);
  font-style: italic;
  margin-bottom: 14px;
}
.mwp-archetype-desc {
  margin: 0 0 14px;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--mwp-ink);
}
.mwp-archetype-neighbors {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}
.mwp-archetype-neighbors-label {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-archetype-neighbor {
  font-size: 12px;
  font-style: italic;
  color: var(--mwp-ink-2);
  padding: 2px 10px;
  border: 1px solid var(--mwp-rule-strong);
  border-radius: 999px;
}

.mwp-panels {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 14px;
  margin-bottom: 24px;
}
.mwp-panel {
  background: rgba(243, 237, 224, 0.45);
  border: 1px solid var(--mwp-rule);
  border-radius: 4px;
  padding: 16px 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.mwp-panel-wide { grid-column: 1 / -1; }
.mwp-panel-label {
  font-size: 10.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-panel-body {
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.mwp-panel-figure {
  flex: 1;
  justify-content: center;
  min-height: 90px;
}
.mwp-panel-caption {
  font-size: 12.5px;
  line-height: 1.5;
  color: var(--mwp-ink-2);
  margin: 0;
}
.mwp-panel-caption strong { color: var(--mwp-ink); font-weight: 600; }
.mwp-big-stat {
  font-size: 42px;
  font-weight: 600;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--mwp-ink);
}
.mwp-big-stat-unit {
  font-size: 18px;
  font-weight: 400;
  color: var(--mwp-ink-3);
  margin-left: 4px;
}
.mwp-trait-name {
  font-size: 22px;
  font-weight: 600;
  font-style: italic;
  color: var(--mwp-ink);
}
.mwp-fingerprint-svg,
.mwp-overtime-svg {
  width: 100%;
  height: auto;
  display: block;
}
.mwp-overtime-svg { max-height: 110px; }
.mwp-legend {
  display: flex;
  gap: 16px;
  font-size: 11.5px;
  color: var(--mwp-ink-2);
  margin-top: 4px;
}
.mwp-legend span { display: inline-flex; align-items: center; gap: 6px; }
.mwp-legend-swatch {
  display: inline-block;
  width: 12px;
  height: 2px;
  border-radius: 999px;
}

/* Heatmap */
.mwp-heatmap { display: flex; flex-direction: column; gap: 8px; }
.mwp-heatmap-grid {
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.mwp-heatmap-row {
  display: grid;
  grid-template-columns: 18px repeat(24, 1fr);
  gap: 3px;
  align-items: center;
}
.mwp-heatmap-day {
  font-size: 10px;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-heatmap-cell {
  height: 14px;
  background: var(--mwp-ink);
  border-radius: 2px;
}
.mwp-heatmap-axis {
  display: flex;
  justify-content: space-between;
  padding-left: 21px;
  font-size: 10px;
  color: var(--mwp-ink-3);
  font-family: 'SF Mono', 'Menlo', monospace;
}

/* Numbers table */
.mwp-numbers {
  width: 100%;
  border-collapse: collapse;
  font-size: 13px;
}
.mwp-numbers td {
  padding: 5px 0;
  border-bottom: 1px dashed var(--mwp-rule);
}
.mwp-numbers td:first-child {
  color: var(--mwp-ink-2);
}
.mwp-numbers td:last-child {
  text-align: right;
  font-family: 'SF Mono', 'Menlo', monospace;
}

/* Signature phrases + openers */
.mwp-section {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px dashed var(--mwp-rule-strong);
}
.mwp-section-h {
  margin: 0 0 4px;
  font-size: 16px;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.mwp-section-intro {
  margin: 0 0 14px;
  font-size: 13px;
  color: var(--mwp-ink-2);
  line-height: 1.55;
}
.mwp-phrases {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.mwp-phrase {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 12px 5px 14px;
  background: var(--mwp-paper-2);
  border: 1px solid var(--mwp-rule);
  border-radius: 999px;
  font-size: 13px;
  font-style: italic;
  color: var(--mwp-ink);
}
.mwp-phrase-count {
  font-style: normal;
  font-family: 'SF Mono', 'Menlo', monospace;
  font-size: 11px;
  color: var(--mwp-ink-3);
}
.mwp-openers {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(140px, 1fr));
  gap: 6px;
}
.mwp-opener {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  padding: 6px 12px;
  border-bottom: 1px dashed var(--mwp-rule);
  font-size: 13px;
}
.mwp-opener-word {
  font-style: italic;
  text-transform: capitalize;
}
.mwp-opener-count {
  font-family: 'SF Mono', 'Menlo', monospace;
  font-size: 11px;
  color: var(--mwp-ink-3);
}

/* ── Archive tab ──────────────────────────────────────────────── */

.mwp-archive-section { display: flex; flex-direction: column; gap: 20px; }
.mwp-archive-intro h3 {
  margin: 0 0 8px;
  font-size: 22px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.mwp-archive-intro p {
  margin: 0;
  font-size: 14px;
  line-height: 1.6;
  color: var(--mwp-ink-2);
}
.mwp-archive-intro code {
  font-family: 'SF Mono', 'Menlo', monospace;
  font-size: 12.5px;
  background: var(--mwp-paper-2);
  padding: 1px 6px;
  border-radius: 3px;
}
.mwp-verifier-link {
  color: var(--mwp-red);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}
.mwp-archive-actions { display: flex; gap: 8px; }
.mwp-archive-btn {
  background: var(--mwp-ink);
  color: var(--mwp-paper);
  border: none;
  padding: 9px 18px;
  border-radius: 3px;
  font-size: 13px;
  font-family: inherit;
  cursor: pointer;
  letter-spacing: 0.02em;
  transition: background 120ms ease;
}
.mwp-archive-btn:hover { background: var(--mwp-red); }
.mwp-archive-list {
  list-style: none;
  padding: 0;
  margin: 0;
  border-top: 1px solid var(--mwp-rule);
}
.mwp-archive-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 14px;
  padding: 12px 0;
  border-bottom: 1px solid var(--mwp-rule);
}
.mwp-archive-row-main { flex: 1; }
.mwp-archive-row-title { font-size: 15px; font-weight: 600; }
.mwp-archive-row-meta {
  font-size: 11.5px;
  color: var(--mwp-ink-3);
  margin-top: 2px;
  font-family: 'SF Mono', 'Menlo', monospace;
}
.mwp-archive-row-btn {
  background: transparent;
  border: 1px solid var(--mwp-rule-strong);
  padding: 5px 12px;
  border-radius: 3px;
  font-size: 12px;
  font-family: inherit;
  cursor: pointer;
  color: var(--mwp-ink);
  transition: all 120ms ease;
}
.mwp-archive-row-btn:hover {
  background: var(--mwp-ink);
  color: var(--mwp-paper);
}
.mwp-archive-trust {
  margin-top: 20px;
  padding: 18px 20px;
  background: var(--mwp-paper-2);
  border-left: 3px solid var(--mwp-red);
  border-radius: 0 3px 3px 0;
}
.mwp-archive-trust h4 {
  margin: 0 0 6px;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.01em;
}
.mwp-archive-trust p {
  margin: 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--mwp-ink-2);
}

/* ── Empty / alumni preview ───────────────────────────────────── */

.mwp-preview-wrap { display: flex; flex-direction: column; gap: 18px; }
.mwp-preview-banner {
  padding: 18px 22px;
  background: var(--mwp-paper-2);
  border-left: 3px solid var(--mwp-red);
  border-radius: 0 3px 3px 0;
}
.mwp-preview-banner-eyebrow {
  font-size: 10.5px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--mwp-red);
  font-family: 'SF Mono', 'Menlo', monospace;
  margin-bottom: 6px;
}
.mwp-preview-banner h3 {
  margin: 0 0 6px;
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.01em;
}
.mwp-preview-banner p {
  margin: 0;
  font-size: 13px;
  color: var(--mwp-ink-2);
  line-height: 1.55;
}
.mwp-preview-card {
  border: 1px dashed var(--mwp-rule-strong);
  border-radius: 4px;
  padding: 20px;
  opacity: 0.92;
}
.mwp-preview-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-top: 18px;
  padding-top: 14px;
  border-top: 1px dashed var(--mwp-rule);
}
.mwp-preview-stat {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.mwp-preview-cta {
  text-align: center;
  font-size: 13px;
  color: var(--mwp-ink-2);
  font-style: italic;
  margin: 0;
}

/* ── Responsive ───────────────────────────────────────────────── */

@media (max-width: 740px) {
  .mwp-panels { grid-template-columns: 1fr; }
  .mwp-archetype { grid-template-columns: 1fr; }
  .mwp-archetype-glyph { font-size: 48px; }
  .mwp-modal-head { padding: 16px 20px 10px; }
  .mwp-tabs { padding: 0 20px; }
  .mwp-body { padding: 18px 20px 24px; }
}

/* ── My Writing Profile (student self-view) ── */
.my-writing-profile-modal { max-width: 720px; }
.my-writing-profile-body {
  padding: 0 24px 20px;
  overflow-y: auto;
}
.mwp-hero {
  padding: 20px 0;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.10));
  margin-bottom: 20px;
}
.mwp-hero-name { font-size: 12px; color: var(--ink-fade, #6a655e); letter-spacing: 0.04em; }
.mwp-hero-title {
  font-family: var(--serif, Georgia, serif);
  font-size: 26px;
  font-weight: 500;
  margin: 6px 0 8px;
  color: var(--ink, #1a1714);
}
.mwp-hero-sub {
  margin: 0;
  font-size: 13px;
  color: var(--ink-2, #2a2520);
  line-height: 1.55;
}
.mwp-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
  margin-bottom: 24px;
}
.mwp-stat {
  padding: 12px;
  background: rgba(0,0,0,0.03);
  border-radius: 8px;
  text-align: center;
}
.mwp-stat-value {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 22px;
  font-weight: 700;
  color: var(--ink, #1a1714);
}
.mwp-stat-label {
  font-size: 10.5px;
  color: var(--ink-fade, #6a655e);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  margin-top: 2px;
}
.mwp-section { margin: 24px 0; }
.mwp-section h3 {
  margin: 0 0 6px;
  font-family: var(--serif, Georgia, serif);
  font-size: 17px;
  font-weight: 500;
  color: var(--ink, #1a1714);
}
.mwp-section-intro {
  font-size: 12.5px;
  color: var(--ink-2, #2a2520);
  margin: 0 0 12px;
  line-height: 1.55;
}
.mwp-sparkline { width: 100%; max-width: 480px; height: auto; display: block; margin: 8px 0; }
.mwp-rhythm-callout {
  padding: 12px 14px;
  background: rgba(107, 70, 193, 0.04);
  border-left: 3px solid #6b46c1;
  border-radius: 0 8px 8px 0;
  font-size: 12.5px;
  line-height: 1.55;
  color: var(--ink-2, #2a2520);
}
.mwp-personality {
  display: grid;
  grid-template-columns: 1fr;
  gap: 12px;
}
.mwp-trait {
  display: flex;
  gap: 14px;
  padding: 12px 14px;
  background: var(--paper, #FAF8F2);
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
  border-radius: 8px;
}
.mwp-trait-icon {
  width: 36px;
  height: 36px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: rgba(0,0,0,0.04);
  font-size: 18px;
  flex-shrink: 0;
}
.mwp-trait-body strong { display: block; font-size: 12px; color: var(--ink, #1a1714); }
.mwp-trait-body span {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  margin-left: 6px;
}
.mwp-trait-body p { margin: 4px 0 0; font-size: 12px; line-height: 1.55; color: var(--ink-2, #2a2520); }
.mwp-section-trust {
  padding: 16px 18px;
  background: rgba(46,125,77,0.05);
  border-radius: 8px;
}
.mwp-section-trust h3 { color: #2c7d4d; }
.mwp-section-trust ul { padding-left: 18px; margin: 8px 0 0; }
.mwp-section-trust li { padding: 4px 0; font-size: 12.5px; line-height: 1.55; }
.mwp-empty { padding: 32px; text-align: center; }
.mwp-empty-icon { font-size: 48px; margin-bottom: 12px; }
.mwp-empty h3 {
  margin: 0 0 8px;
  font-family: var(--serif, Georgia, serif);
  font-size: 19px;
}
.mwp-empty p { font-size: 13px; color: var(--ink-2, #2a2520); max-width: 380px; margin: 8px auto; }
.mwp-empty-sub { color: var(--ink-fade, #6a655e); font-style: italic; font-size: 11.5px; }
.mwp-secondary-btn {
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: white;
  font-family: var(--sans);
  font-size: 12px;
  padding: 8px 14px;
  border-radius: 999px;
  cursor: pointer;
}
.mwp-doc-list { list-style: none; padding: 0; margin: 12px 0; }
.mwp-doc-item {
  display: flex;
  justify-content: space-between;
  padding: 8px 12px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
  font-size: 12.5px;
}
.mwp-doc-slug { font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace); font-size: 10.5px; color: var(--ink-fade, #6a655e); }
.mwp-back-btn {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--red, #b83829);
  cursor: pointer;
  font-size: 12px;
  margin-bottom: 12px;
  padding: 0;
}
@media (max-width: 600px) {
  .mwp-grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── Bulk review overlay ── */
.bulk-review-overlay {
  position: fixed;
  bottom: 16px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
  padding: 12px 20px;
  border-radius: 12px;
  box-shadow: 0 12px 32px rgba(0,0,0,0.32);
  font-family: var(--sans);
  font-size: 12px;
  z-index: 280;
  display: flex;
  flex-direction: column;
  gap: 6px;
  max-width: 720px;
}
.bulk-review-progress { display: flex; gap: 14px; align-items: center; }
.bulk-review-count {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 12px;
  background: rgba(255,255,255,0.10);
  padding: 3px 10px;
  border-radius: 999px;
}
.bulk-review-student { font-weight: 600; }
.bulk-review-status[data-status="graded"]    { color: #5bd388; }
.bulk-review-status[data-status="submitted"] { color: #ffd166; }
.bulk-review-keys { font-size: 10.5px; color: rgba(255,255,255,0.6); }
.bulk-review-keys kbd {
  display: inline-block;
  padding: 1px 5px;
  margin: 0 1px;
  border: 1px solid rgba(255,255,255,0.20);
  border-radius: 3px;
  background: rgba(255,255,255,0.08);
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 9.5px;
  font-weight: 600;
  color: rgba(255,255,255,0.85);
}

/* ── Classroom analytics ── */
.classroom-analytics-modal { max-width: 800px; }
.classroom-analytics-body { padding: 0 18px 18px; overflow-y: auto; }
.ca-intro {
  padding: 12px;
  background: rgba(0,0,0,0.03);
  border-radius: 6px;
  font-size: 12px;
  margin: 12px 0;
}
.ca-empty { padding: 24px; text-align: center; color: var(--ink-fade, #6a655e); }
.ca-table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
  margin: 12px 0;
}
.ca-table th, .ca-table td {
  padding: 6px 8px;
  text-align: left;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.ca-table th {
  font-size: 10px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--ink-fade, #6a655e);
}
.ca-row-empty td { color: var(--ink-fade, #6a655e); font-style: italic; font-size: 11.5px; }
.ca-pill {
  display: inline-block;
  padding: 2px 8px;
  border-radius: 999px;
  font-size: 10.5px;
  font-weight: 600;
}
.ca-pill-ok   { background: rgba(46,125,77,0.10);  color: #2c7d4d; }
.ca-pill-warn { background: rgba(201,138,26,0.12); color: #8a5d10; }
.ca-foot {
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  margin-top: 12px;
  line-height: 1.55;
  font-style: italic;
}

/* Classroom-view analytics CTA */
.teacher-classroom-actions {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.08));
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
}
.teacher-classroom-analytics-btn {
  font-size: 12px;
  padding: 6px 14px;
  border-radius: 999px;
  background: rgba(0,0,0,0.04);
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  cursor: pointer;
  font-family: var(--sans);
}
.teacher-classroom-analytics-btn:hover { background: rgba(0,0,0,0.08); }

/* Assignment-row action buttons (Bulk review / Manage groups) */
.teacher-assignment-bulk-review,
.teacher-assignment-manage-groups {
  font-size: 11.5px;
}

/* ── Mobile / tablet responsive ── */
@media (max-width: 900px) {
  .prov-pip-replay {
    width: calc(100vw - 16px);
    right: 8px;
    bottom: 8px;
    max-width: none;
  }
  .prov-pip-replay-stage { min-height: 180px; max-height: 240px; }
  .provenance-review-progress-summary {
    flex-direction: column;
    align-items: flex-start;
    gap: 6px;
  }
  .provenance-review-progress-actions {
    width: 100%;
    flex-wrap: wrap;
    margin-left: 0;
  }
  .provenance-review-filters {
    flex-direction: column;
    align-items: flex-start;
    gap: 8px;
  }
  .provenance-review-filter-chips { width: 100%; }
  .prov-import-modal { max-width: 100%; }
  .cross-doc-hist { max-width: 100%; }
  .cf-baseline-metric {
    grid-template-columns: 100px 1fr 60px;
    font-size: 10.5px;
  }
  .cf-sparkline { font-size: 9px; }
}
@media (max-width: 600px) {
  .prov-import-overlay { padding: 8px; }
  .prov-import-head { padding: 10px 12px; }
  .prov-import-title { font-size: 12px; }
  .review-settings-intro, .student-appeal-intro, .prov-privacy-intro {
    font-size: 11.5px;
  }
  .provenance-review-summary-meta { font-size: 11px; }
}

/* ── Typing-rhythm sparkline ── */
.cf-spark-block {
  margin-top: 14px;
  padding: 10px 12px;
  background: var(--paper, #FAF8F2);
  border-radius: 8px;
  border: 1px solid var(--rule, rgba(0,0,0,0.08));
}
.cf-spark-label {
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-2, #2a2520);
  margin-bottom: 8px;
}
.cf-sparkline {
  width: 100%;
  height: auto;
  max-width: 360px;
}
.cf-spark-note {
  margin-top: 8px;
  font-family: var(--sans);
  font-size: 10.5px;
  color: var(--ink-fade, #6a655e);
  line-height: 1.5;
  font-style: italic;
}

/* ── Loading / spinner state ── */
.provenance-review-loading {
  padding: 28px 20px;
  text-align: center;
  font-family: var(--sans);
  color: var(--ink-2, #2a2520);
}
.provenance-review-loading p {
  margin: 8px 0 0;
  font-size: 12.5px;
}
.provenance-review-loading-detail {
  font-size: 11px;
  color: var(--ink-fade, #6a655e);
  font-style: italic;
}
.provenance-review-spinner {
  width: 28px;
  height: 28px;
  margin: 0 auto;
  border: 3px solid rgba(0,0,0,0.10);
  border-top-color: var(--red, #b83829);
  border-radius: 50%;
  animation: provenance-spinner-spin 0.8s linear infinite;
}
@keyframes provenance-spinner-spin {
  to { transform: rotate(360deg); }
}

/* ── Print styles for the academic-integrity file ──
   When the teacher prints the dashboard, hide PIP/scrubber UI,
   show all flags expanded, show the composition fingerprint
   expanded, and use plain colors instead of background tints so
   it photocopies legibly. */
@media print {
  body { background: white !important; color: black !important; }
  /* Hide UI chrome that doesn't belong in the printed record. */
  #prov-pip-replay,
  .provenance-review-replay,
  .provenance-review-sort,
  .provenance-review-filter-chips,
  .provenance-review-bulk-btn,
  .provenance-review-export-btn,
  .provenance-review-import-btn,
  .provenance-review-flagged-jump,
  .prov-pip-replay-shortcuts {
    display: none !important;
  }
  /* Expand the fingerprint panel automatically when printing. */
  .provenance-review-fingerprint {
    page-break-inside: avoid;
  }
  .provenance-review-fingerprint > summary {
    pointer-events: none;
  }
  .provenance-review-fingerprint > summary + * { display: block !important; }
  .provenance-review-fingerprint[open] { display: block; }
  details[open] { display: block; }
  /* Severity badges as filled shapes (not just color) */
  .provenance-review-flagged-sev::before { content: "[" attr(data-severity) "] "; font-size: 10px; }
  /* No expensive backgrounds */
  .provenance-review-flagged-item,
  .provenance-review-fingerprint,
  .cf-spark-block,
  .provenance-review-progress {
    background: white !important;
    border: 1px solid #888 !important;
    page-break-inside: avoid;
  }
  /* Make every flag's decision row print as readable text */
  .provenance-review-flagged-decision-btn {
    background: white !important;
    color: black !important;
    border: 1px solid #888 !important;
  }
  /* Header with title for the print copy */
  .provenance-review-summary::before {
    content: "Provenance Review — printed for academic file";
    display: block;
    font-size: 14px;
    font-weight: bold;
    margin-bottom: 8px;
    border-bottom: 2px solid black;
    padding-bottom: 6px;
  }
}

/* Flash on the canvas when "Show in document" is clicked on a
   style-shift flag — quickly draws the eye to the paragraph the
   detector flagged. Decays in 2.4s. */
.provenance-style-flash {
  background: rgba(107, 70, 193, 0.18);
  box-shadow: 0 0 0 4px rgba(107, 70, 193, 0.10);
  border-radius: 3px;
  animation: provenance-style-flash-anim 2.4s ease-out;
}
@keyframes provenance-style-flash-anim {
  0%   { background: rgba(107, 70, 193, 0.40); box-shadow: 0 0 0 8px rgba(107, 70, 193, 0.25); }
  100% { background: rgba(107, 70, 193, 0.00); box-shadow: 0 0 0 0 rgba(107, 70, 193, 0.00); }
}

.prov-pip-replay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 10px 14px;
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.08));
  background: var(--paper-soft, rgba(0,0,0,0.02));
}
.prov-pip-replay-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--ink-2, #2a2520);
}
.prov-pip-replay-close {
  appearance: none;
  border: 0;
  background: transparent;
  font-size: 20px;
  line-height: 1;
  color: var(--ink-fade, #6a655e);
  cursor: pointer;
  padding: 0 4px;
  border-radius: 4px;
}
.prov-pip-replay-close:hover {
  background: rgba(0,0,0,0.06);
  color: var(--ink, #1a1714);
}

.prov-pip-replay-stage {
  position: relative;
  width: 100%;
  /* Holds the text panel underneath + cursor/trail overlaid on top.
     Bounded height so very long doc excerpts scroll internally
     instead of stretching the PIP. */
  min-height: 200px;
  max-height: 320px;
  overflow: hidden;
  background: var(--paper, #FAF8F2);
  border-bottom: 1px solid var(--rule, rgba(0,0,0,0.06));
}
.prov-pip-replay-trail {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}
.prov-pip-replay-trail polyline {
  fill: none;
  stroke: var(--red, #b83829);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.65;
  filter: drop-shadow(0 0 4px rgba(184, 56, 41, 0.5));
}
/* Legacy outer cursor — kept in the DOM for backward compat with
   any callers, but hidden by default. The active cursor is now
   .prov-pip-viewport-cursor inside the viewport mirror. */
.prov-pip-replay-cursor {
  position: absolute;
  top: 0;
  left: 0;
  width: 22px;
  height: 28px;
  opacity: 0;
  pointer-events: none;
}

/* Active cursor — lives INSIDE the viewport mirror so it scrolls
   with the document. Inline `transform: translate(x, y) scale(1/s)`
   set by paintStage: translate positions it in viewport-native
   coords, scale undoes the parent's shrink so the arrow stays a
   visually constant ~22×28 regardless of the page-shrink factor. */
.prov-pip-viewport-cursor {
  width: 22px;
  height: 28px;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 22 28'><path d='M1 1 L1 21 L6 17 L9.5 25 L13 23.5 L9.5 15.5 L17 15.5 Z' fill='%23b83829' stroke='white' stroke-width='1.4' stroke-linejoin='round'/></svg>");
  background-repeat: no-repeat;
  background-size: contain;
  filter: drop-shadow(0 0 6px rgba(184, 56, 41, 0.55))
          drop-shadow(0 1px 2px rgba(0,0,0,0.25));
  transition: transform 50ms linear;
  will-change: transform;
  z-index: 3;
  pointer-events: none;
}

/* Trail inside the viewport mirror — strokes are kept at constant
   visual width via vector-effect="non-scaling-stroke" set on each
   polyline at render time. */
.prov-pip-viewport-trail polyline {
  fill: none;
  stroke: var(--red, #b83829);
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.65;
  filter: drop-shadow(0 0 4px rgba(184, 56, 41, 0.5));
}

/* Hint line under the stage — used by the paste preview to explain
   what the highlighted span is. Cursor flags leave it empty. */
.prov-pip-replay-stage-hint {
  font-size: 10px;
  line-height: 1.4;
  color: var(--ink-fade, #6a655e);
  padding: 6px 14px 0;
  font-style: italic;
}
.prov-pip-replay-stage-hint:empty { display: none; }

/* Text panel — lives INSIDE the stage as its background layer. The
   cursor + trail draw over it via absolute positioning. The mirror
   inside renders the text at the writing canvas's native font + width
   then transform-scales down to fit the PIP stage, so word-wrap
   positions line up with the document the teacher is referencing. */
.prov-pip-replay-text-inner {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  overflow-x: hidden;
  padding: 10px 14px;
  color: var(--ink, #1a1714);
  z-index: 1;
}
.prov-pip-text-scaler {
  /* Outer wrapper sized to scaled-viewport dimensions so the
     scrollable container has correct height. */
  position: relative;
  overflow: hidden;
}
/* Viewport mirror — sized to the recorded viewport (recVw × recVh)
   then CSS-transformed to fit the PIP stage. The prose mirror lives
   inside it at its real viewport coordinates. */
.prov-pip-viewport-mirror {
  position: absolute;
  top: 0;
  left: 0;
  transform-origin: top left;
  background: var(--paper, #FAF8F2);
  /* Subtle inner grid so the teacher can see the "shrunken page"
     framing — without it the viewport reads as an unstructured slab
     and the prose just floats. */
  background-image:
    linear-gradient(180deg, rgba(0,0,0,0.02), rgba(0,0,0,0.04));
}
.prov-pip-text-mirror {
  white-space: pre-wrap;
  word-wrap: break-word;
  word-break: normal;
  /* No font/size set here — set inline by paintText() to match the
     live #prose element exactly. position+left+top+width set inline. */
}
/* When the mirror also carries class="prose" (for cascade
   inheritance) we still need to neutralize a few prose rules that
   would otherwise distort the mirror: the line-height transition
   would animate every repaint, and the margin: auto would push the
   absolute-positioned box around. */
.prov-pip-text-mirror.prose {
  transition: none !important;
  margin: 0 !important;
}
.prov-pip-text-caret {
  display: inline-block;
  color: var(--red, #b83829);
  font-weight: 700;
  margin: 0 -1px;
  animation: prov-pip-caret-blink 1s steps(2, end) infinite;
}
@keyframes prov-pip-caret-blink {
  0%, 50%  { opacity: 1; }
  51%,100% { opacity: 0.25; }
}
.prov-pip-text-ell {
  color: var(--ink-fade, #6a655e);
  opacity: 0.55;
  padding: 0 2px;
}
.prov-pip-text-recent {
  background: rgba(184, 56, 41, 0.10);
  color: var(--red, #b83829);
  border-bottom: 1px solid rgba(184, 56, 41, 0.35);
  padding: 0 1px;
  border-radius: 2px;
}
.prov-pip-text-paste {
  color: rgba(184, 56, 41, 0.55);
  background: rgba(184, 56, 41, 0.06);
  border-radius: 2px;
  padding: 0 1px;
  letter-spacing: 0.5px;
  cursor: help;
}

/* ── Paste-flag preview styling ──────────────────────────────────
   Shown when the flag is a paste (we can't replay paste content from
   keystrokes — it isn't in the stream). The header chip shows the
   paste size + position, the body shows the FINAL document text with
   the recorded paste range highlighted so a teacher can actually
   read what the student dropped in. */
.prov-pip-text-paste-head {
  display: inline-block;
  font-family: var(--sans);
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--red, #b83829);
  background: rgba(184, 56, 41, 0.08);
  padding: 3px 8px;
  border-radius: 999px;
  margin-bottom: 8px;
}
.prov-pip-text-paste-body {
  font-family: var(--serif, Georgia, serif);
  font-size: 13px;
  line-height: 1.6;
  color: var(--ink, #1a1714);
}
.prov-pip-text-pasted {
  background: rgba(184, 56, 41, 0.15);
  color: var(--ink, #1a1714);
  border-bottom: 2px solid rgba(184, 56, 41, 0.5);
  padding: 0 2px;
  border-radius: 2px;
  /* Slight font weight bump so the paste is unmistakable when the
     teacher's eye scans the doc excerpt. */
  font-weight: 500;
}
/* Chars the student TYPED inside the paste range, post-paste — they
   shouldn't get the red highlight (that would falsely accuse those
   chars of being pasted). Subtle dotted underline shows the teacher
   "the student edited the paste here" without conflating it with
   the original paste content. */
.prov-pip-text-edited {
  border-bottom: 1px dotted rgba(0,0,0,0.35);
  background: rgba(0,0,0,0.02);
  cursor: help;
}
.prov-pip-text-trunc {
  display: inline-block;
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  color: var(--ink-fade, #6a655e);
  background: rgba(0,0,0,0.04);
  padding: 1px 7px;
  border-radius: 4px;
  margin: 0 4px;
  vertical-align: middle;
}

/* Explicit paste boundary markers — leave no doubt where the paste
   begins and ends, especially when the student has edited inside
   the paste range after dropping it. */
.prov-pip-paste-boundary {
  display: inline-block;
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 9.5px;
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--red, #b83829);
  background: rgba(184, 56, 41, 0.12);
  border: 1px solid rgba(184, 56, 41, 0.35);
  padding: 1px 6px;
  margin: 0 3px;
  border-radius: 999px;
  vertical-align: 1px;
  cursor: help;
  white-space: nowrap;
}
.prov-pip-paste-boundary-start { background: rgba(184, 56, 41, 0.18); }
.prov-pip-paste-boundary-end   { background: rgba(184, 56, 41, 0.08); }

/* "Some characters are missing" notice — surfaces the case where the
   student pasted, then deleted part of it. Without this row a
   teacher would just see a shorter highlight and wonder if the
   detector was wrong. */
.prov-pip-paste-shortfall {
  margin-top: 10px;
  padding: 6px 10px;
  border-radius: 6px;
  background: rgba(201, 138, 26, 0.10);
  border-left: 3px solid #c98a1a;
  color: var(--ink-2, #2a2520);
  font-family: var(--sans);
  font-size: 11px;
  line-height: 1.45;
}

/* ── PIP scrubber tick marks ──
   Visual proof that ±5s really IS 5 seconds. Without these the eye
   has nothing to scale against and a sparse log reads as a bug.
   Positioned absolutely over the input's column — paintStamps()
   measures the input's actual bounding rect each repaint. */
.prov-pip-replay-scrubrow { position: relative; }
.prov-pip-replay-ticks {
  position: absolute;
  bottom: 4px;           /* tuck under the range input */
  height: 8px;
  pointer-events: none;
}
.prov-pip-replay-tick {
  position: absolute;
  top: 2px;
  width: 1px;
  height: 4px;
  background: var(--ink-fade, #6a655e);
  opacity: 0.35;
  transform: translateX(-0.5px);
}
.prov-pip-replay-tick.is-major {
  height: 7px;
  top: 0;
  opacity: 0.55;
  width: 1.5px;
  background: var(--red, #b83829);
}

/* ── Log boundary + idle rows ── */
.prov-pip-replay-log-row.is-boundary {
  color: var(--ink-fade, #6a655e);
  font-style: italic;
  opacity: 0.7;
  border-top: 1px dashed rgba(0,0,0,0.12);
  border-bottom: 1px dashed rgba(0,0,0,0.12);
  margin: 2px 0;
}
.prov-pip-replay-log-row.is-idle {
  color: var(--ink-fade, #6a655e);
  font-style: italic;
  opacity: 0.6;
}
.prov-pip-replay-log-row.is-idle .prov-pip-replay-log-text {
  text-align: center;
}

.prov-pip-replay-scrubrow {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 8px;
  padding: 10px 14px 6px;
}
.prov-pip-replay-stamp {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  color: var(--ink-fade, #6a655e);
  min-width: 36px;
  text-align: center;
}
.prov-pip-replay-scrubrow input[type="range"] {
  width: 100%;
  accent-color: var(--red, #b83829);
}

.prov-pip-replay-controls {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 4px 14px 10px;
  gap: 8px;
}
.prov-pip-replay-window {
  display: inline-flex;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  border-radius: 999px;
  overflow: hidden;
  background: var(--paper, #FAF8F2);
}
.prov-pip-replay-window-btn {
  appearance: none;
  border: 0;
  background: transparent;
  font-family: inherit;
  font-size: 11px;
  font-weight: 500;
  padding: 4px 10px;
  cursor: pointer;
  color: var(--ink-fade, #6a655e);
  transition: background 120ms ease, color 120ms ease;
}
.prov-pip-replay-window-btn:hover { background: rgba(0,0,0,0.04); }
.prov-pip-replay-window-btn.is-active {
  background: var(--ink, #1a1714);
  color: var(--paper, #FAF8F2);
}
/* Play / Pause / Replay button. Real-time playback advances the
   scrubber from current position to window end at 1× speed so the
   cursor and keystrokes animate at the cadence the student
   actually produced them. */
.prov-pip-replay-play {
  appearance: none;
  border: 1px solid var(--red, #b83829);
  background: var(--red, #b83829);
  color: var(--paper, #FAF8F2);
  font-family: var(--sans);
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  padding: 5px 12px;
  border-radius: 999px;
  letter-spacing: 0.02em;
  transition: background 120ms ease, transform 80ms ease;
  min-width: 78px;
}
.prov-pip-replay-play:hover {
  background: #c64534;
}
.prov-pip-replay-play:active {
  transform: translateY(1px);
}

.prov-pip-replay-fullscrub {
  appearance: none;
  border: 0;
  background: transparent;
  color: var(--red, #b83829);
  font-family: inherit;
  font-size: 11px;
  font-weight: 600;
  cursor: pointer;
  padding: 4px 6px;
  border-radius: 6px;
  letter-spacing: 0.02em;
}
.prov-pip-replay-fullscrub:hover {
  background: rgba(184, 56, 41, 0.08);
  text-decoration: underline;
}

.prov-pip-replay-log {
  max-height: 160px;
  overflow-y: auto;
  border-top: 1px solid var(--rule, rgba(0,0,0,0.08));
  padding: 8px 14px;
  background: var(--paper-soft, rgba(0,0,0,0.015));
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  line-height: 1.5;
}
.prov-pip-replay-log-row {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: 8px;
  padding: 2px 0;
  color: var(--ink-2, #2a2520);
  border-radius: 3px;
}
.prov-pip-replay-log-row.is-flag {
  background: rgba(184, 56, 41, 0.08);
  color: var(--red, #b83829);
  font-weight: 600;
}
.prov-pip-replay-log-stamp {
  color: var(--ink-fade, #6a655e);
  text-align: right;
}
.prov-pip-replay-log-row.is-flag .prov-pip-replay-log-stamp {
  color: var(--red, #b83829);
}

/* Keyboard shortcuts hint at the bottom of the PIP. Tiny so it
   doesn't compete for attention; readable for discovery. */
.prov-pip-replay-shortcuts {
  padding: 6px 14px 8px;
  background: rgba(0,0,0,0.02);
  border-top: 1px solid var(--rule, rgba(0,0,0,0.06));
  font-family: var(--sans);
  font-size: 10px;
  color: var(--ink-fade, #6a655e);
  text-align: center;
  line-height: 1.6;
}
.prov-pip-replay-shortcuts kbd {
  display: inline-block;
  padding: 0 4px;
  margin: 0 1px;
  border: 1px solid var(--rule, rgba(0,0,0,0.18));
  border-radius: 3px;
  background: var(--paper, #FAF8F2);
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 9.5px;
  color: var(--ink-2, #2a2520);
  font-weight: 600;
}

/* "View full session" button appears next to the main scrubber's
   time display once the teacher has handed off from the PIP. */
.prov-scrub-restore-btn {
  appearance: none;
  border: 1px solid var(--rule, rgba(0,0,0,0.15));
  background: var(--paper, #FAF8F2);
  color: var(--ink-2, #2a2520);
  font-family: var(--sans);
  font-size: 10.5px;
  font-weight: 500;
  padding: 3px 9px;
  border-radius: 999px;
  cursor: pointer;
  margin-left: 8px;
  transition: background 120ms ease;
}
.prov-scrub-restore-btn:hover { background: rgba(0,0,0,0.04); }

/* Detailed signal summary is collapsed by default now. */
.provenance-review-signals-detail {
  margin: 16px 0;
}
.provenance-review-signals-detail > summary {
  cursor: pointer;
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-fade);
  padding: 6px 0;
  list-style: none;
}
.provenance-review-signals-detail > summary::-webkit-details-marker { display: none; }
.provenance-review-signals-detail[open] > summary { color: var(--ink-2); }
.provenance-review-dot {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  margin-right: 4px;
  vertical-align: 1px;
}
.provenance-review-dot.is-green  { background: #4a8a4a; }
.provenance-review-dot.is-yellow { background: #c98a1a; }
.provenance-review-dot.is-red    { background: var(--red); }
.provenance-review-disclaimer {
  grid-column: 1 / 3;
  margin: 4px 0 0;
  font-size: 11px;
  color: var(--ink-fade);
  font-style: italic;
}
.provenance-review-source {
  display: inline-block;
  margin-top: 4px;
  font-style: normal;
  font-size: 10.5px;
  font-family: var(--mono);
  color: var(--ink-fade);
}

.provenance-review-signals {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.provenance-review-signal {
  display: grid;
  grid-template-columns: 14px 1fr;
  gap: 10px;
  padding: 8px 10px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
}
.provenance-review-signal[data-status="green"]  { border-left: 3px solid #4a8a4a; }
.provenance-review-signal[data-status="yellow"] { border-left: 3px solid #c98a1a; }
.provenance-review-signal[data-status="red"]    { border-left: 3px solid var(--red); }
.provenance-review-signal-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  align-self: center;
  margin-top: 3px;
}
.provenance-review-signal[data-status="green"]  .provenance-review-signal-dot { background: #4a8a4a; }
.provenance-review-signal[data-status="yellow"] .provenance-review-signal-dot { background: #c98a1a; }
.provenance-review-signal[data-status="red"]    .provenance-review-signal-dot { background: var(--red); }
.provenance-review-signal-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 10px;
}
.provenance-review-signal-label { font-size: 12.5px; font-weight: 600; color: var(--ink); }
.provenance-review-signal-value { font-family: var(--mono); font-size: 11px; color: var(--ink-fade); }
.provenance-review-signal-note  { font-size: 11.5px; color: var(--ink-2); margin-top: 2px; line-height: 1.4; }

/* Replay scrubber. */
.provenance-review-replay {
  margin-top: 16px;
  padding: 12px;
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  background: var(--paper);
}
.provenance-review-replay-head {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 8px;
}
.provenance-review-section-label {
  font-size: 10.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.provenance-review-replay-time {
  font-family: var(--mono);
  font-size: 11px;
  color: var(--ink-2);
}
.provenance-review-replay-track {
  position: relative;
  height: 6px;
  background: var(--paper-edge);
  border-radius: 3px;
  margin-bottom: 8px;
  overflow: visible;
}
.provenance-review-replay-bar {
  position: absolute;
  top: 0;
  left: 0;
  height: 100%;
  background: var(--red);
  border-radius: 3px;
  width: 0%;
}
.provenance-review-marker {
  position: absolute;
  top: -2px;
  width: 2px;
  height: 10px;
  border-radius: 1px;
  pointer-events: none;
}
.provenance-review-marker.replay-marker-paste { background: var(--red); }
.provenance-review-marker.replay-marker-focus { background: #c98a1a; }
.provenance-review-marker.replay-marker-leave { background: #4a8a8a; }

/* ── Focused-mode track ───────────────────────────────────────────
   When a teacher clicks "Open scrubbable replay" inside a PIP, we
   add a SECOND track below the full-session one — zoomed into the
   ±2.5min window so dragging happens at human scale. The full track
   stays visible (gets a "you are here" focus-region highlight) so
   the teacher always knows where the zoom sits in the whole essay.

   The scrubber input below drives the focused track's fill — not
   the full one. The full bar still tracks the absolute time so the
   eye can map the playhead between the two scales. */
.provenance-review-focus-region {
  position: absolute;
  top: -3px;
  height: 12px;
  background: rgba(184, 56, 41, 0.10);
  border-left:  2px solid rgba(184, 56, 41, 0.55);
  border-right: 2px solid rgba(184, 56, 41, 0.55);
  pointer-events: none;
  border-radius: 2px;
  z-index: 1;
}
.provenance-review-focus-track {
  margin: 10px 0 8px;
  padding: 8px 10px 10px;
  background: rgba(184, 56, 41, 0.04);
  border: 1px solid rgba(184, 56, 41, 0.18);
  border-radius: 8px;
}
.provenance-review-focus-track-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  font-family: var(--sans);
  font-size: 10px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--red, #b83829);
  margin-bottom: 6px;
}
.provenance-review-focus-track-range {
  font-family: var(--mono, ui-monospace, SFMono-Regular, Menlo, monospace);
  font-size: 10.5px;
  color: var(--ink-fade, #6a655e);
  letter-spacing: 0;
  text-transform: none;
}
.provenance-review-focus-track-bar {
  position: relative;
  height: 14px;
  background: var(--paper-edge);
  border-radius: 7px;
  overflow: visible;
  /* When the input lives INSIDE this bar (focused mode), the bar
     becomes the entire scrubbable surface. Markers + fill render
     beneath; the input renders on top with a transparent track
     so the thumb is the only visible draggable. */
}
.provenance-review-focus-track-fill {
  position: absolute;
  top: 3px;
  left: 0;
  height: 8px;
  background: var(--red);
  border-radius: 4px;
  width: 0%;
  pointer-events: none;
}

/* ── Input overlay inside the focused bar ── */
#provenance-review-replay-scrub.is-focused-overlay {
  position: absolute;
  inset: -4px 0;            /* slightly larger hit area than the visual bar */
  width: 100%;
  height: calc(100% + 8px);
  margin: 0;
  padding: 0;
  background: transparent;
  -webkit-appearance: none;
  appearance: none;
  cursor: grab;
  z-index: 2;
}
#provenance-review-replay-scrub.is-focused-overlay:active { cursor: grabbing; }
#provenance-review-replay-scrub.is-focused-overlay::-webkit-slider-runnable-track {
  background: transparent;
  height: 100%;
}
#provenance-review-replay-scrub.is-focused-overlay::-moz-range-track {
  background: transparent;
  height: 100%;
}
#provenance-review-replay-scrub.is-focused-overlay::-webkit-slider-thumb {
  -webkit-appearance: none;
  appearance: none;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--red, #b83829);
  border: 3px solid var(--paper, #FAF8F2);
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
  margin-top: 1px;
  cursor: grab;
}
#provenance-review-replay-scrub.is-focused-overlay::-moz-range-thumb {
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--red, #b83829);
  border: 3px solid var(--paper, #FAF8F2);
  box-shadow: 0 1px 4px rgba(0,0,0,0.25);
  cursor: grab;
}

#provenance-review-replay-scrub {
  width: 100%;
  accent-color: var(--red);
}
.provenance-review-replay-event {
  font-family: var(--mono);
  font-size: 11.5px;
  color: var(--ink-2);
  background: var(--paper-edge);
  padding: 6px 10px;
  border-radius: 4px;
  margin-top: 8px;
  min-height: 28px;
}

/* =========================================================================
   Editorial memo pane — per-doc structural feedback (Step 13)
   ========================================================================= */
.memo-panel {
  position: fixed;
  top: var(--tb-h);
  right: 0;
  bottom: 0;
  width: 480px;
  max-width: 100vw;
  z-index: 60;
  background: var(--paper);
  border-left: 1px solid var(--hair-strong);
  box-shadow: -2px 0 12px rgba(28,26,23,0.06);
  display: flex;
  flex-direction: column;
  font-family: var(--sans);
  transform: translateX(0);
  transition: transform 220ms cubic-bezier(.2,.7,.3,1);
}
.memo-panel[hidden] {
  display: flex;
  transform: translateX(100%);
  pointer-events: none;
}
.memo-header {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid var(--hair);
}
.memo-header h2 {
  margin: 0;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  color: var(--ink-2);
  flex: 1;
}
.memo-title {
  border: 0;
  border-bottom: 1px solid var(--hair);
  outline: none;
  padding: 14px 18px;
  font-family: var(--serif);
  font-size: 17px;
  font-weight: 600;
  color: var(--ink);
  background: transparent;
}
.memo-title:focus {
  background: var(--paper-edge);
}
.memo-body {
  /* When the teacher block isn't present (editor/author/student),
     the body should fill the remaining height. When it IS present,
     we use a flexible min-height to keep at least a few lines of
     typing room without pushing the footer below the viewport. */
  flex: 1 1 auto;
  min-height: 160px;
  border: 0;
  outline: none;
  padding: 14px 18px;
  font-family: var(--prose);
  font-size: 14.5px;
  line-height: 1.6;
  color: var(--ink);
  background: transparent;
  resize: none;
}
.memo-body:focus {
  background: var(--paper-edge);
}

/* Teacher document workspace — sections inside the memo panel.
   Shown only when the role is Teacher AND the doc has an associated
   submission. Renders above the legacy Notes (title + body). */
.memo-teacher-block {
  overflow-y: auto;
  padding: 12px 16px;
  border-bottom: 1px solid var(--hair);
  max-height: 60vh;
}
.memo-assignment-meta {
  display: grid;
  grid-template-columns: 6px 1fr;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
  margin-bottom: 12px;
}
.memo-assignment-stripe { width: 6px; }
.memo-assignment-body   { padding: 10px 12px; }
/* Clickable variant — full card acts as a button that drills into
   the teacher dashboard scoped to this assignment's classroom. */
.memo-assignment-body-clickable {
  cursor: pointer;
  transition: background var(--t-fast);
  outline-offset: -2px;
}
.memo-assignment-body-clickable:hover { background: var(--paper-edge); }
.memo-assignment-body-clickable:focus { outline: 2px solid var(--red); }
.memo-assignment-body-clickable::after {
  content: '↗';
  float: right;
  font-size: 14px;
  color: var(--ink-fade);
  margin-left: 8px;
  transition: color var(--t-fast), transform var(--t-fast);
}
.memo-assignment-body-clickable:hover::after {
  color: var(--red);
  transform: translate(2px, -2px);
}
.memo-assignment-label  {
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-fade);
  font-weight: 600;
  margin-bottom: 2px;
}
.memo-assignment-title {
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
}
.memo-assignment-meta-row {
  font-size: 12px;
  color: var(--ink-soft);
  display: flex;
  gap: 6px;
  margin-top: 2px;
}
.memo-assignment-instructions {
  margin: 8px 0 0;
  font-size: 12.5px;
  color: var(--ink-soft);
  line-height: 1.5;
  white-space: pre-wrap;
}

.memo-section {
  margin-bottom: 8px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  overflow: hidden;
}
.memo-section summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 10px 12px;
  background: var(--paper-edge);
  font-size: 12.5px;
  color: var(--ink);
}
.memo-section summary::-webkit-details-marker { display: none; }
.memo-section summary:hover { background: color-mix(in srgb, var(--paper-edge) 70%, var(--ink) 6%); }
.memo-section[open] summary {
  border-bottom: 1px solid var(--hair);
}
.memo-section-label  { font-weight: 600; }
.memo-section-meta   { color: var(--ink-fade); font-size: 11.5px; }
.memo-section-body   { padding: 12px; }
.memo-section-body p { margin: 0 0 10px; }

.memo-messages-thread {
  max-height: 240px;
  overflow-y: auto;
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 6px 0;
  margin-bottom: 10px;
}
.memo-message-form {
  display: flex;
  gap: 8px;
  align-items: flex-end;
  padding-top: 8px;
  border-top: 1px solid var(--hair);
}
.memo-message-form textarea {
  flex: 1;
  resize: vertical;
  min-height: 44px;
  font-family: var(--sans);
  font-size: 13px;
  padding: 8px 10px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
}

.memo-consistency-actions {
  display: flex;
  gap: 8px;
  flex-wrap: wrap;
  align-items: center;
}

/* AGS passback status pill — shows next to the Save rubric button
   when the assignment is bound to a Canvas lineitem. State attribute
   drives the color (green/red). Self-hides after success. */
.ags-status-pill {
  display: inline-flex;
  align-items: center;
  font-family: var(--sans);
  font-size: 12px;
  padding: 4px 10px;
  border-radius: 999px;
  border: 1px solid var(--rule);
}
.ags-status-pill[data-state="ok"] {
  background: rgba(47, 138, 74, 0.10);
  border-color: #2f8a4a;
  color: #2f8a4a;
}
.ags-status-pill[data-state="err"] {
  background: rgba(184, 56, 41, 0.10);
  border-color: var(--red);
  color: var(--red);
  cursor: help;
}

.memo-notes-section {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}
.memo-notes-heading {
  margin: 0;
  padding: 10px 16px 6px;
  font-size: 10.5px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--ink-fade);
  font-weight: 600;
}

/* Teacher mode hides the legacy memo notes (title + body) entirely.
   The teacher's workspace lives in the assignment-block above and
   covers the full panel. Notes-section element + heading stay in the
   DOM so the JS reading anno.memo doesn't break; just visually gone. */
body.memo-teacher-mode .memo-notes-section { display: none; }
/* Without notes, let the teacher block fill the available height
   instead of being capped to 60vh. */
body.memo-teacher-mode .memo-teacher-block {
  max-height: none;
  flex: 1 1 auto;
}
/* Messages tab — hide every other inner section so the message
   thread fills the whole panel. The assignment meta card stays
   so the teacher always sees who they're talking to. */
body.memo-messages-tab #memo-assignment-meta { display: block; }
body.memo-messages-tab #memo-provenance-section,
body.memo-messages-tab #memo-rubric-section,
body.memo-messages-tab #memo-consistency-section { display: none; }
body.memo-messages-tab #memo-messages-section {
  display: block;
}
body.memo-messages-tab #memo-messages-section > summary {
  display: none;   /* no need for the disclosure — we're in dedicated mode */
}
body.memo-messages-tab #memo-messages-section .memo-section-body {
  display: block;
  padding-top: 4px;
}
body.memo-messages-tab #memo-messages-section[open],
body.memo-messages-tab #memo-messages-section:not([open]) {
  /* Force the details to behave as if always-open since we hide its summary. */
  display: block;
}
.memo-footer {
  padding: 8px 18px;
  border-top: 1px solid var(--hair);
  font-size: 11px;
  color: var(--ink-fade);
  display: flex;
  align-items: center;
  justify-content: space-between;
}
.memo-status {
  font-family: var(--mono);
  letter-spacing: 0.02em;
}

/* Sidebar memo button — uses the same pill styling as the export pill */
.sidebar-memo-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-start;
}

/* --- generic Red Stet modal -------------------------------------------- */
.rm-modal {
  position: fixed;
  inset: 0;
  z-index: 999;
  display: flex;
  align-items: center;
  justify-content: center;
}
.rm-modal[hidden] { display: none; }
.rm-modal-scrim {
  position: absolute;
  inset: 0;
  background: rgba(26, 24, 21, 0.32);
  backdrop-filter: blur(2px);
}
.rm-modal-card {
  position: relative;
  width: min(440px, 92vw);
  background: var(--paper);
  border-radius: 12px;
  padding: 26px 28px 22px;
  box-shadow: 0 18px 48px -16px rgba(26, 24, 21, 0.35);
  font-family: var(--sans);
  color: var(--ink);
}
.rm-modal-card h2 {
  margin: 0 0 6px;
  font-family: var(--display);
  font-weight: 500;
  font-size: 20px;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.rm-modal-help {
  margin: 0 0 18px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--ink-soft);
}
.rm-modal-help code {
  background: var(--paper-edge);
  padding: 1px 5px;
  border-radius: 3px;
  font-size: 12px;
}
.rm-field {
  display: block;
  margin: 0 0 12px;
}
.rm-field > span {
  display: block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-fade);
  margin-bottom: 4px;
}
.rm-field > span small {
  font-weight: 400;
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-fade);
}
.rm-field input,
.rm-field textarea {
  width: 100%;
  padding: 9px 11px;
  border: 1px solid var(--hair-strong);
  border-radius: 6px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 14px;
  transition: border-color 120ms ease, box-shadow 120ms ease;
  resize: vertical;
  line-height: 1.45;
}
.rm-field input:focus,
.rm-field textarea:focus {
  outline: none;
  border-color: var(--red);
  box-shadow: 0 0 0 3px rgba(184, 58, 44, 0.12);
}

/* First-class teacher CTA on the sign-in modal step 1.
   Replaces the old buried "Are you signing up as a teacher?" link. */
.signin-teacher-tile {
  margin-top: 12px;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 14px 16px;
  background: rgba(40, 80, 60, 0.05);
  border: 1px solid rgba(40, 80, 60, 0.15);
  border-radius: 10px;
  text-decoration: none;
  color: var(--ink);
  transition: background 120ms ease, border-color 120ms ease, transform 80ms ease;
  cursor: pointer;
}
.signin-teacher-tile:hover {
  background: rgba(40, 80, 60, 0.08);
  border-color: rgba(40, 80, 60, 0.30);
}
.signin-teacher-tile:active {
  transform: scale(0.995);
}
.signin-teacher-tile-icon {
  font-size: 22px;
  flex-shrink: 0;
}
.signin-teacher-tile-body {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 3px;
}
.signin-teacher-tile-body strong {
  font-size: 14px;
  font-weight: 600;
}
.signin-teacher-tile-body span {
  font-size: 12px;
  color: var(--ink-fade);
  line-height: 1.4;
}
.signin-teacher-tile-chev {
  font-size: 16px;
  color: var(--ink-fade);
  flex-shrink: 0;
}
/* Provenance consent: terms checkbox + label as a single row. */
.rm-field-check {
  flex-direction: row;
  align-items: flex-start;
  gap: 8px;
  font-size: 12.5px;
  line-height: 1.4;
  color: var(--ink-2);
}
.rm-field-check input {
  width: auto;
  margin-top: 3px;
  flex: 0 0 auto;
}
.rm-field-check span {
  font-size: 12.5px;
  font-family: var(--sans);
  text-transform: none;
  letter-spacing: 0;
  color: var(--ink-2);
}
.rm-modal-actions {
  display: flex;
  justify-content: flex-end;
  gap: 8px;
  margin-top: 8px;
}
/* Explainer sections inside modals — "Why it's worth turning on" /
   "The fine print" headings + bulleted lists. Lighter weight than
   form fields so the modal reads as informational, not a form. */
.rm-explainer-section {
  margin: 14px 0 4px;
  padding: 10px 12px;
  background: var(--paper-edge);
  border-radius: 6px;
}
.rm-explainer-section h4 {
  margin: 0 0 6px;
  font-size: 12px;
  letter-spacing: 0.03em;
  color: var(--ink-soft);
  text-transform: uppercase;
  font-weight: 600;
}
.rm-explainer-list {
  margin: 0;
  padding-left: 18px;
}
.rm-explainer-list li {
  font-size: 13px;
  line-height: 1.45;
  color: var(--ink);
  margin-bottom: 6px;
}
.rm-explainer-list li:last-child { margin-bottom: 0; }
.rm-explainer-list strong { font-weight: 600; }
/* Radio-group field — kept for any future flows that need it.
   The sign-in modal previously used it for a writer-vs-teacher
   toggle; that toggle was replaced by a dedicated teacher screen
   reached via the "Are you signing up as a teacher?" hyperlink. */
.rm-field-radio {
  display: block;
  margin: 0 0 14px;
  padding: 0;
  border: 0;
}
.rm-field-radio legend {
  display: block;
  font-size: 11.5px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-fade);
  margin-bottom: 6px;
  padding: 0;
}
.rm-radio {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  margin-bottom: 6px;
  font-size: 13.5px;
  color: var(--ink);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.rm-radio:hover { border-color: var(--ink-2); }
.rm-radio input { accent-color: var(--red); }
.rm-radio:has(input:checked) {
  border-color: var(--red);
  background: var(--red-wash);
}
.rm-field-hint {
  display: block;
  margin-top: 6px;
  font-size: 11.5px;
  color: var(--ink-fade);
  line-height: 1.4;
}
.rm-field-err {
  color: var(--red);
}

/* Hyperlink row under the modal's primary action — used for the
   "Are you signing up as a teacher?" affordance on the standard
   sign-up step and the "Not a teacher? Use standard sign-up." link
   on the teacher screen. */
.rm-modal-link-row {
  margin: 14px 0 0 !important;
  text-align: center;
  font-size: 13px;
  color: var(--ink-fade);
}
.rm-modal-link {
  color: var(--red);
  text-decoration: underline;
  text-underline-offset: 2px;
  text-decoration-thickness: 1px;
  cursor: pointer;
}
.rm-modal-link:hover { color: var(--red-deep); }

/* Wide modal variant — the teacher sign-up screen carries enough
   legal context that the standard 440px width feels cramped. */
.rm-modal-card-wide {
  width: min(560px, 94vw);
  max-height: 92vh;
  overflow-y: auto;
}
.rm-modal-card-wide h2 { margin-bottom: 8px; }
/* Tall variant — used by the Provenance timeline where the content
   needs more vertical room and a wider column for the line-diff. */
.rm-modal-card-tall {
  width: min(760px, 95vw);
  max-height: 92vh;
  overflow-y: auto;
}

/* Provenance timeline ---------------------------------------------------
   Sessions are green-marker rows; gaps are red-stet rows with an
   expandable line-diff. Reads top-to-bottom in chronological order. */
.rm-timeline-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin: 0 0 4px;
}
.rm-modal-close {
  appearance: none;
  background: transparent;
  border: 0;
  font-size: 22px;
  line-height: 1;
  color: var(--ink-fade);
  cursor: pointer;
  padding: 0 4px;
}
.rm-modal-close:hover { color: var(--ink); }
.rm-timeline-list {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin-top: 12px;
}
.rm-timeline-empty {
  padding: 24px 0;
  text-align: center;
  color: var(--ink-fade);
  font-style: italic;
}
.rm-timeline-row {
  display: grid;
  grid-template-columns: 28px 1fr;
  gap: 10px;
  padding: 10px 12px;
  border: 1px solid var(--hair);
  border-radius: 8px;
  background: var(--paper);
}
.rm-timeline-row-gap {
  border-color: color-mix(in srgb, var(--red) 40%, var(--hair) 60%);
  background: color-mix(in srgb, var(--red) 5%, var(--paper) 95%);
}
.rm-timeline-marker {
  text-align: center;
  font-size: 14px;
  padding-top: 2px;
}
.rm-timeline-marker-session { color: var(--accent, #2b6a3f); }
.rm-timeline-marker-gap     { color: var(--red); }
.rm-timeline-body { min-width: 0; }
.rm-timeline-head-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 2px;
}
.rm-timeline-title { font-weight: 600; font-size: 13.5px; color: var(--ink); }
.rm-timeline-pill {
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 2px 6px;
  border-radius: 4px;
  background: var(--paper-edge);
  color: var(--ink-fade);
  text-transform: uppercase;
  font-family: var(--sans);
}
.rm-timeline-pill.is-open { background: var(--red); color: var(--paper); }
.rm-timeline-pill-warn    { background: var(--red); color: var(--paper); }
.rm-timeline-pill-cloud   { background: var(--accent, #2b4a6f); color: var(--paper); }
.rm-timeline-pill-row {
  display: inline-flex;
  gap: 4px;
  align-items: center;
}
.rm-timeline-meta {
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-top: 1px;
}
.rm-timeline-diff {
  margin-top: 8px;
  font-size: 12px;
}
.rm-timeline-diff summary {
  cursor: pointer;
  color: var(--ink-soft);
  font-size: 11.5px;
  padding: 2px 0;
}
.rm-timeline-diff summary:hover { color: var(--ink); }
.rm-diff-block {
  margin: 6px 0 0;
  padding: 8px 10px;
  background: var(--paper-edge);
  border: 1px solid var(--hair);
  border-radius: 6px;
  font-family: var(--mono);
  font-size: 11.5px;
  line-height: 1.45;
  max-height: 360px;
  overflow: auto;
  white-space: pre-wrap;
  word-break: break-word;
}
.rm-diff-line { padding: 0 4px; border-radius: 2px; }
.rm-diff-same { color: var(--ink-soft); }
.rm-diff-add  { background: color-mix(in srgb, #2b6a3f 12%, transparent); color: #1f5a31; }
.rm-diff-del  { background: color-mix(in srgb, var(--red) 12%, transparent);  color: var(--red); text-decoration: line-through; }

/* In-modal explainer sections — each one is a heading + a short
   paragraph, separated by hairlines. Lighter weight than the modal
   help intro so they don't fight the form below them for attention. */
.signin-section {
  margin: 14px 0;
  padding-top: 14px;
  border-top: 1px solid var(--hair);
}
.signin-section h3 {
  margin: 0 0 6px;
  font-family: var(--sans);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--ink-fade);
}
.signin-section p {
  margin: 0;
  font-size: 13px;
  line-height: 1.55;
  color: var(--ink-soft);
}
.signin-section p strong {
  color: var(--ink);
  font-weight: 600;
}

/* --- Sign-in CTA -------------------------------------------------------
   Appended below the welcome doc's "Ready to use Red Stet?" section
   when the user is logged out. Just a button + a one-line follow-up,
   no duplicate heading or paragraph (the doc body already carries the
   pitch copy). */
.signin-cta {
  max-width: var(--reader-max);
  margin: 24px auto 80px;
  text-align: left;
}
.signin-cta .signin-cta-btn {
  font-size: 14px;
  padding: 10px 22px;
  border-radius: 8px;
}
.signin-cta-fine {
  margin: 12px 0 0;
  font-size: 12px;
  color: var(--ink-fade);
}

/* Settings-tab foot link — bottom-of-panel utility row for things
   like "Reset role preset" that need to be discoverable but
   shouldn't compete with the main toggles. */
.settings-foot-link {
  margin: 24px 0 8px;
  padding-top: 16px;
  border-top: 1px solid var(--hair);
  text-align: center;
  font-size: 12.5px;
}

/* Role selection modal — appears once after first sign-in. Four
   stacked cards, one per role preset. Same visual language as the
   Customizations role-preset cards but in a centered modal. */
.role-select-grid {
  display: flex;
  flex-direction: column;
  gap: 10px;
  margin: 16px 0 6px;
}
.role-select-card {
  appearance: none;
  background: var(--paper);
  border: 1px solid var(--hair-strong);
  border-radius: 8px;
  padding: 12px 14px;
  text-align: left;
  font-family: var(--sans);
  cursor: pointer;
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  gap: 12px 10px;
  transition: border-color 120ms ease, background 120ms ease;
}
.role-select-card[hidden] { display: none !important; }
.role-select-card:hover { border-color: var(--ink-2); background: var(--paper-edge); }
.role-select-glyph {
  font-size: 18px;
  color: var(--red);
  grid-row: span 2;
  text-align: center;
}
.role-select-name {
  font-size: 14px;
  font-weight: 600;
  color: var(--ink);
}
.role-select-tabs {
  font-size: 10.5px;
  color: var(--ink-fade);
  font-family: var(--mono);
  letter-spacing: 0.03em;
}
.role-select-desc {
  grid-column: 2 / -1;
  font-size: 12.5px;
  color: var(--ink-soft);
  line-height: 1.45;
}

/* Dev-account badge — small pill in the status bar that flags god-
   mode (DEV_EMAILS allowlist). Subtle so it doesn't compete with the
   page, but distinct enough that a dev knows their role gates are off. */
.rm-dev-badge {
  margin-left: 8px;
  padding: 1px 6px;
  border-radius: 4px;
  background: var(--accent, #2b4a6f);
  color: var(--paper, #fff);
  font-size: 9px;
  font-weight: 600;
  letter-spacing: 0.06em;
  vertical-align: 1px;
  font-family: var(--sans);
}

/* Clerk-hosted sign-in overlay. Full-screen scrim + a centered card
   that Clerk mounts its prebuilt sign-in component into. We render
   our own overlay rather than calling clerk.openSignIn() because v6
   of the JS SDK lazy-loads modal components; mounting into a div via
   mountSignIn() loads them on demand and avoids the
   "Clerk was not loaded with Ui components" error. */
.clerk-overlay {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
}
.clerk-overlay[hidden] { display: none; }
.clerk-overlay-scrim {
  position: absolute;
  inset: 0;
  background: rgba(26, 24, 21, 0.42);
  backdrop-filter: blur(2px);
}
.clerk-overlay-card {
  position: relative;
  width: min(440px, 92vw);
  max-height: 92vh;
  overflow-y: auto;
  background: var(--paper);
  border-radius: 12px;
  box-shadow: 0 18px 48px -16px rgba(26, 24, 21, 0.35);
}
.clerk-overlay-card #clerk-mount {
  /* Clerk's mounted component is responsive; just give it the card
     to fill. */
  display: block;
  min-height: 200px;
}

/* Profile chip — "Sign in" state. When logged out the chip becomes a
   compact pill with text instead of initials. */
.profile-chip.is-signin {
  width: auto;
  min-width: 72px;
  padding: 0 14px;
  border-radius: 16px;
  background: var(--red);
  color: var(--paper);
  border-color: var(--red);
  font-size: 12.5px;
  font-weight: 500;
  letter-spacing: 0.005em;
}
.profile-chip.is-signin:hover {
  background: var(--red-deep);
  border-color: var(--red-deep);
}
.profile-chip.is-signin #profile-initials {
  font-size: 12.5px;
  color: inherit;
  letter-spacing: 0.01em;
}

/* =========================================================================
   Inline author orbs — appear on ins + editorial marks when toggled on.
   Hidden by default so the reading surface stays uncluttered. The author's
   color is passed in via the inline `--author-color` custom property.
   ========================================================================= */
.rm-author-orb {
  display: none;                  /* hidden by default */
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--author-color, #6b6b6b);
  margin-right: 4px;
  vertical-align: 0.1em;
  flex-shrink: 0;
  pointer-events: none;            /* don't intercept clicks on the mark */
}
/* Visible only when the user toggles "Authors" on in the review panel. */
body[data-author-orbs="on"] .rm-author-orb {
  display: inline-block;
}

/* The "Authors" toggle pill in the review panel header. */
.review-orbs-toggle {
  appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 5px;
  padding: 3px 9px;
  border: 1px solid var(--hair-strong);
  border-radius: 999px;
  background: var(--paper);
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 11.5px;
  font-weight: 500;
  letter-spacing: 0.01em;
  cursor: pointer;
  margin-left: auto;               /* push to the right of the h2 */
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.review-orbs-toggle:hover {
  border-color: var(--red);
  color: var(--red);
}
.review-orbs-toggle[aria-pressed="true"] {
  background: var(--red);
  border-color: var(--red);
  color: white;
}
.review-orbs-toggle-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: linear-gradient(135deg, #b83a2c 0%, #2b6cb0 50%, #2f855a 100%);
  flex-shrink: 0;
}
.review-orbs-toggle[aria-pressed="true"] .review-orbs-toggle-dot {
  background: white;
}

/* Compress the review panel chrome so its footer aligns with the bottom
   of the mark palette rather than overshooting. */
.review-panel {
  /* Existing rules in the file already control width/position; this just
     tightens internal spacing. */
}
.review-panel header {
  padding: 10px 14px 8px;
}
.review-panel .review-author-chip {
  padding: 5px 14px 3px;
}
.review-panel .review-counter {
  padding: 2px 14px 6px;
  font-size: 11.5px;
}
.review-panel .review-body {
  padding: 4px 14px 6px;
}
.review-panel .review-author-orbs {
  padding: 4px 14px 6px;
  gap: 5px;
}
.review-panel footer {
  padding: 6px 14px 10px;
  gap: 5px;
}

/* =========================================================================
   Student left panel — replaces the editor's file browser + doc nav when
   role=student. Three stacked sections: outline, other assignments, bookmarks.
   ========================================================================= */
.student-left-panel {
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  font-family: var(--sans);
}
.student-left-panel[hidden] { display: none; }

/* When role=student the editor's open-menu / file-tree / doc-nav (which
   the file-browser uses) are noise — students don't open arbitrary local
   files; they work inside assignment docs. Hide them so the new panel
   takes that real estate. The existing assignments-sidebar is also
   hidden — its content is now embedded inside this panel. */
body.role-student .file-browser,
body.role-student #doc-nav,
body.role-student #assignments-sidebar,
body.role-student .search {
  display: none !important;
}
/* And inverse — non-student roles get the editor browser, not the student panel. */
body:not(.role-student) #student-left-panel {
  display: none !important;
}

.sl-section {
  padding: 10px 12px;
  border-top: 1px solid var(--hair);
}
.sl-section:first-child { border-top: 0; }

.sl-section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 11.5px;
  color: var(--ink-fade);
  margin-bottom: 6px;
}
.sl-section-head > span { flex: 1; min-width: 0; }

/* Sort dropdown — compact, matches the muted header tone. */
.sl-sort-select {
  appearance: none;
  -webkit-appearance: none;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 6px;
  color: var(--ink-soft);
  font-family: var(--sans);
  font-size: 11px;
  padding: 2px 18px 2px 6px;
  cursor: pointer;
  /* Tiny chevron via background-image so we don't depend on a separate
     glyph. SVG inlined; recolor follows currentColor poorly so we hard
     code a soft ink color. */
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 5'><path d='M0 0l4 5 4-5z' fill='%23999'/></svg>");
  background-repeat: no-repeat;
  background-position: right 6px center;
  background-size: 7px 5px;
}
.sl-sort-select:hover { border-color: var(--ink-fade); }
.sl-sort-select:focus {
  outline: 2px solid var(--red);
  outline-offset: 1px;
}

/* --- Outline list ---------------------------------------------------- */
.sl-outline-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sl-outline-item {
  appearance: none;
  background: transparent;
  border: 0;
  border-left: 2px solid transparent;
  text-align: left;
  font-family: var(--sans);
  font-size: 12.5px;
  color: var(--ink-soft);
  padding: 4px 8px 4px 10px;
  border-radius: 4px;
  cursor: pointer;
  width: 100%;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}
.sl-outline-item:hover {
  background: var(--paper-edge);
  color: var(--ink);
}
.sl-outline-item.is-active {
  border-left-color: var(--red);
  color: var(--red);
  background: var(--red-wash);
}
.sl-outline-item[data-level="2"] { padding-left: 22px; font-size: 12px; }
.sl-outline-item[data-level="3"] { padding-left: 34px; font-size: 11.5px; color: var(--ink-fade); }
.sl-outline-empty {
  font-size: 11.5px;
  color: var(--ink-fade);
  font-style: italic;
  padding: 4px 4px;
}

/* --- Other assignments list ----------------------------------------- */
.sl-other-list {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.sl-other-item {
  display: grid;
  grid-template-columns: 3px 1fr;
  gap: 8px;
  align-items: stretch;
  padding: 0;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
  overflow: hidden;
  text-align: left;
  font-family: inherit;
}
.sl-other-item:hover { border-color: var(--ink-fade); background: var(--paper-edge); }
.sl-other-item.is-active {
  border-color: var(--red);
  background: var(--red-wash);
}
.sl-other-item-stripe {
  background: var(--ink-fade);
  width: 3px;
}
.sl-other-item-body {
  padding: 5px 8px 6px 0;
  display: flex;
  flex-direction: column;
  gap: 1px;
  min-width: 0;
}
.sl-other-item-title {
  font-size: 12.5px;
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-other-item-meta {
  font-size: 11px;
  color: var(--ink-fade);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.sl-other-item-due {
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
}
.sl-other-item-due.is-overdue { color: var(--red); }
.sl-other-empty,
.sl-bookmarks-empty {
  font-size: 11.5px;
  color: var(--ink-fade);
  font-style: italic;
  padding: 2px 0;
}

/* --- Bookmarks (mirrors per-doc bookmark sidebar) ------------------- */
.sl-bookmarks-list {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.sl-bookmark-item {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 6px;
  border-radius: 4px;
  cursor: pointer;
  background: transparent;
  border: 0;
  text-align: left;
  font-family: inherit;
  width: 100%;
  color: var(--ink-soft);
  font-size: 12px;
  transition: background var(--t-fast);
}
.sl-bookmark-item:hover { background: var(--paper-edge); color: var(--ink); }
.sl-bookmark-item .sl-bookmark-glyph {
  color: var(--red);
  width: 10px;
  height: 13px;
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
}
.sl-bookmark-item .sl-bookmark-glyph svg {
  width: 10px;
  height: 13px;
  display: block;
}
.sl-bookmark-item .sl-bookmark-name {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  flex: 1;
}

/* =========================================================================
   Teacher left panel — admin surface. Hidden by default; shown when
   body.role-teacher. Mirrors the student-left-panel layout pattern.
   ========================================================================= */
.teacher-left-panel {
  display: flex;
  flex-direction: column;
  gap: 0;
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  font-family: var(--sans);
}
.teacher-left-panel[hidden] { display: none; }

/* Mirror the role-student rule: hide the editor's browser when a teacher
   is in the building, show the teacher-left-panel. */
body.role-teacher .file-browser,
body.role-teacher #doc-nav,
body.role-teacher #assignments-sidebar,
body.role-teacher .search {
  display: none !important;
}
body:not(.role-teacher) #teacher-left-panel {
  display: none !important;
}

.tl-section {
  padding: 12px 14px;
  border-top: 1px solid var(--hair);
}
.tl-section:first-child { border-top: 0; }
.tl-section-coming-soon { opacity: 0.7; }

.tl-section-head {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12px;
  letter-spacing: 0.02em;
  color: var(--ink-fade);
  margin-bottom: 8px;
  font-weight: 600;
  text-transform: uppercase;
}
.tl-section-head > span { flex: 1; min-width: 0; }
.tl-section-add {
  appearance: none;
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: 50%;
  width: 22px;
  height: 22px;
  font-size: 13px;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
}
.tl-section-add:hover {
  border-color: var(--red);
  color: var(--red);
  background: var(--red-wash);
}
.tl-section-body {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.tl-coming-soon {
  margin: 0;
  font-size: 11.5px;
  color: var(--ink-fade);
  font-style: italic;
  line-height: 1.4;
}

/* Generic row used by the integrations + rubrics lists. */
.tl-row {
  display: flex;
  flex-direction: column;
  gap: 2px;
  padding: 8px 10px;
  border: 1px solid var(--hair);
  border-radius: 6px;
  background: var(--paper);
  font-size: 12.5px;
}
.tl-row-title {
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.tl-row-meta {
  font-size: 11px;
  color: var(--ink-fade);
}
.tl-row-actions {
  display: flex;
  gap: 4px;
  margin-top: 6px;
  flex-wrap: wrap;
}
.tl-row-action {
  appearance: none;
  background: transparent;
  border: 1px solid var(--hair);
  border-radius: 4px;
  padding: 2px 8px;
  font-size: 11px;
  font-family: var(--sans);
  color: var(--ink-soft);
  cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast);
}
.tl-row-action:hover { border-color: var(--red); color: var(--red); }
.tl-row-action.is-danger:hover { border-color: #b34a3a; color: #b34a3a; }
.tl-empty {
  font-size: 11.5px;
  color: var(--ink-fade);
  font-style: italic;
  padding: 4px 2px;
}
/* Activity rows — clickable to jump to the assignment. */
.tl-activity-row {
  transition: background var(--t-fast);
}
.tl-activity-row:hover {
  background: var(--paper-edge);
  border-color: var(--ink-fade);
}

/* =========================================================================
   Panel tabs — sits directly under each right-side panel's header.
   Same markup shape across memo-panel and style-guide-panel; the active
   tab matches the currently-open panel so the user always sees where
   they are. Hidden for student role (their FAB skips this whole flow).
   ========================================================================= */
.panel-tabs {
  display: flex;
  gap: 0;
  border-bottom: 1px solid var(--hair);
  padding: 0 14px;
  background: var(--paper);
  font-family: var(--sans);
}
.panel-tabs[hidden] { display: none; }
.panel-tab {
  appearance: none;
  background: transparent;
  border: 0;
  border-bottom: 2px solid transparent;
  padding: 9px 10px 8px;
  font-family: inherit;
  font-size: 12.5px;
  color: var(--ink-fade);
  cursor: pointer;
  transition: color var(--t-fast), border-color var(--t-fast);
  margin-bottom: -1px;       /* sit on top of the bottom border */
}
.panel-tab:hover { color: var(--ink); }
.panel-tab.is-active {
  color: var(--red);
  border-bottom-color: var(--red);
  font-weight: 500;
}
.panel-tab[disabled] {
  opacity: 0.4;
  cursor: default;
}
.panel-tab-count {
  display: inline-block;
  font-family: var(--mono);
  font-size: 10.5px;
  color: var(--ink-fade);
  margin-left: 6px;
}

/* =========================================================================
   All Submissions block — teacher-only section inside the memo panel.
   Shown when the teacher selects the "All submissions" tab. Lists each
   student's submission for the current assignment with status + click-
   to-swap to that submission's doc.
   ========================================================================= */
.memo-submissions-block {
  padding: 12px 18px 18px;
  font-family: var(--sans);
}
.memo-submissions-block[hidden] { display: none; }
.memo-submissions-head {
  display: flex;
  align-items: baseline;
  gap: 8px;
  font-size: 13px;
  color: var(--ink);
  font-weight: 500;
  margin-bottom: 8px;
}
.memo-submissions-meta {
  font-size: 11px;
  color: var(--ink-fade);
  font-weight: 400;
}
.memo-submissions-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.memo-submission-row {
  display: grid;
  grid-template-columns: 4px 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 0;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-radius: 6px;
  cursor: pointer;
  text-align: left;
  font-family: inherit;
  overflow: hidden;
  transition: border-color var(--t-fast), background var(--t-fast);
}
.memo-submission-row:hover { border-color: var(--ink-fade); background: var(--paper-edge); }
.memo-submission-row.is-current {
  border-color: var(--red);
  background: var(--red-wash);
}
.memo-submission-stripe {
  width: 4px;
  height: 100%;
  align-self: stretch;
  background: var(--ink-fade);
}
.memo-submission-body {
  padding: 7px 0 7px 4px;
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.memo-submission-name {
  font-size: 13px;
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.memo-submission-email {
  font-size: 11px;
  color: var(--ink-fade);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.memo-submission-status {
  font-family: var(--mono);
  font-size: 10px;
  letter-spacing: 0.04em;
  padding: 2px 8px;
  border-radius: 999px;
  margin-right: 10px;
  white-space: nowrap;
}
.memo-submission-status.status-not-started { background: var(--paper-edge); color: var(--ink-fade); }
.memo-submission-status.status-in-progress { background: rgba(201, 138, 26, 0.12); color: #c98a1a; }
.memo-submission-status.status-submitted   { background: rgba(74, 138, 74, 0.12); color: #4a8a4a; }
.memo-submission-status.status-graded      { background: rgba(60, 100, 180, 0.12); color: #3c64b4; }
.memo-submissions-empty {
  padding: 14px;
  border: 1px dashed var(--hair);
  border-radius: 8px;
  color: var(--ink-fade);
  font-size: 12px;
  text-align: center;
}

/* Author read-only view of the editor's memo. Plain prose, no input
   chrome — the writer is consuming the editor's letter, not writing one. */
.memo-readonly-view {
  font-family: var(--serif);
  font-size: 14px;
  line-height: 1.6;
  color: var(--ink);
  white-space: pre-wrap;
  padding: 8px 0;
}
.memo-readonly-view-title {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 10px;
}
.memo-readonly-view-empty {
  font-style: italic;
  color: var(--ink-fade);
}

/* =========================================================================
   LTI DeepLink picker modal — teacher picks a Red Stet assignment to
   attach to a Canvas item. One-off modal built on demand by app.js.
   ========================================================================= */
.lti-deeplink-card {
  max-width: 520px;
}
.lti-deeplink-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin: 12px 0 16px;
  max-height: 360px;
  overflow-y: auto;
  border: 1px solid var(--hair);
  border-radius: 8px;
  padding: 6px;
}
.lti-deeplink-row {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 8px 10px;
  border-radius: 6px;
  cursor: pointer;
  transition: background var(--t-fast);
}
.lti-deeplink-row:hover { background: var(--paper-edge); }
.lti-deeplink-row input[type="radio"] {
  margin-top: 3px;
  flex-shrink: 0;
}
.lti-deeplink-row-body {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}
.lti-deeplink-row-title {
  font-size: 13.5px;
  font-weight: 500;
  color: var(--ink);
  overflow: hidden;
  text-overflow: ellipsis;
}
.lti-deeplink-row-meta {
  font-size: 11.5px;
  color: var(--ink-fade);
}
.lti-deeplink-empty {
  padding: 16px;
  border: 1px dashed var(--hair);
  border-radius: 8px;
  text-align: center;
  color: var(--ink-fade);
  margin: 12px 0;
}

/* ═══ LTI iframe / DeepLink sign-in surface ════════════════════════
   When body.lti-iframe-mode is on (set by the early-paint script in
   index.html when /#/lti?mode=deeplink lands), the marketing chrome
   is hidden and the minimal sign-in surface takes over the viewport.
   Lets a teacher launching from Canvas/Moodle's Select Content iframe
   see a focused setup wizard instead of the homepage. */
body.lti-iframe-mode > *:not(#lti-signin-surface):not(#lti-deeplink-modal):not(script):not(noscript):not(style) {
  display: none !important;
}
/* Hard-lock light theme in the iframe context — even if the user's
   OS preference flips us to dark elsewhere, the LMS host renders
   a neutral light surface and our setup wizard should match. We
   override the CSS custom properties (not just body bg) so every
   nested element — including the Clerk widget mount and any modal
   inheriting from our tokens — resolves to light values regardless
   of whatever data-theme attribute the theme listener slaps on. */
body.lti-iframe-mode {
  --paper:        #FAF8F2 !important;
  --paper-edge:   #ece8df !important;
  --ink:          #1A1815 !important;
  --ink-2:        #3e3a32 !important;
  --ink-soft:     #4a463f !important;
  --ink-fade:     #8a857a !important;
  --muted:        #6a655c !important;
  --rule:         #d8d2c3 !important;
  background: #FAF8F2 !important;
  color: #1A1815 !important;
  overflow: auto;
}

/* Surface fills the LMS iframe and CENTERS its content both axes.
   The content column is fluid — narrow viewports get tighter type
   and a smaller CTA; wider viewports breathe out. clamp() keeps
   things readable from ~360px iframes up to full-window launches.
   overflow-y:auto guarantees scroll if content ever exceeds height. */
.lti-signin-surface {
  position: fixed;
  inset: 0;
  background: var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 40px);
  overflow-y: auto;
  z-index: 10000;
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}
.lti-signin-card {
  /* Fluid width: roughly half the viewport at desktop sizes, capped
     at 640px so the column doesn't sprawl on giant displays, and
     pulled wide at narrow sizes (min 90% of viewport, never less than
     280px to keep readable). Since we open Clerk's native modal on
     CTA click — not embed it inline — we're not constrained by
     Clerk's responsive breakpoints here. */
  width: clamp(280px, 50%, 640px);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}
.lti-signin-brand {
  font-family: var(--display);
  font-weight: 400;
  font-size: clamp(11px, 1.4vw, 13px);
  letter-spacing: 0.02em;
  color: var(--red);
  margin: 0 0 clamp(12px, 2.5vw, 20px) 0;
  padding: 3px 12px;
  border: 1px solid var(--red);
  border-radius: 999px;
  background: rgba(184, 56, 41, 0.04);
  text-transform: uppercase;
}
.lti-signin-title {
  font-family: var(--display);
  font-weight: 400;
  /* Scale from 17px on narrow → 26px on wide. Wraps cleanly at
     all sizes because line-height stays generous. */
  font-size: clamp(17px, 3.4vw, 26px);
  line-height: 1.25;
  color: var(--ink);
  margin: 0 0 clamp(6px, 1.5vw, 10px) 0;
  letter-spacing: -0.005em;
  /* Keep the headline column tighter than the CTA column for a
     more "wizard" feel even on wide viewports. */
  max-width: 22ch;
}
.lti-signin-caption {
  font-size: clamp(11.5px, 1.6vw, 14px);
  color: var(--muted);
  margin: 0 0 clamp(14px, 2.5vw, 22px) 0;
  line-height: 1.45;
  max-width: 36ch;
}
.lti-signin-clerk-mount {
  margin: 0 auto;
  width: 100%;
  display: flex;
  justify-content: center;
}
/* Big "Sign in to Red Stet" CTA. Clicking it opens Clerk's native
   modal (the same one used everywhere else in the app), which lands
   in the perfect "Continue with Google / Continue with Microsoft"
   stacked layout that mountSignIn's compact embed mode never quite
   matches. After the modal completes auth, the LTI listener tears
   down the surface and resumes the DeepLink picker. */
.lti-signin-cta {
  font-family: var(--sans);
  /* CTA breathes with the viewport — bigger touch target on wider
     iframes (where it's harder to spot), tighter on narrow ones. */
  font-size: clamp(13px, 1.7vw, 16px);
  font-weight: 500;
  letter-spacing: 0.01em;
  color: #FAF8F2;
  background: var(--red);
  border: 0;
  border-radius: 999px;
  padding: clamp(10px, 1.6vw, 14px) clamp(22px, 3.5vw, 36px);
  cursor: pointer;
  transition: background var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 2px 8px rgba(184, 56, 41, 0.18);
}
.lti-signin-cta:hover {
  background: #8c2a1f;
  transform: translateY(-1px);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 4px 12px rgba(184, 56, 41, 0.24);
}
.lti-signin-cta:active {
  transform: translateY(0);
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.04), 0 2px 6px rgba(184, 56, 41, 0.16);
}
.lti-signin-footer {
  font-size: clamp(10px, 1.3vw, 12.5px);
  color: var(--ink-fade);
  margin: clamp(14px, 2.5vw, 22px) 0 0 0;
  line-height: 1.5;
  max-width: 38ch;
  font-style: italic;
}
