/* Phase 7 Stage-2a — Mirror Editor styling inside the product.
 *
 * Every rule is scoped under `.mirror-mode` (the class app.js adds to #editor
 * when the mirror flag is on), so this stylesheet is completely inert in the
 * normal Clean-view path — flag-off is unaffected. Typography is ported from the
 * spike's `.paper` rules so the ProseMirror editor reads like a manuscript, not a
 * code box; the widget styles are the spike's chip palette. */

/* ---- Editor surface + typography (≈ Clean view) ---- */
.mirror-mode { display: flex; flex-direction: column; height: 100%; overflow: hidden; background: #f3f4f6; }
.mirror-mode .mirror-wysiwyg { flex: 1; overflow: auto; }
.mirror-mode .mirror-wysiwyg.hidden, .mirror-mode .mirror-source.hidden { display: none; }
.mirror-mode .mirror-source { flex: 1; display: flex; flex-direction: column; min-height: 0; background: #fff; }
.mirror-mode .mirror-source-host { flex: 1; min-height: 0; overflow: hidden; }
.mirror-mode .mirror-source-host .cm-editor { height: 100%; font-size: 13px; }
.mirror-mode .mirror-source-host .cm-content { font-family: 'Menlo', 'Courier New', monospace; }
/* Word-style status bar along the bottom of the editor pane (Source + Editor).
   Left: the Source-only Apply cluster. Right: page/word counts + Split toggle. */
.mirror-mode .mirror-statusbar { display: flex; align-items: center; gap: 10px; padding: 6px 12px; border-top: 1px solid #e3e6ea; background: #f8fafc; flex: 0 0 auto; }
/* `overflow: hidden` is load-bearing: without it a child that has stopped shrinking (Apply has a
   floor, the notes button has its padding) simply draws OUTSIDE this box and over whatever sits
   to the right. That is what printed Apply on top of the Split toggle. */
.mirror-mode .mirror-statusbar-apply { display: flex; align-items: center; gap: 10px; min-width: 0; flex: 0 1 auto; overflow: hidden; }
.mirror-mode .mirror-statusbar-apply.hidden { display: none; }
/* The Source bar's yield ladder.
   In a narrow split-view pane the bar's contents do not fit, and what happens then used to be an
   accident: `.mirror-statusbar-apply` could shrink but the Apply button inside it could not, so
   the button overflowed its own group's box and DREW OVER the counts and the Split toggle. Two
   controls printed on top of each other, at any pane under roughly 1024px.
   Nothing here is allowed to overflow its box, so overlap is impossible by construction; instead
   each element states, through its shrink factor, how readily it gives up width. In order:
     1. the hint      (prose, and pure decoration)             flex-shrink 10000
     2. the counts    (an informational readout)               flex-shrink 1000
     3. LaTeX notes   (a reference, reachable when wider)      flex-shrink 500
     4. Apply's label (the primary action — last to give)      flex-shrink 1
   The Split toggle never shrinks: it is the only control on the right, and losing it is how a
   writer loses their way back from split view.
   The factors are orders of magnitude apart on purpose. Flexbox distributes a shortfall across
   every shrinkable item in proportion to (factor x base size), so with neighbouring factors each
   item takes a small share of every squeeze — which is how the notes button ended up one pixel
   short of its own text at EVERY width, reading "LaTeX not…" even on a wide screen. A 10x gap
   makes the lower rungs round to zero while a higher one still has width to give. */
.mirror-mode .mirror-statusbar-apply .mirror-apply-btn { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mirror-mode .mirror-statusbar-apply .mirror-source-hint { flex: 0 10000 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* Collapses to nothing so the counts can yield width, and clips rather than letting anything
   draw outside it. The Split toggle used to live in here and was clipped along with it, which
   is why it is now a bar-level child (see mirror-editor-pane.js). */
.mirror-mode .mirror-statusbar-info { margin-left: auto; flex: 0 1 auto; min-width: 0; display: flex; align-items: center; gap: 14px; overflow: hidden; }
.mirror-mode .mirror-statusbar-count { font-size: 11px; color: #6b7280; white-space: nowrap; font-variant-numeric: tabular-nums; flex: 0 1000 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* Page navigator: "Page [ n ] of N" — indicator + go-to-page box (page-box Editor only). */
.mirror-mode .mirror-statusbar-pagenav { display: inline-flex; align-items: center; gap: 5px; font-size: 11px; color: #6b7280; white-space: nowrap; }
.mirror-mode .mirror-statusbar-pagenav.hidden { display: none; }
.mirror-mode .mirror-pagenav-input { width: 42px; font: inherit; font-size: 11px; text-align: center; color: #374151; background: #fff; border: 1px solid #d3d8de; border-radius: 5px; padding: 2px 4px; font-variant-numeric: tabular-nums; -moz-appearance: textfield; }
.mirror-mode .mirror-pagenav-input:focus { outline: none; border-color: #2e5c7a; box-shadow: 0 0 0 2px rgba(46,92,122,0.15); }
.mirror-mode .mirror-pagenav-input::-webkit-inner-spin-button, .mirror-mode .mirror-pagenav-input::-webkit-outer-spin-button { -webkit-appearance: none; margin: 0; }
.mirror-mode .mirror-pagenav-total { color: #6b7280; }
.mirror-mode .mirror-statusbar-split { font: inherit; font-size: 11px; color: #374151; background: #fff; border: 1px solid #d3d8de; border-radius: 5px; padding: 3px 10px; cursor: pointer; white-space: nowrap; flex: 0 0 auto; }
/* Re-assert colour on hover so the generic button:hover accent (rust) can't leak in. */
.mirror-mode .mirror-statusbar-split:hover { background: #eef1f4; color: #374151; }
.mirror-mode .mirror-statusbar-split.is-active { background: #2e5c7a; color: #fff; border-color: #2e5c7a; }
.mirror-mode .mirror-statusbar-split.is-active:hover { background: #24506b; color: #fff; }
.mirror-mode .mirror-statusbar-split.hidden { display: none; }
.mirror-apply-btn { font: inherit; font-size: 12px; padding: 4px 12px; border-radius: 5px; cursor: pointer; background: #2e5c7a; color: #fff; border: 1px solid #2e5c7a; }
/* Re-assert colour + border on hover so the generic `button:hover` (which sets
   `color: var(--accent)`, a rust/red) cannot leak in; the hover cue is a bolder
   label plus the slightly darker blue, never a colour change. */
.mirror-apply-btn:hover { background: #24506b; border-color: #24506b; color: #fff; font-weight: 700; }
.mirror-apply-btn.hidden { display: none; }
.mirror-advanced-btn { font: inherit; font-size: 12px; padding: 4px 12px; border-radius: 5px; cursor: pointer; background: #fff; color: #5b6470; border: 1px solid #cfd4da; }
/* "About this LaTeX", beside Apply in the Source tab. Quieter than Apply (which is the action)
   but still a button rather than a link, because it opens a panel.
   It SHRINKS, on the same contract as the hint two rules below: Apply and the Split toggle are
   fixed, and in a narrow split-view pane the bar has exactly zero slack, so a non-shrinking button
   here pushes the Source/PDF view toggle off the edge instead of giving way (measured at a 259px
   pane: the bar went from 259px of content in 259px to 395px). */
.mirror-notes-btn { font: inherit; font-size: 11px; padding: 3px 6px; border-radius: 5px; cursor: pointer;
  background: #fff; color: #2e5c7a; border: 1px solid #cfd8e0;
  /* Rung 3 of the Source bar's yield ladder (see .mirror-statusbar-apply above): it gives way
     after the hint and the counts, and before Apply's own label. */
  flex: 0 500 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mirror-notes-btn:hover { background: #f2f7fb; border-color: #a9c2d6; color: #2e5c7a; }
/* The panel itself: read-only prose in openTextEditor's shell, so only the body needs rules.
   A two-column row keeps each command beside the reason it exists; it collapses to stacked rows
   on a narrow pane, where a fixed code column would squeeze the prose to a few words per line. */
.mirror-notesmodal { max-width: 760px; width: min(760px, 92vw); }
.mirror-notes-body { overflow-y: auto; max-height: min(62vh, 620px); padding: 2px 2px 4px; }
.mirror-notes-h { margin: 16px 0 4px; font-size: 12.5px; font-weight: 700; color: #2b3440;
  text-transform: uppercase; letter-spacing: .04em; }
.mirror-notes-h:first-child { margin-top: 4px; }
.mirror-notes-lead { margin: 0 0 8px; font-size: 12.5px; line-height: 1.5; color: #5b6470; }
.mirror-notes-row { display: grid; grid-template-columns: minmax(180px, 34%) 1fr; gap: 10px;
  padding: 5px 0; border-top: 1px solid #eef1f4; align-items: baseline; }
.mirror-notes-row-prose { grid-template-columns: 1fr; }
.mirror-notes-code { font-family: 'Menlo', 'Courier New', monospace; font-size: 11.5px; color: #8a5a00;
  background: #fdf6e7; border: 1px solid #f0e2c4; border-radius: 4px; padding: 1px 5px;
  overflow-wrap: anywhere; }
.mirror-notes-why { font-size: 12.5px; line-height: 1.5; color: #374151; }
@media (max-width: 620px) {
  .mirror-notes-row { grid-template-columns: 1fr; gap: 4px; }
}
.mirror-advanced-btn:hover { background: #f1f3f5; }
.mirror-advanced-btn.is-active { background: #fdecea; color: #a6342b; border-color: #f0b8b2; }
.mirror-source-hint { font-size: 11px; color: #8a9099; }
.mirror-source-badge { font-size: 11px; color: #8a5a00; background: #fff4d6; border: 1px solid #f0d59a; border-radius: 4px; padding: 2px 8px; }
.mirror-source-badge.hidden { display: none; }
/* Pre-compile check result: the first structural problem in the Source buffer.
   Styled as a warning rather than an error because nothing has failed yet — this
   is the compile that is ABOUT to fail, and it is still fixable in one click. */
.mirror-source-issue {
  flex: 0 0 auto; font-family: inherit; font-size: 11px; cursor: pointer;
  color: #8a1c2c; background: #fdecef; border: 1px solid #e7b3bd;
  border-radius: 4px; padding: 2px 8px; white-space: nowrap;
}
.mirror-source-issue:hover { background: #f8d9df; }
.mirror-source-issue.hidden { display: none; }
.mirror-mode .ProseMirror {
  max-width: 7.0in; margin: 18px auto; min-height: 9in;
  background: #fff; box-shadow: 0 1px 4px rgba(0,0,0,.16);
  padding: 0.9in 1.0in; outline: none;
  font-family: var(--mirror-fontfamily, 'Times New Roman', Georgia, serif);
  font-size: 12pt; line-height: var(--mirror-linespacing, 1.2); color: #111;
  /* Document-wide default paragraph alignment, read from the source in
     applyDocStyleVars (justify like the LaTeX PDF, or left for \RaggedRight
     docs). Paragraphs inherit it; alignment containers (center/flushleft/
     flushright) set their own text-align and override for their subtree. */
  text-align: var(--mirror-textalign, justify);
  /* ProseMirror requires an explicit white-space (it warns otherwise). With the default
     `normal`, a space typed next to an existing space collapses to zero rendered width, so the
     caret does not advance and the space is invisible — the editor feels frozen when you press
     Space at a sentence start after ". " (bug #5, 2026-07-22). `break-spaces` gives every space
     width (Word-like) and keeps the off-screen brain and the projected clones wrapping
     identically, which the paginator depends on. */
  white-space: break-spaces;
}
/* Page-box mode: the visible pages are re-fragmented clones under boxHost
   (.mirror-pagebox), OUTSIDE .ProseMirror, so carry the alignment there too. */
.mirror-mode .mirror-pagebox { text-align: var(--mirror-textalign, justify); }
/* The document default goes in the var() FALLBACK, never as a declaration on
   .ProseMirror. A declaration there is applied to the visible page clones too —
   they carry the same class — so it would re-declare the property on the very
   element that consumes it and shadow the document's own value, which
   applyDocStyleVars sets on the ancestor .mirror-pagebox. That is what made a
   `\setlength{\parindent}{0in}` document render every paragraph indented half an
   inch on screen while the off-screen brain and the Editor PDF had it right
   (docs/lessons.md 2026-08-13). The other three doc-style vars were always
   fallback-only, which is why only the indent broke. */
/* `--p-indent-inherited` is the indent a paragraph shows when it carries NO explicit
   first-line indent of its own, published so Tab / Shift-Tab can ask what "inherit"
   means for THIS paragraph (indent-ladder.js). An explicit indent arrives as an inline
   `text-indent`, which overrides the property below for rendering but never overwrites
   this variable — so the command can read the inherited value even for a paragraph that
   is not currently inheriting, instead of restating the exceptions here in JS.
   Note this declares a NEW variable on `p`; it does not re-declare --mirror-parindent,
   which must keep resolving from the ancestor .mirror-pagebox (see the note above). */
.mirror-mode .ProseMirror p { margin: 0; --p-indent-inherited: var(--mirror-parindent, 0.5in); text-indent: var(--p-indent-inherited); }
/* The exceptions set the variable and let the rule above render it, so the two can
   never disagree about what a paragraph inherits. */
.mirror-mode .ProseMirror h1 + p, .mirror-mode .ProseMirror h2 + p,
.mirror-mode .ProseMirror h3 + p, .mirror-mode .ProseMirror h4 + p,
.mirror-mode .ProseMirror h5 + p, .mirror-mode .ProseMirror h6 + p { --p-indent-inherited: 0in; }
/* Per-paragraph indent suppression (Word: Backspace removes a paragraph's indent). */
.mirror-mode .ProseMirror p.mirror-noindent { text-indent: 0; }
/* Print-faithful line breaking: hyphenate justified prose the way TeX does, so wrap points, and
   therefore the line count per page, track the LaTeX PDF instead of running consistently long. The
   retired Clean view carried this rule (public/style.css, `.cm-line`) and the Mirror Editor never
   inherited it; measured on the R2 manuscript it is 18 lines and one page in 51. Chrome's patterns
   are not TeX's, so this narrows the gap rather than closing it. Scoped to paragraphs, which is
   where the line count comes from, and mirrored verbatim on `#pg-print-root p` so the editor and
   the Editor PDF cannot break differently (ADR 0008, Rule 4). */
.mirror-mode .ProseMirror p { -webkit-hyphens: auto; hyphens: auto; }
.mirror-mode .ProseMirror h1, .mirror-mode .ProseMirror h2, .mirror-mode .ProseMirror h3,
.mirror-mode .ProseMirror h4, .mirror-mode .ProseMirror h5, .mirror-mode .ProseMirror h6 {
  font-family: var(--mirror-fontfamily, 'Times New Roman', Georgia, serif);
  font-weight: 700; line-height: 1.3; margin: .8em 0 .4em;
}
.mirror-mode .ProseMirror h1 { font-size: 17pt; }
.mirror-mode .ProseMirror h2 { font-size: 15pt; }
.mirror-mode .ProseMirror h3 { font-size: 13pt; }
.mirror-mode .ProseMirror h4 { font-size: 12pt; font-style: italic; }
.mirror-mode .ProseMirror h5, .mirror-mode .ProseMirror h6 { font-size: 12pt; }
.mirror-mode .ProseMirror ul, .mirror-mode .ProseMirror ol { margin: .4em 0; padding-left: 1.6em; }
.mirror-mode .ProseMirror li { margin: .15em 0; }
.mirror-mode .ProseMirror li p { --p-indent-inherited: 0in; }
.mirror-mode .ProseMirror strong { font-weight: 700; }
.mirror-mode .ProseMirror em { font-style: italic; }
/* \texttt inline code: monospace, tinted like a code span. The body font rule would
   otherwise override the <code> element's UA monospace default. */
.mirror-mode .ProseMirror code.mirror-mono {
  font-family: 'Menlo', 'Courier New', monospace; font-size: .9em;
  background: rgba(0,0,0,0.05); border-radius: 3px; padding: 0 2px;
}
.mirror-mode .ProseMirror[contenteditable="true"] { caret-color: #2e5c7a; }
.mirror-mode .ProseMirror-selectednode { outline: 2px solid #2e5c7a; outline-offset: 1px; }

/* ---- Inline marks / chips ---- */
.mirror-mode .mirror-hl { border-radius: 2px; padding: 0 1px; }
.mirror-mode .mirror-cite {
  /* inline (not inline-block) + normal wrapping so a multi-key citation wraps
     across lines like text instead of one over-wide pill. */
  display: inline; padding: 0; border-radius: 4px;
  background: rgba(46, 92, 122, 0.10); color: rgba(46, 92, 122, 0.95);
  /* The tint reads as a padded pill without OCCUPYING the padding: a spread box-shadow paints
     outside the box, so a citation is exactly as wide in the editor as the plain parenthesised
     text it becomes in both PDFs (`#pg-print-root .mirror-cite` resets to bare text). The former
     `padding: 0 2px` was a screen-only value on the width of a run of body text, which is what
     ADR 0008 Rule 4 forbids; both PDF paths already cancelled it, so the editor was measuring a
     line the printed page did not have. */
  box-shadow: 0 0 0 2px rgba(46, 92, 122, 0.10);
  white-space: normal; cursor: pointer;
}
/* Frame as a parenthetical citation, matching the printed PDF (#pg-print-root
   .mirror-cite uses the same "(" / ")"). */
.mirror-mode .mirror-cite::before { content: '('; }
.mirror-mode .mirror-cite::after { content: ')'; }
/* Numeric styles (IEEE/Vancouver) frame as "[1, 2]". */
.mirror-mode .mirror-cite.numeric::before { content: '['; }
.mirror-mode .mirror-cite.numeric::after { content: ']'; }
/* An unlinked citation: a \cite whose key has no resolvable library reference (no
   BibTeX/CSL). Muted amber with a dashed underline so it reads as "needs linking" rather
   than as content or a working link; clicking it opens the popover's Link search (bug #1). */
.mirror-mode .mirror-cite.mirror-cite-unlinked {
  color: #9a6a00;
  text-decoration: underline dashed 1px;
  text-underline-offset: 2px;
}
/* PrintView is a preview of the printed PDF, so its citations render as plain
   parenthesised body text (identical to #pg-print-root in the @media print block),
   not the editor's blue chip. Placed after the base + unlinked rules so it wins on
   equal specificity; the "(" / ")" (or "[" / "]") delimiters are inherited. */
.printview-doc .mirror-cite { background: none; border: 0; padding: 0; border-radius: 0; box-shadow: none; color: #000; cursor: default; }
.printview-doc .mirror-cite.mirror-cite-unlinked { color: #000; text-decoration: none; }
/* A resolved \ref cross-reference renders as its target's NUMBER (a live cross-ref),
   as a subtle inline chip so it reads as a reference rather than plain typed text. An
   unresolved ref (dangling label, or a target kind not yet numbered) keeps the raw
   command in the amber monospace look, so nothing is hidden. */
.mirror-mode .mirror-ref {
  display: inline; padding: 0 2px; border-radius: 4px;
  background: rgba(46, 92, 122, 0.08); color: rgba(46, 92, 122, 0.95);
  cursor: default; white-space: normal;
}
.mirror-mode .mirror-ref.mirror-ref-unresolved {
  font-family: 'Menlo', 'Courier New', monospace; font-size: .82em;
  background: #fbf3e2; color: #8a5a00; border: 1px solid #ecd9a8; padding: 0 3px;
}
.printview-doc .mirror-ref { background: none; border: 0; padding: 0; border-radius: 0; color: #000; }
.printview-doc .mirror-ref.mirror-ref-unresolved { font-family: inherit; font-size: inherit; border: 0; }
.mirror-mode .mirror-rawinline {
  font-family: 'Menlo', 'Courier New', monospace; font-size: .82em;
  background: #fbf3e2; color: #8a5a00; border: 1px solid #ecd9a8; border-radius: 4px; padding: 0 3px; cursor: pointer;
}
.mirror-mode .mirror-math { cursor: pointer; padding: 0 1px; border-radius: 3px; }
.mirror-mode .mirror-math:hover { background: #eef4fb; outline: 1px solid #bcd; }
.mirror-mode .mirror-math-display { display: block; text-align: center; margin: .6em 0; }

/* ---- Block widgets: figure / table / raw ---- */
.mirror-mode .mirror-figure { margin: 1em 0; text-align: center; }
.mirror-mode .mirror-figure img { max-width: 100%; max-height: 320px; border: 1px solid #e0e3e7; border-radius: 4px; background: #fff; }
.mirror-mode .mirror-figure-placeholder {
  display: inline-block; padding: 24px 32px; color: #8a9099; font-size: 13px;
  border: 1px dashed #c7ccd2; border-radius: 6px; background: #f7f9fb; font-family: 'Menlo', monospace;
}
.mirror-mode .mirror-figcaption { margin-top: 6px; font-size: 10.5pt; color: #444; font-style: italic; cursor: text; }
.mirror-mode .mirror-figcaption:hover { color: #2e5c7a; }
.mirror-mode .mirror-table { margin: .8em 0; border: 1px solid #cdd8e3; border-radius: 6px; background: #f5f9fd; padding: 8px 10px; }
.mirror-mode .mirror-table-head { display: flex; align-items: center; gap: 8px; }
.mirror-mode .mirror-table-name { font-family: 'Menlo', monospace; font-size: 12px; font-weight: 600; color: #2e5c7a; }
.mirror-mode .mirror-table-tag { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: #5b7a96; background: #e3eef7; border-radius: 3px; padding: 1px 5px; }
.mirror-mode .mirror-table-caption { margin-top: 4px; font-size: 11px; color: #5a6b7a; font-style: italic; }
.mirror-mode .mirror-rawblock { margin: .7em 0; border: 1px dashed #d2b87a; border-radius: 6px; background: #fdf8ee; padding: 8px 10px; }
.mirror-mode .mirror-blockquote { margin: .7em 0 .7em 1.5em; padding-left: .9em; border-left: 3px solid #cbd5e1; color: #334155; font-style: italic; }

/* Page break / section break — a labelled divider. The break takes effect in the
   LaTeX PDF; the editor shows where it is (PDF-faithful). A page break is a subtle
   dashed grey rule; a section break (column-layout change) is a solid accent rule. */
.mirror-mode .mirror-docbreak {
  display: flex; align-items: center; gap: 0; margin: 1.1em 0;
  user-select: none; -webkit-user-select: none;
}
.mirror-mode .mirror-docbreak::before,
.mirror-mode .mirror-docbreak::after {
  content: ""; flex: 1 1 auto; border-top: 1px dashed rgba(0, 0, 0, 0.22);
}
.mirror-mode .mirror-docbreak-label {
  display: inline-flex; align-items: center; gap: .5em; flex: 0 0 auto;
  padding: 0 .85em; font-size: .68rem; letter-spacing: .06em; text-transform: uppercase;
  color: #8a9099; white-space: nowrap;
}
.mirror-mode .mirror-docbreak-title { font-weight: 700; }
.mirror-mode .mirror-docbreak[data-kind="section"]::before,
.mirror-mode .mirror-docbreak[data-kind="section"]::after { border-top: 1px solid rgba(46, 92, 122, 0.55); }
.mirror-mode .mirror-docbreak[data-kind="section"] .mirror-docbreak-label { color: #24506b; }
.mirror-mode .mirror-docbreak.ProseMirror-selectednode { outline: 2px solid rgba(46, 92, 122, 0.6); outline-offset: 3px; border-radius: 4px; }
/* In the read-only print/PDF-faithful views, hide the editor's own divider chrome: the page
   itself already breaks (the box paginator opens a fresh .pgx-page → a fresh @page), so the
   printed PDF gets the break without the on-screen marker — as Word prints a break, not its label. */
.printview-doc .mirror-docbreak,
.paginated-print .mirror-docbreak { display: none; }
.mirror-mode .mirror-inline-image { max-width: 100%; height: auto; vertical-align: middle; }
.mirror-mode .mirror-footnote-marker { color: #2563eb; cursor: help; font-weight: 600; }
/* Endnotes: a numbered superscript reference. The number is a CSS counter in
   document order, reset PER CONTENT ROOT so the page-box brain and the visible
   page projection never cross-count (each subtree numbers 1..n on its own). This
   renumbers automatically on insert/delete with no nodeview update(). The
   collected "Notes" section is produced at compile by the endnotes package. */
.mirror-mode .mirror-wysiwyg,
.mirror-mode .mirror-pagebox-brain { counter-reset: cw-endnote; }
.mirror-mode .mirror-endnote-marker {
  counter-increment: cw-endnote;
  color: #2563eb; font-weight: 600; cursor: help; padding: 0 1px;
}
.mirror-mode .mirror-endnote-marker::before { content: counter(cw-endnote); }
.mirror-mode .mirror-url { color: #2563eb; text-decoration: underline; word-break: break-all; }
/* An internal cross-reference (\hyperref[anchor]{label}) reads as a link in the source
   document, so it carries the link colour — but no underline, since it points inside the
   document rather than out to the web. */
.mirror-mode .mirror-xref { color: #2563eb; }

/* \hrulefill — a rule that fills the line, drawn as the rule it means rather than printed as
   its own command. Inline-block so it sits inside its paragraph like the LaTeX fill does. */
.mirror-mode .mirror-hrule {
  display: inline-block; width: 100%; vertical-align: middle;
  border-bottom: 1px solid currentColor; opacity: .45; user-select: none;
}

/* View → Show non-printing characters (mirror-editor/src/formatting-marks.js).
   EVERY marker here draws WITHOUT OCCUPYING WIDTH. The editor paginates in the browser, so a
   glyph that took real space at the end of a line could push that line over and move every
   page break in the document — turning the marks on would silently repaginate the paper.
   The pilcrow is therefore a zero-width inline-block that overflows its box, and a space
   marker is an absolutely-positioned ::before painted OVER the space it belongs to. */
.mirror-mode .mirror-np-pilcrow {
  display: inline-block; width: 0; overflow: visible; white-space: nowrap;
  color: #7aa7e0; opacity: .6; user-select: none; pointer-events: none;
  /* Upright and regular-weight regardless of the paragraph it ends. It SIZE-scales with the
     block (a heading's mark is bigger, as in Word — the mark belongs to that paragraph), but
     inheriting weight and slant too made it render bold in a heading and italic in an
     italic one, which reads as content rather than as an editor mark. */
  font-weight: 400; font-style: normal;
}
.mirror-mode .mirror-np-ws { position: relative; }
/* A whitespace marker is PAINTED AS A BACKGROUND, not drawn as an overlaid pseudo-element.
   The overlay was tried first and is genuinely unreliable here: an absolutely-positioned
   ::before resolves against its INLINE containing block, and an inline box is fragmented by
   line breaking and justification, so `inset: 0` produced a usable box for only some spans.
   Measured on the 52 KB paper: 574 spaces, 574 decoration spans — every marker present — and
   perhaps a third of them actually painted. A background gradient has no such dependency, and
   like the overlay it cannot affect layout, which is the constraint that rules everything
   here (a marker with width would repaginate the document). Sized in `em` so it tracks the
   font and the editor's zoom. */
.mirror-mode .mirror-np-ws { background-repeat: no-repeat; background-position: 50% 50%; }
.mirror-mode .mirror-np-ws.is-sp {
  background-image: radial-gradient(circle, rgba(90, 140, 200, .95) 0 .075em, transparent .08em);
}
/* The look-alikes a spacing bug hides behind get their own colour, not just their own size: a
   non-breaking space pasted from Word is invisible until it breaks justification. */
.mirror-mode .mirror-np-ws.is-nbsp,
.mirror-mode .mirror-np-ws.is-thin,
.mirror-mode .mirror-np-ws.is-fig,
.mirror-mode .mirror-np-ws.is-nnbsp {
  background-image: radial-gradient(circle, transparent 0 .05em, rgba(209, 116, 60, .95) .055em .105em, transparent .11em);
}
.mirror-mode .mirror-np-ws.is-nbsp { background-color: rgba(209, 116, 60, .12); border-radius: 2px; }
/* A tab has a wide box, so it can carry a real glyph — and an arrow reads better than a dot
   for something that means "jump to the next stop". */
.mirror-mode .mirror-np-ws.is-tab::before {
  content: '→'; position: absolute; inset: 0; pointer-events: none;
  display: flex; align-items: center; justify-content: center;
  color: #7aa7e0; opacity: .7; line-height: 1;
}
/* A zero-width character has a ZERO-WIDTH box, so the centred overlay above would have nothing
   to sit in. These pin to the box's edge and overflow it instead — the marker has to be
   findable precisely because the character is invisible everywhere else, which is the whole
   reason it is worth showing. Red, not blue: this is nearly always something pasted in from a
   web page rather than something the writer meant. */
.mirror-mode .mirror-np-ws.is-zwsp::before,
.mirror-mode .mirror-np-ws.is-zwnbsp::before {
  content: '⁞'; color: #c0392b; opacity: 1;
  left: 0; right: auto; width: 0; overflow: visible; white-space: nowrap;
  transform: translateX(-50%);
}
.mirror-mode .mirror-rawblock-head { display: flex; align-items: center; gap: 8px; margin-bottom: 4px; }
.mirror-mode .mirror-rawblock-name { font-family: 'Menlo', 'Courier New', monospace; font-size: 12px; font-weight: 600; color: #8a5a00; }
.mirror-mode .mirror-rawblock-name::before { content: '⟨ '; opacity: .6; }
.mirror-mode .mirror-rawblock-name::after { content: ' ⟩'; opacity: .6; }
.mirror-mode .mirror-rawblock-tag { font-size: 10px; text-transform: uppercase; letter-spacing: .5px; color: #b08a3a; background: #f5e9cf; border-radius: 3px; padding: 1px 5px; }
.mirror-mode .mirror-rawblock-preview { display: block; font-family: 'Menlo', 'Courier New', monospace; font-size: 11px; color: #6b5a33; white-space: pre-wrap; word-break: break-word; }
.mirror-mode .mirror-edit-btn {
  margin-left: auto; font: inherit; font-size: 11px; cursor: pointer;
  border: 1px solid #c7ccd2; background: #fff; color: #2e5c7a; border-radius: 4px; padding: 1px 8px;
}
.mirror-mode .mirror-edit-btn:hover { background: #eef4fb; border-color: #9bb6cc; }

/* ---------- Inline comments (Stage 2c) ---------- */
/* Anchor highlight inside the manuscript; mirrors the CodeMirror look. */
.mirror-mode .mirror-comment-anchor {
  background-color: rgba(255, 200, 100, 0.18);
  border-bottom: 1.5px dotted rgba(200, 130, 50, 0.7);
  cursor: pointer;
}
.mirror-mode .mirror-comment-anchor:hover { background-color: rgba(255, 200, 100, 0.32); }
/* Transient flash when the Comments panel reveals a passage (click a card). */
.mirror-mode .mirror-comment-anchor.mirror-comment-flash { animation: mirror-comment-flash 1.6s ease-out; }
@keyframes mirror-comment-flash {
  0%, 30% { background-color: rgba(255, 180, 60, 0.75); box-shadow: 0 0 0 3px rgba(255, 180, 60, 0.35); }
  100%    { background-color: rgba(255, 200, 100, 0.18); box-shadow: 0 0 0 0 rgba(255, 180, 60, 0); }
}

/* ---------- Outline bookmarks ---------- */
/* A marked word carries NO standing highlight: marking a word into the Outline is
   a navigation aid, not an annotation on the prose, so the manuscript must read
   exactly as it did before. The anchor span is still emitted (decoration-only,
   never serialized) because it is what the Outline scrolls to and flashes. */
/* Transient flash when the Outline reveals a marked word (click its entry). */
.mirror-mode .mirror-bookmark-anchor.mirror-bookmark-flash { animation: mirror-bookmark-flash 1.6s ease-out; }
/* Fades to fully transparent: there is no standing tint to settle back into. */
@keyframes mirror-bookmark-flash {
  0%, 30% { background-color: rgba(60, 120, 210, 0.7); box-shadow: 0 0 0 3px rgba(60, 120, 210, 0.3); }
  100%    { background-color: rgba(60, 120, 210, 0); box-shadow: 0 0 0 0 rgba(60, 120, 210, 0); }
}

/* Right-click "Add comment" menu and the click-to-read tooltip are appended to
   document.body (not inside .mirror-mode), so these rules are unscoped. */
.mirror-comment-menu {
  position: fixed; z-index: 9999; background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px;
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.18); padding: 4px 0; min-width: 150px;
  font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
/* Long synonym lists scroll. The viewport term also bounds the menu on a short
   window, so the JS clamp always has a box it can fit fully on-screen. */
.mirror-comment-menu { max-height: min(340px, calc(100vh - 16px)); overflow-y: auto; }
.mirror-comment-menu-item { padding: 6px 14px; cursor: pointer; user-select: none; }
.mirror-comment-menu-item:hover { background: rgba(122, 59, 46, 0.10); }
/* Section header (e.g. "Synonyms for …") — a label, not an action. */
.mirror-menu-header {
  padding: 5px 14px 3px; font-size: 11px; font-weight: 600; letter-spacing: 0.02em;
  color: #999; text-transform: none; user-select: none; cursor: default;
}
/* Non-actionable rows: "Looking up…", "No synonyms found". */
.mirror-comment-menu-item.is-disabled { color: #aaa; cursor: default; }
.mirror-comment-menu-item.is-disabled:hover { background: transparent; }
/* Divider between the synonyms section and Add comment. */
.mirror-menu-sep { height: 1px; margin: 4px 0; background: rgba(0, 0, 0, 0.10); }

.mirror-comment-tooltip {
  position: fixed; z-index: 9999; background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); padding: 8px 12px; max-width: 360px;
  font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.mirror-comment-tooltip .mirror-comment-author { font-size: 11px; color: #888; margin-bottom: 4px; }
.mirror-comment-tooltip .mirror-comment-body { color: #2a2a2a; margin-bottom: 8px; white-space: pre-wrap; line-height: 1.4; }
.mirror-comment-tooltip .mirror-comment-actions { display: flex; gap: 6px; }
.mirror-comment-tooltip .mirror-comment-edit,
.mirror-comment-tooltip .mirror-comment-delete {
  background: rgba(0, 0, 0, 0.04); border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 3px;
  padding: 3px 10px; cursor: pointer; font-size: 11px; color: #2a2a2a;
}
.mirror-comment-tooltip .mirror-comment-edit:hover,
.mirror-comment-tooltip .mirror-comment-delete:hover { background: rgba(122, 59, 46, 0.10); border-color: rgba(122, 59, 46, 0.4); }

/* ---------- Grammar-check findings ---------- */
/* Red wavy underline on the flagged prose; click to open the Accept/Dismiss popover. */
.mirror-mode .mirror-grammar-squiggle {
  text-decoration: underline;
  text-decoration-style: wavy;
  text-decoration-color: #d64545;
  text-decoration-skip-ink: none;
  text-underline-offset: 2px;
  cursor: pointer;
}
.mirror-mode .mirror-grammar-squiggle:hover { background-color: rgba(214, 69, 69, 0.10); }

/* Popover appended to document.body (unscoped, like the comment tooltip). */
.mirror-grammar-tooltip {
  position: fixed; z-index: 9999; background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); padding: 8px 12px; max-width: 340px;
  font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.mirror-grammar-tooltip .mirror-grammar-reason { color: #555; margin-bottom: 4px; line-height: 1.4; }
.mirror-grammar-tooltip .mirror-grammar-suggestion { color: #1a1a1a; font-weight: 600; margin-bottom: 8px; white-space: pre-wrap; }
.mirror-grammar-tooltip .mirror-grammar-actions { display: flex; gap: 6px; }
.mirror-grammar-tooltip .mirror-grammar-accept,
.mirror-grammar-tooltip .mirror-grammar-dismiss {
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 3px;
  padding: 3px 10px; cursor: pointer; font-size: 11px;
}
.mirror-grammar-tooltip .mirror-grammar-accept { background: rgba(40, 140, 70, 0.12); border-color: rgba(40, 140, 70, 0.4); color: #1d6b39; }
.mirror-grammar-tooltip .mirror-grammar-accept:hover { background: rgba(40, 140, 70, 0.20); }
.mirror-grammar-tooltip .mirror-grammar-dismiss { background: rgba(0, 0, 0, 0.04); color: #2a2a2a; }
.mirror-grammar-tooltip .mirror-grammar-dismiss:hover { background: rgba(122, 59, 46, 0.10); border-color: rgba(122, 59, 46, 0.4); }

/* ---------- Suggesting mode: tracked changes as marks-in-model (ADR 0007) ---------- */
/* Pending insertion: IN the model, marked, shown in the author's colour so a
   reader can tell coauthors apart at a glance. The colour comes from the mark's
   validated --sugg-color custom property (schema-spec.js suggInsert). */
.mirror-mode .mirror-sugg-insert {
  color: var(--sugg-color, #7b5cd6);
  text-decoration: underline; text-decoration-color: var(--sugg-color, #7b5cd6);
  text-underline-offset: 2px;
  cursor: pointer;
}
/* Pending deletion (slice 2): struck trunk text, still present until accepted. */
.mirror-mode .mirror-sugg-delete {
  text-decoration: line-through; text-decoration-thickness: 1.5px;
  text-decoration-color: var(--sugg-color, #7b5cd6);
  opacity: 0.72; cursor: pointer;
}
.mirror-proposal-tooltip {
  position: fixed; z-index: 9999; background: #fff;
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 4px;
  box-shadow: 0 4px 12px rgba(0, 0, 0, 0.18); padding: 8px 12px;
  font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}
.mirror-proposal-tooltip .mirror-proposal-author { font-size: 11px; color: #888; margin-bottom: 6px; }
.mirror-proposal-tooltip .mirror-proposal-actions { display: flex; gap: 6px; }
.mirror-proposal-tooltip .mirror-proposal-accept,
.mirror-proposal-tooltip .mirror-proposal-reject {
  border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 3px;
  padding: 3px 12px; cursor: pointer; font-size: 11px;
}
.mirror-proposal-tooltip .mirror-proposal-accept { background: rgba(58, 122, 46, 0.12); color: #2e5c1e; border-color: rgba(58, 122, 46, 0.4); }
.mirror-proposal-tooltip .mirror-proposal-accept:hover { background: rgba(58, 122, 46, 0.22); }
.mirror-proposal-tooltip .mirror-proposal-reject { background: rgba(122, 46, 46, 0.10); color: #7a2e2e; border-color: rgba(122, 46, 46, 0.35); }
.mirror-proposal-tooltip .mirror-proposal-reject:hover { background: rgba(122, 46, 46, 0.20); }

/* Step-through review bar: walk suggestions one by one (Word Review-pane style). */
.suggestion-review-bar {
  position: fixed; top: 84px; left: 50%; transform: translateX(-50%);
  z-index: 9998; display: flex; align-items: center; gap: 14px;
  max-width: min(760px, 94vw); padding: 8px 12px;
  background: #fff; border: 1px solid rgba(0, 0, 0, 0.15); border-radius: 8px;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.20);
  font-size: 13px; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; color: #1c1c1c;
}
.suggestion-review-bar.hidden { display: none; }
.suggestion-review-bar:focus { outline: none; }
/* Drag-to-move: the whole bar is a grab surface (the action buttons re-assert cursor:pointer
   below), and the grip at the left is the affordance that says so. */
.suggestion-review-bar { cursor: grab; }
.suggestion-review-bar.srb-dragging { cursor: grabbing; user-select: none; }
.srb-grip {
  flex: 0 0 auto; cursor: grab; color: #b8b4ac; font-size: 15px; line-height: 1;
  letter-spacing: -2px; user-select: none; margin-right: -2px;
}
.srb-grip:hover { color: #8a8680; }
.suggestion-review-bar.srb-dragging .srb-grip { cursor: grabbing; }
.srb-count { font-weight: 600; color: #666; white-space: nowrap; }
.srb-body { display: flex; align-items: baseline; gap: 8px; min-width: 0; flex: 1 1 auto; overflow: hidden; }
.srb-author { font-weight: 600; white-space: nowrap; flex: 0 0 auto; }
.srb-diff { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; }
.srb-diff del { color: #7a2e2e; text-decoration: line-through; }
.srb-diff ins { color: #2e5c1e; text-decoration: none; background: rgba(58, 122, 46, 0.12); border-radius: 2px; padding: 0 3px; }
.srb-arrow { color: #999; padding: 0 2px; }
.srb-actions { display: flex; gap: 6px; flex: 0 0 auto; }
.srb-btn {
  border: 1px solid rgba(0, 0, 0, 0.15); background: #f7f6f3; color: #1c1c1c;
  border-radius: 4px; padding: 4px 10px; cursor: pointer; font-size: 12px; line-height: 1.4;
}
.srb-btn:hover:not(:disabled) { background: #efece6; }
.srb-btn:disabled { opacity: 0.4; cursor: default; }
.srb-accept { background: rgba(58, 122, 46, 0.12); color: #2e5c1e; border-color: rgba(58, 122, 46, 0.4); font-weight: 600; }
.srb-accept:hover:not(:disabled) { background: rgba(58, 122, 46, 0.22); }
.srb-reject { background: rgba(122, 46, 46, 0.10); color: #7a2e2e; border-color: rgba(122, 46, 46, 0.35); font-weight: 600; }
.srb-reject:hover:not(:disabled) { background: rgba(122, 46, 46, 0.20); }
/* Grammar review: the finding's reason (italic, muted) beside the original→suggestion diff; a
   "(remove)" suggestion reads as a deletion, not an insertion. */
.srb-grammar-reason { color: #666; font-style: italic; white-space: nowrap; flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.srb-diff ins.srb-remove { color: #7a2e2e; background: rgba(122, 46, 46, 0.10); }
/* The grammar "N findings" status doubles as a shortcut into the review bar. */
.compile-status.grammar-clickable { cursor: pointer; text-decoration: underline; text-underline-offset: 2px; }
.compile-status.grammar-clickable:hover { filter: brightness(0.9); }

/* Flash the suggestion the review bar just scrolled to. */
.mirror-proposal-flash {
  background: rgba(122, 92, 214, 0.22);
  box-shadow: 0 0 0 2px rgba(122, 92, 214, 0.30); border-radius: 3px;
  transition: background 0.5s ease, box-shadow 0.5s ease;
}

/* ---------- Display-math block (Stage 4: \begin{equation} etc.) ---------- */
.mirror-mode .mirror-mathblock {
  margin: 0.6em 0; padding: 6px 10px; text-align: center; cursor: pointer;
  border-radius: 4px; overflow-x: auto;
}
.mirror-mode .mirror-mathblock:hover { background: rgba(46, 92, 122, 0.06); }
.mirror-mode .mirror-mathblock .katex-display { margin: 0; }
/* Equation numbers for numbered display environments (equation/align/… without `*`),
   in document order. The counter resets at the content root and re-numbers automatically
   as equations move. A multi-row align shows one block number — KaTeX cannot render a
   per-row number (see nodeviews.js MathBlockView). */
.mirror-mode .ProseMirror, .mirror-mode .pgx-content { counter-reset: cw-eqn; }
.mirror-mode .mirror-mathblock.mirror-eq-num { position: relative; counter-increment: cw-eqn; }
.mirror-mode .mirror-mathblock.mirror-eq-num::after {
  content: "(" counter(cw-eqn) ")";
  position: absolute; right: 8px; top: 50%; transform: translateY(-50%);
  color: #333; font-size: 0.92em; pointer-events: none;
}

/* ---------- Editable table cell grid (Stage 4) ---------- */
.mirror-mode .mirror-table-grid {
  border-collapse: collapse; margin: 4px 0 8px; font-size: 0.92em; width: auto;
}
.mirror-mode .mirror-table-grid td {
  padding: 3px 8px; min-width: 28px;
  vertical-align: top; outline: none; font-family: inherit;
}
.mirror-mode .mirror-table-grid td:focus {
  background: #eef4fb; box-shadow: inset 0 0 0 2px #9bb6cc;
}
/* Faithful borders: draw only the rules the LaTeX actually has (booktabs = horizontal
   only; |l|l|+\hline = grid; plain tabular = none) instead of a uniform grid. The legacy
   full grid survives only for a table whose rows the shared parser could not align
   (.cw-grid-fallback), so an unparsed table never renders borderless by accident. */
.mirror-mode .mirror-table-grid.cw-grid-fallback td { border: 1px solid #d3d8de; }
.mirror-mode .mirror-table-grid tr.rule-top > * { border-top: 1.6px solid #333; }
.mirror-mode .mirror-table-grid tr.rule-mid > * { border-top: 1px solid #666; }
.mirror-mode .mirror-table-grid tr.rule-bottom > * { border-bottom: 1.6px solid #333; }
.mirror-mode .mirror-table-grid td.cw-vl,
.mirror-mode .mirror-realtable td.cw-vl, .mirror-mode .mirror-realtable th.cw-vl { border-left: 1px solid #555; }
.mirror-mode .mirror-table-grid td.cw-vr,
.mirror-mode .mirror-realtable td.cw-vr, .mirror-mode .mirror-realtable th.cw-vr { border-right: 1px solid #555; }
.mirror-mode .mirror-realtable tr.rule-bottom > * { border-bottom: 1.6px solid #333; }

/* ---------- Wrapper container (Stage 4: landscape) ---------- */
.mirror-mode .mirror-container {
  position: relative; border: 1px dashed #c7ccd2; border-radius: 5px;
  padding: 10px 12px 8px; margin: 0.7em 0;
}
.mirror-mode .mirror-container::before {
  content: attr(data-env); position: absolute; top: -0.7em; left: 10px;
  font-size: 10px; text-transform: uppercase; letter-spacing: .5px;
  color: #8a93a0; background: #fff; padding: 0 6px;
}

/* Paragraph-alignment containers (center / flushleft / flushright) are plain
   alignment, not a boxed construct: drop the dashed border + env label so they
   read like Word (just aligned text), and apply the matching text-align, which
   the inner paragraphs inherit. Applies equally to the off-screen brain and the
   page-box clones (both live under .mirror-mode). Landscape keeps its box. */
.mirror-mode .mirror-container[data-env="center"],
.mirror-mode .mirror-container[data-env="flushleft"],
.mirror-mode .mirror-container[data-env="flushright"] {
  border: none; padding: 0; margin: 0;
}
.mirror-mode .mirror-container[data-env="center"]::before,
.mirror-mode .mirror-container[data-env="flushleft"]::before,
.mirror-mode .mirror-container[data-env="flushright"]::before { content: none; }
.mirror-mode .mirror-container[data-env="center"] { text-align: center; }
.mirror-mode .mirror-container[data-env="flushright"] { text-align: right; }
.mirror-mode .mirror-container[data-env="flushleft"] { text-align: left; }

/* A block quote is an indented paragraph in Word, not a boxed construct: drop the dashed border and
   the env label, and indent both sides the way LaTeX's `quote` does. The inner paragraphs stay
   ordinary editable paragraphs — the whole point is that a writer can type in them. */
.mirror-mode .mirror-container[data-env="quote"] {
  border: none; padding: 0; margin: 0.6em 0; padding-left: 0.5in; padding-right: 0.5in;
}
.mirror-mode .mirror-container[data-env="quote"]::before { content: none; }
.mirror-mode .mirror-container[data-env="quote"] > p { --p-indent-inherited: 0in; }

/* `quotation` is the same construct as `quote` (an indented block quote); pandoc
   emits either. Style it identically: no box, no env label, indented both sides. */
.mirror-mode .mirror-container[data-env="quotation"] {
  border: none; padding: 0; margin: 0.6em 0; padding-left: 0.5in; padding-right: 0.5in;
}
.mirror-mode .mirror-container[data-env="quotation"]::before { content: none; }
.mirror-mode .mirror-container[data-env="quotation"] > p { text-indent: 0; }

/* Abstract: the PDF centers an "Abstract" heading over a slightly narrower, smaller
   body. Render it that way — no box, centered label, indented body — while the inner
   paragraphs stay ordinary editable content (a writer types their abstract in place). */
.mirror-mode .mirror-container[data-env="abstract"] {
  border: none; padding: 0; margin: 1em 1.6em; font-size: 0.95em;
}
.mirror-mode .mirror-container[data-env="abstract"]::before {
  content: "Abstract"; position: static; display: block; text-align: center;
  font-weight: 700; font-size: 1em; text-transform: none; letter-spacing: 0;
  color: inherit; background: none; padding: 0; margin: 0 0 0.4em;
}
.mirror-mode .mirror-container[data-env="abstract"] > p { text-indent: 0; }

/* Theorem family (amsthm): a bold run-in label over an editable body, with a subtle
   left rule instead of the generic dashed box. Numbering is the LaTeX PDF's job (it
   depends on the doc's \newtheorem config), so the editor shows the label only. */
.mirror-mode .mirror-container[data-env="theorem"],
.mirror-mode .mirror-container[data-env="lemma"],
.mirror-mode .mirror-container[data-env="proof"],
.mirror-mode .mirror-container[data-env="definition"],
.mirror-mode .mirror-container[data-env="corollary"],
.mirror-mode .mirror-container[data-env="proposition"],
.mirror-mode .mirror-container[data-env="remark"],
.mirror-mode .mirror-container[data-env="example"],
.mirror-mode .mirror-container[data-env="claim"] {
  border: none; border-left: 2px solid #d7dbe0; border-radius: 0;
  padding: 0.05em 0 0.05em 12px; margin: 0.7em 0;
}
.mirror-mode .mirror-container[data-env="theorem"]::before,
.mirror-mode .mirror-container[data-env="lemma"]::before,
.mirror-mode .mirror-container[data-env="proof"]::before,
.mirror-mode .mirror-container[data-env="definition"]::before,
.mirror-mode .mirror-container[data-env="corollary"]::before,
.mirror-mode .mirror-container[data-env="proposition"]::before,
.mirror-mode .mirror-container[data-env="remark"]::before,
.mirror-mode .mirror-container[data-env="example"]::before,
.mirror-mode .mirror-container[data-env="claim"]::before {
  position: static; display: block; margin: 0 0 0.15em;
  font-weight: 700; font-size: 1em; text-transform: none; letter-spacing: 0;
  color: inherit; background: none; padding: 0;
}
/* The body under the label is the lead content, so drop the default first-line
   indent (matching abstract/quote) — the label already sets the block off. */
.mirror-mode .mirror-container[data-env="theorem"] > p,
.mirror-mode .mirror-container[data-env="lemma"] > p,
.mirror-mode .mirror-container[data-env="proof"] > p,
.mirror-mode .mirror-container[data-env="definition"] > p,
.mirror-mode .mirror-container[data-env="corollary"] > p,
.mirror-mode .mirror-container[data-env="proposition"] > p,
.mirror-mode .mirror-container[data-env="remark"] > p,
.mirror-mode .mirror-container[data-env="example"] > p,
.mirror-mode .mirror-container[data-env="claim"] > p { text-indent: 0; }
.mirror-mode .mirror-container[data-env="theorem"]::before { content: "Theorem"; }
.mirror-mode .mirror-container[data-env="lemma"]::before { content: "Lemma"; }
.mirror-mode .mirror-container[data-env="definition"]::before { content: "Definition"; }
.mirror-mode .mirror-container[data-env="corollary"]::before { content: "Corollary"; }
.mirror-mode .mirror-container[data-env="proposition"]::before { content: "Proposition"; }
.mirror-mode .mirror-container[data-env="remark"]::before { content: "Remark"; }
.mirror-mode .mirror-container[data-env="example"]::before { content: "Example"; }
.mirror-mode .mirror-container[data-env="claim"]::before { content: "Claim"; }
/* amsthm renders a proof's label in italic and appends a QED box; keep it distinct. */
.mirror-mode .mirror-container[data-env="proof"]::before { content: "Proof"; font-style: italic; font-weight: 400; }

/* Verbatim / lstlisting rendered as a real code block (RawLatexView cosmetic): a
   raw block is drawn as monospace, whitespace-preserved code instead of a chip. */
.mirror-mode .mirror-codeblock-wrap { position: relative; margin: 0.7em 0; }
.mirror-mode .mirror-codeblock {
  font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
  font-size: 0.85em; line-height: 1.45; white-space: pre; overflow-x: auto;
  background: #f6f8fa; border: 1px solid #e3e7ec; border-radius: 6px;
  padding: 10px 12px; margin: 0; color: #24292f; tab-size: 2;
}

/* Description list rendered as a definition list (RawLatexView cosmetic). */
.mirror-mode .mirror-desclist-wrap { position: relative; margin: 0.7em 0; }
.mirror-mode .mirror-desclist { margin: 0; }
.mirror-mode .mirror-desclist dt { font-weight: 700; margin: 0.4em 0 0; }
.mirror-mode .mirror-desclist dd { margin: 0 0 0 1.6em; }

/* The Edit button on a cosmetic raw render: top-right, revealed on hover. */
.mirror-mode .mirror-codeblock-wrap .mirror-edit-btn,
.mirror-mode .mirror-desclist-wrap .mirror-edit-btn {
  position: absolute; top: 4px; right: 4px; opacity: 0; transition: opacity .12s;
}
.mirror-mode .mirror-codeblock-wrap:hover .mirror-edit-btn,
.mirror-mode .mirror-desclist-wrap:hover .mirror-edit-btn { opacity: 1; }

/* \tableofcontents / \listof… placeholder (RawInlineView cosmetic): the real list
   is produced by the LaTeX PDF at compile, so the editor shows a labeled marker. */
.mirror-mode .mirror-toc-placeholder {
  display: inline-block; font-size: 0.85em; color: #6b7480;
  background: #f2f4f7; border: 1px dashed #cfd5dc; border-radius: 5px; padding: 1px 8px;
}

/* ---------- Compile-driven page-break markers ---------- */
/* Block form: a divider between two blocks (break at a paragraph boundary). */
.mirror-mode .mirror-page-break {
  display: block; position: relative; height: 0; margin: 1.1em 0;
  border-top: 1px dashed #b9c2cc; user-select: none; pointer-events: none;
}
/* Inline form: a break that falls MID-paragraph. inline-block + full width forces
   the line to end here and the divider to span the page, so the paragraph splits
   exactly where the PDF page does. */
.mirror-mode .mirror-page-break.is-inline {
  display: inline-block; width: 100%; vertical-align: top;
  margin: 0.5em 0; height: 0.6em;
}
.mirror-mode .mirror-page-break-folio {
  position: absolute; right: 0; top: -0.75em; background: #fff;
  padding: 0 8px; font-size: 10px; letter-spacing: .4px; text-transform: uppercase;
  color: #97a1ad; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
}

/* ============================================================
   Word-style pagination (Phase 1) — overlay sheets.
   Scoped under `.mirror-mode.paginated` (added by app.js when the
   paginatedEditor flag is on) and `.paginated-host` (added by the
   paginator to the scroll container). Inert otherwise — flag-off and
   non-paginated mirror mode are byte-identical to before.
   ============================================================ */
.mirror-mode.paginated .mirror-wysiwyg.paginated-host { background: #525659; position: relative; }

/* ---------- Page rulers (ADR 0008, Rule 7: the geometry, made visible) ---------- */
.mirror-mode.paginated .paginated-host.has-rulers { padding-left: var(--pg-gutter); }
.pg-ruler { box-sizing: border-box; font: 9px/1 -apple-system, BlinkMacSystemFont, sans-serif; color: #9aa0a6; pointer-events: none; }
/* The horizontal bar spans the host's FULL width, gutter included, and stays there while the
   content scrolls sideways. The sticky `left` has to be the negative gutter, not 0: sticky clamps
   an element to its `left` threshold measured from the SCROLLPORT, which is the padding box, so
   `left: 0` pinned the bar to the padding edge and the `margin-left: -30px` meant to pull it over
   the gutter never rendered at all — computed as -30px, drawn at +0. The gutter showed as a strip
   of bare canvas to the left of the ruler (reported 2026-08-27). Verified at 200% zoom: the bar
   holds the host's left edge at every horizontal scroll offset, fully scrolled right included. */
.pg-ruler-h {
  position: sticky; top: 0; left: calc(-1 * var(--pg-gutter)); z-index: 6; height: 24px;
  width: calc(100% + var(--pg-gutter)); margin-left: calc(-1 * var(--pg-gutter));
  background: #edeff1; border-bottom: 1px solid #d4d7dc;
}
/* The vertical ruler's visible strip lives on the BAND, not the container: one band per
   page, each flush against the page it measures, so a landscape page and a portrait page
   each get the strip at their own left edge (rulers.js placeV). The container is a
   transparent positioning layer spanning only the gutter between them. */
/* The ruler's two fixed widths, each stated once: the visible strip, and the left gutter the
   host reserves for it (which the horizontal bar must also cover — see .pg-ruler-h). */
.has-rulers { --pg-vruler-w: 28px; --pg-gutter: 30px; }
.pg-ruler-v { position: absolute; left: 0; width: var(--pg-vruler-w, 28px); z-index: 5; }
.pg-ruler-corner { position: sticky; top: 0; left: 0; z-index: 7; width: var(--pg-vruler-w, 28px); height: 24px; margin-bottom: -24px; background: #e3e5e8; border-right: 1px solid #d4d7dc; border-bottom: 1px solid #d4d7dc; }
.pg-ruler-track { position: absolute; top: 0; height: 100%; }
.pg-ruler-h .pg-ruler-content { position: absolute; bottom: 0; height: 7px; }
.pg-ruler-h .pg-ruler-margin { position: absolute; top: 0; bottom: 0; background: rgba(110,120,135,0.20); }
.pg-ruler-h .pg-ruler-num { position: absolute; bottom: 8px; transform: translateX(-50%); }
.pg-ruler-indent { position: absolute; bottom: 0; margin-left: -4px; width: 0; height: 0; border-left: 4px solid transparent; border-right: 4px solid transparent; border-bottom: 7px solid #5b6470; }
.pg-ruler-vpage { position: absolute; left: 0; width: var(--pg-vruler-w, 28px); background: #edeff1; border-right: 1px solid #d4d7dc; }
.pg-ruler-v .pg-ruler-content { position: absolute; left: 0; width: 7px; }
.pg-ruler-v .pg-ruler-margin { position: absolute; left: 0; width: 100%; background: rgba(110,120,135,0.20); }
.pg-ruler-v .pg-ruler-num { position: absolute; left: 9px; transform: translateY(-50%); }
/* Drag handles (ADR 0008, Rule 7: the ruler writes back to the geometry). */
.pg-ruler-handle { position: absolute; pointer-events: auto; z-index: 2; }
.pg-ruler-h .pg-ruler-handle.mh { top: 0; height: 100%; width: 8px; margin-left: -4px; cursor: ew-resize; }
.pg-ruler-v .pg-ruler-handle.mh { left: 0; width: 100%; height: 8px; margin-top: -4px; cursor: ns-resize; }
.pg-ruler-handle.mh:hover { background: rgba(74,144,217,0.35); }
.pg-ruler-indent { cursor: ew-resize; pointer-events: auto; z-index: 3; }
.pg-ruler-guide { position: absolute; z-index: 8; pointer-events: none; background: #4a90d9; display: none; }
.pg-ruler-guide.visible { display: block; }
.pg-ruler-guide.x { width: 1px; }
.pg-ruler-guide.y { height: 1px; }
.pg-ruler-tip { position: absolute; z-index: 9; display: none; background: #2b2f36; color: #fff; font: 10px/1.4 -apple-system, sans-serif; padding: 2px 6px; border-radius: 3px; pointer-events: none; white-space: nowrap; }
.pg-ruler-tip.visible { display: block; }

.mirror-mode.paginated .pg-stack { position: relative; margin: 0 auto; zoom: var(--editor-zoom, 1); }
.mirror-mode.paginated .pg-sheets { position: absolute; inset: 0; z-index: 0; pointer-events: none; }
.mirror-mode.paginated .pg-sheet {
  position: absolute; left: 0;
  width: var(--pg-page-w); height: var(--pg-page-h);
  background: #fff; box-shadow: 0 1px 8px rgba(0,0,0,.5);
}
.mirror-mode.paginated .pg-folio {
  position: absolute; left: 0; right: 0; bottom: calc(var(--pg-margin) * 0.40);
  text-align: center; color: #9aa0a6; font-size: 10pt;
  font-family: 'Times New Roman', Georgia, serif;
}
/* Page-number position (Insert > Page number). Edge picks top vs bottom; side
   picks the horizontal alignment within the margin. */
.mirror-mode.paginated .pg-folio--top-left,
.mirror-mode.paginated .pg-folio--top-center,
.mirror-mode.paginated .pg-folio--top-right { top: calc(var(--pg-margin) * 0.40); bottom: auto; }
.mirror-mode.paginated .pg-folio--bottom-left,
.mirror-mode.paginated .pg-folio--bottom-center,
.mirror-mode.paginated .pg-folio--bottom-right { top: auto; bottom: calc(var(--pg-margin) * 0.40); }
.mirror-mode.paginated .pg-folio--top-left,
.mirror-mode.paginated .pg-folio--bottom-left { text-align: left; padding: 0 var(--pg-margin); }
.mirror-mode.paginated .pg-folio--top-right,
.mirror-mode.paginated .pg-folio--bottom-right { text-align: right; padding: 0 var(--pg-margin); }
.mirror-mode.paginated .pg-gap { display: block; width: 100%; pointer-events: none; user-select: none; }

/* The editable goes transparent + full page-width so the sheets show through;
   the single-sheet `.ProseMirror` styling above is neutralised in this mode. */
.mirror-mode.paginated .paginated-host .ProseMirror {
  position: relative; z-index: 1;
  max-width: none; width: var(--pg-page-w); margin: 0;
  padding: var(--pg-margin) var(--pg-margin) 0 var(--pg-margin);
  background: transparent; box-shadow: none; min-height: 0;
}

/* ============================================================
   Word-like rendering of common non-content LaTeX (nodeviews.js
   RawInlineView): \maketitle title block, \bibliography placeholder,
   and hidden invisible directives. Rendering-only; the source is
   unchanged. Scoped to mirror mode.
   ============================================================ */
.mirror-mode .mirror-title-block { display: block; text-align: center; margin: 0.1in 0 0.4in; }
.mirror-mode .mirror-title-line { display: block; font-size: 18pt; font-weight: 700; line-height: 1.25; }
.mirror-mode .mirror-title-author { display: block; font-size: 12pt; margin-top: 10px; }
.mirror-mode .mirror-title-date { display: block; font-size: 12pt; margin-top: 6px; color: #333; }
/* The block is a render of preamble state, so it is not typed into; clicking it
   opens the Title and authors dialog. The hover tint is the whole affordance —
   nothing is drawn on top, because this is the first thing on a printed page. A
   reader gets the render without the invitation. */
.mirror-mode .mirror-title-block.is-editable { cursor: pointer; border-radius: 4px; transition: background 90ms ease; }
.mirror-mode .mirror-title-block.is-editable:hover { background: rgba(184, 131, 122, 0.10); }
.mirror-read-only .mirror-title-block.is-editable { cursor: default; }
.mirror-read-only .mirror-title-block.is-editable:hover { background: none; }
.mirror-mode .mirror-references-ph {
  display: block; margin-top: 1em; padding-top: .5em;
  border-top: 1px solid #d9dde2; color: #8a9099; font-style: italic;
}
.mirror-mode .mirror-rawinline-hidden { display: none; }

/* Raw blocks that are really an image (\includegraphics wrapped in center/etc.)
   render as the image (nodeviews.js RawLatexView.buildImage); allow a taller cap
   than inline figures so real page figures show at a usable size. */
.mirror-mode .mirror-image-block { margin: 1em 0; }
.mirror-mode .mirror-image-block img { max-height: 5in; }

/* Mid-paragraph split gap (Phase 2): a full-width inline-block ends the current
   line and lands the paragraph's continuation on the next sheet. */
.mirror-mode.paginated .pg-gap.is-inline { display: inline-block; vertical-align: top; }

/* Phase 3 — rendered reference list at the \bibliography{} position
   (nodeviews.js refs branch + render-bibliography.js). APA hanging indent. */
/* The reference list is formattable INDEPENDENTLY of the body via the "Format
   references" affordance (mirror-editor-pane.js setBibFormat → CW-BIBFMT preamble
   block → these --mirror-bib-* vars, set in applyDocStyleVars). Each var falls
   back to the document default, so an unformatted list looks exactly as before. */
.mirror-mode .mirror-bibliography { display: block; margin: 1em 0; position: relative; text-align: var(--mirror-bib-align, left); font-family: var(--mirror-bib-font, inherit); }
.mirror-mode .mirror-bib-entry {
  padding-left: var(--mirror-bib-hang, 0.5in);
  text-indent: calc(0px - var(--mirror-bib-hang, 0.5in));
  margin: 0 0 var(--mirror-bib-gap, 0.5em);
  font-size: var(--mirror-bib-fontsize, inherit);
  line-height: var(--mirror-bib-linespacing, var(--mirror-linespacing, 1.2));
  font-weight: var(--mirror-bib-weight, inherit);
  font-style: var(--mirror-bib-style, inherit);
  text-decoration: var(--mirror-bib-decoration, none);
}
/* Numeric reference list: "[n]" hangs in the left gutter, body indented. */
.mirror-mode .mirror-bibliography--numbered .mirror-bib-entry { padding-left: 2.4em; text-indent: 0; }
.mirror-mode .mirror-bib-num { display: inline-block; width: 2.4em; margin-left: -2.4em; }
.mirror-mode .mirror-bib-entry em { font-style: var(--mirror-bib-em-style, italic); }
.mirror-mode .mirror-bib-empty { color: #8a9099; font-style: italic; }
/* "⚙ Format references" — appears on hover at the top-right of the list. */
.mirror-mode .mirror-bib-format-btn {
  position: absolute; top: -1.7em; right: 0; z-index: 4;
  font: 500 11px/1 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
  padding: 4px 9px; border-radius: 6px; white-space: nowrap;
  border: 1px solid rgba(74, 123, 214, 0.40); background: #fff; color: #2c5cc4;
  cursor: pointer; opacity: 0; transition: opacity .12s;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.10); user-select: none;
}
.mirror-mode .mirror-bibliography:hover .mirror-bib-format-btn,
.mirror-mode .mirror-bib-format-btn:hover,
.mirror-mode .mirror-bib-format-btn:focus-visible { opacity: 1; }
@media print { .mirror-bib-format-btn { display: none !important; } }
#pg-print-root .mirror-bib-format-btn { display: none !important; }
/* Reference-list formatting popover (app.js showBibFormatPopover). */
.bibfmt-popover {
  position: absolute; z-index: 10000; width: 268px;
  background: #fff; border: 1px solid #dfe3ea; border-radius: 10px;
  box-shadow: 0 8px 28px rgba(0, 0, 0, 0.16); padding: 12px 14px;
  font: 13px/1.3 -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; color: #1c2330;
}
.bibfmt-title { font-weight: 600; font-size: 13px; margin: 0 0 10px; }
/* Label stacked above a full-width segmented control, so a 4-option row never
   clips regardless of the label/option text width. */
.bibfmt-row { display: flex; flex-direction: column; align-items: stretch; gap: 5px; margin: 0 0 10px; }
.bibfmt-label { color: #4a5261; font-size: 11px; font-weight: 500; }
.bibfmt-seg { display: flex; border: 1px solid #d3d8e0; border-radius: 7px; overflow: hidden; }
.bibfmt-opt {
  flex: 1 1 0; text-align: center; white-space: nowrap;
  appearance: none; border: 0; border-left: 1px solid #e3e7ee; background: #fff; color: #2c3340;
  padding: 5px 6px; font: inherit; cursor: pointer;
}
.bibfmt-opt:first-child { border-left: 0; }
.bibfmt-opt:hover { background: #f1f4f9; }
.bibfmt-opt.is-active { background: #2c5cc4; color: #fff; }
/* Each B/I/U/S toggle previews the style it applies. */
.bibfmt-style { font-size: 13px; }
.bibfmt-style-bold { font-weight: 700; }
.bibfmt-style-italic { font-style: italic; }
.bibfmt-style-underline { text-decoration: underline; }
.bibfmt-style-strike { text-decoration: line-through; }
.bibfmt-select {
  width: 100%; padding: 5px 8px; font: inherit; color: #2c3340; cursor: pointer;
  border: 1px solid #d3d8e0; border-radius: 7px; background: #fff;
}
.bibfmt-note { margin-top: 8px; color: #8a9099; font-size: 11px; line-height: 1.35; }
/* In-editor reference edit: each field is hoverable; clicking opens an inline
   editor overlay seeded with the source BibTeX value (mirror-editor-pane.js). */
.mirror-mode .mirror-bib-field { cursor: text; border-radius: 2px; transition: background-color .08s; }
.mirror-mode .mirror-bib-field:hover { background: rgba(74, 123, 214, 0.14); box-shadow: 0 0 0 1px rgba(74, 123, 214, 0.30); }
.mirror-bib-edit {
  position: fixed; z-index: 10001; box-sizing: border-box;
  background: #fff; color: #111; max-width: 60ch; white-space: pre-wrap;
  border: 1px solid #4a7bd6; border-radius: 3px; padding: 1px 4px;
  box-shadow: 0 3px 14px rgba(0, 0, 0, 0.20); outline: none;
}

/* Hide LaTeX comments + scaffolding-only paragraphs in the editor
   (latex-cosmetics.js). Rendering-only; the source is unchanged. */
.mirror-mode .pg-cosmetic-hidden { display: none; }

/* Real tables (render-table.js) — Word-like booktabs look, not a chip. */
.mirror-mode .mirror-table { position: relative; margin: 1em 0; text-align: center; border: 0; background: none; padding: 0; border-radius: 0; }
.mirror-mode .mirror-realtable, .mirror-mode .mirror-table-grid { border-collapse: collapse; margin: 0 auto; font-size: 10.5pt; line-height: 1.35; }
/* Real tables scroll horizontally rather than crush. table-layout:fixed forced a
   many-column table (e.g. a 22-column correlation matrix) into the page width and
   overflow-wrap:anywhere then broke every cell character-by-character — unreadable.
   Auto layout sizes columns to their content; min-width:100% still fills the page
   for a narrow proportional table; the .mirror-table-scroll wrapper lets a wide
   (or landscape) table exceed the sheet and scroll instead of collapsing. */
.mirror-mode .mirror-table-scroll { overflow-x: auto; max-width: 100%; }
.mirror-mode .mirror-realtable--full { min-width: 100%; margin: 0; }
.mirror-mode .mirror-realtable th, .mirror-mode .mirror-realtable td { padding: 4px 12px; vertical-align: top; max-width: 26em; overflow-wrap: break-word; }
.mirror-mode .mirror-realtable th { font-weight: 700; }
.mirror-mode .mirror-realtable tr.rule-top > * { border-top: 1.6px solid #333; }
.mirror-mode .mirror-realtable thead { border-bottom: 1px solid #555; }
.mirror-mode .mirror-realtable tr.rule-mid > * { border-top: 1px solid #888; }
.mirror-mode .mirror-realtable tbody tr:last-child > * { border-bottom: 1.6px solid #333; }
.mirror-mode .mirror-table-caption { font-size: 10.5pt; color: #333; margin-bottom: 6px; font-style: italic; }
.mirror-mode .mirror-table-edit { position: absolute; top: 0; right: 0; opacity: 0; transition: opacity .12s; font-size: 10px; }
.mirror-mode .mirror-table:hover .mirror-table-edit { opacity: .85; }

/* Page-break spacer inside a splittable table/list (paginate.js applyInnerGaps). */
.mirror-mode .pg-inner-gap, .mirror-mode .pg-inner-gap td { border: 0 !important; padding: 0 !important; background: none !important; }

/* Repeated table header on continuation pages (paginate.js). */
.mirror-mode .pg-cloned-header > * { font-weight: 700; border-top: 1.6px solid #333; border-bottom: 1px solid #555; padding: 4px 12px; vertical-align: top; }

/* ============================================================
   Print / Export PDF — a faithful render of the editor (print.js).
   The browser paginates the cloned content at @page geometry.
   ============================================================ */
/* PrintView tab: a read-only, print-faithful preview of the editor's pages
   (a snapshot clone of the live paginated render). Same .pg-sheet CSS applies. */
.printview-preview { flex: 1; min-height: 0; overflow: auto; background: #525659; }
.printview-preview .printview-doc.mirror-mode { height: auto; overflow: visible; display: block; }
.printview-preview .printview-doc .paginated-host { background: #525659; padding: 16px 0; }
.printview-preview .printview-doc .ProseMirror { caret-color: transparent; }
.printview-empty { color: #cfd2d6; padding: 24px; font: 13px -apple-system, sans-serif; }

#pg-print-root { display: none; }
@media print {
  html, body { background: #fff !important; margin: 0 !important; }
  body > *:not(#pg-print-root) { display: none !important; }
  /* The print root carries `.mirror-mode` for its descendant typography rules,
     which also brings `height:100%; overflow:hidden; display:flex` — that caps
     the render at one viewport and clips the rest. Force a natural flow box so
     the browser's paged-media engine paginates the whole document. */
  #pg-print-root { display: block !important; height: auto !important; overflow: visible !important; }
  #pg-print-root .ProseMirror { outline: none; max-width: none; width: auto; margin: 0; padding: 0; background: #fff;
    font-family: var(--mirror-fontfamily, 'Times New Roman', Georgia, serif); font-size: 12pt; line-height: var(--mirror-linespacing, 1.2); color: #000;
    text-align: var(--mirror-textalign, justify); }
  /* `hyphens` mirrors the editor's paragraph rule exactly; the two must never disagree, or the
     printed PDF re-wraps the paragraphs the editor already measured and paginated. */
  #pg-print-root p { margin: 0; text-indent: var(--mirror-parindent, 0.5in); orphans: 2; widows: 2;
    -webkit-hyphens: auto; hyphens: auto; }
  #pg-print-root h1 + p, #pg-print-root h2 + p, #pg-print-root h3 + p, #pg-print-root h4 + p { text-indent: 0; }
  #pg-print-root p.mirror-noindent { text-indent: 0; }
  #pg-print-root h1, #pg-print-root h2, #pg-print-root h3, #pg-print-root h4 {
    font-family: var(--mirror-fontfamily, 'Times New Roman', Georgia, serif); font-weight: 700; break-after: avoid; margin: .8em 0 .4em; }
  #pg-print-root h1 { font-size: 17pt; } #pg-print-root h2 { font-size: 15pt; } #pg-print-root h3 { font-size: 13pt; }
  #pg-print-root .pg-cosmetic-hidden { display: none !important; }
  #pg-print-root .mirror-title-block { display:block; text-align:center; margin:.1in 0 .4in; }
  #pg-print-root .mirror-title-line { display:block; font-size:18pt; font-weight:700; }
  #pg-print-root .mirror-title-author, #pg-print-root .mirror-title-date { display:block; font-size:12pt; }
  #pg-print-root figure, #pg-print-root .mirror-figure, #pg-print-root .mirror-image-block { break-inside: avoid; text-align: center; margin: 1em 0; }
  #pg-print-root img { max-width: 100%; }
  #pg-print-root table { border-collapse: collapse; margin: 0 auto; font-size: 10.5pt; }
  /* Match the editor: auto layout (no fixed/crush). A PDF can't scroll, so print.js
     scales a table wider than the page to fit (transform); narrow tables still fill. */
  #pg-print-root .mirror-realtable--full { min-width: 100%; margin: 0; }
  #pg-print-root .mirror-table-scroll { overflow: visible; }
  #pg-print-root table thead { display: table-header-group; }   /* repeat header on each printed page */
  #pg-print-root tr { break-inside: avoid; }
  #pg-print-root th, #pg-print-root td { padding: 4px 12px; vertical-align: top; }
  #pg-print-root .mirror-realtable th { font-weight: 700; }
  #pg-print-root .mirror-realtable tr.rule-top > * { border-top: 1.5px solid #000; }
  #pg-print-root .mirror-realtable thead { border-bottom: 1px solid #000; }
  #pg-print-root .mirror-realtable tbody tr:last-child > * { border-bottom: 1.5px solid #000; }
  #pg-print-root .mirror-bibliography { margin-top: 1em; }
  #pg-print-root .mirror-bib-entry { padding-left: .5in; text-indent: -.5in; margin: 0 0 .4em; }
  #pg-print-root .mirror-bibliography--numbered .mirror-bib-entry { padding-left: 2.4em; text-indent: 0; }
  #pg-print-root .mirror-bib-num { display: inline-block; width: 2.4em; margin-left: -2.4em; }
  /* citations print as plain parenthesised text, not the editor chip */
  #pg-print-root .mirror-cite { background: none; border: 0; padding: 0; box-shadow: none; color: #000; font-family: inherit; font-size: inherit; white-space: normal; }
  #pg-print-root .mirror-cite::before { content: "("; opacity: 1; margin: 0; }
  #pg-print-root .mirror-cite::after { content: ")"; }
  #pg-print-root .mirror-cite.numeric::before { content: "["; }
  #pg-print-root .mirror-cite.numeric::after { content: "]"; }
  #pg-print-root .mirror-edit-btn, #pg-print-root .mirror-table-edit { display: none !important; }
}

/* Focused editor for one block's LaTeX (table / figure / raw / caption), opened
   from the block's ✎ LaTeX button. Above the app's modals (z max 10001). Buttons
   re-assert colour + border on hover so the global `button:hover` accent cannot
   leak in (see docs/lessons.md, the apply-button incident). */
.mirror-textmodal-overlay { position: fixed; inset: 0; z-index: 10002; display: flex; align-items: center; justify-content: center; background: rgba(20,24,28,0.42); }
.mirror-textmodal { width: min(760px, 92vw); max-height: 84vh; display: flex; flex-direction: column; background: #fff; border-radius: 10px; box-shadow: 0 18px 50px rgba(0,0,0,0.3); overflow: hidden; }
.mirror-textmodal-head { padding: 14px 18px; font: 600 14px/1.3 system-ui, sans-serif; color: #1f2937; border-bottom: 1px solid #e5e7eb; }
/* Safety note above the raw-LaTeX editor: warn that the coloured commands are structural. */
.mirror-textmodal-note { padding: 10px 18px; font: 12px/1.5 system-ui, sans-serif; color: #7a5300; background: #fff7e6; border-bottom: 1px solid #f0e0b8; }
.mirror-textmodal-note b { color: #6a4800; }
.mirror-textmodal-note code { font-family: 'Menlo','Courier New',monospace; font-size: 11px; background: rgba(0,0,0,0.06); padding: 0 3px; border-radius: 3px; }
/* Host for the reused CodeMirror LaTeX editor (syntax highlighting). CM fills it (height:100%). */
.mirror-textmodal-cm { height: 50vh; min-height: 200px; overflow: hidden; }
.mirror-textmodal-field { flex: 1; min-height: 88px; margin: 0; padding: 14px 18px; border: 0; outline: none; resize: none; font: 13px/1.55 'Menlo','Courier New',monospace; color: #111827; background: #fff; overflow: auto; }
.mirror-textmodal:not(.mirror-textmodal-oneline) .mirror-textmodal-field { height: 52vh; white-space: pre; }
.mirror-textmodal-oneline .mirror-textmodal-field { min-height: 0; }
.mirror-textmodal-foot { display: flex; align-items: center; gap: 10px; padding: 12px 18px; border-top: 1px solid #e5e7eb; background: #f8fafc; }
.mirror-textmodal-hint { margin-right: auto; font: 11px system-ui, sans-serif; color: #8a9099; }
.mirror-textmodal-btn { font: 500 13px system-ui, sans-serif; padding: 6px 16px; border-radius: 6px; border: 1px solid #cfd4da; background: #fff; color: #374151; cursor: pointer; }
.mirror-textmodal-btn:hover { background: #f1f3f5; border-color: #cfd4da; color: #374151; }
.mirror-textmodal-save { background: #2e5c7a; border-color: #2e5c7a; color: #fff; }
.mirror-textmodal-save:hover { background: #24506b; border-color: #24506b; color: #fff; }

/* Remote collaborator cursors (y-prosemirror). The plugin's defaultCursorBuilder
   emits <span class="ProseMirror-yjs-cursor"><div>Name</div></span> and sets the
   awareness color inline (border-color + the label's background-color); it relies
   on the APP to shape the caret and float the name label. Without these rules the
   label is an unstyled full-width block, so a collaborator's cursor renders as a
   solid full-width bar across the line (the label's inline background painting the
   whole line). These rules give the caret a thin colored rule and turn the label
   into a small tag above it. Applies in both the brain view and the page-box
   projection (unscoped by design). See docs/lessons.md (2026-07-15). */
.ProseMirror-yjs-cursor {
  position: relative; margin-left: -1px; margin-right: -1px;
  border-left: 1px solid; border-right: 1px solid;
  word-break: normal; pointer-events: none;
}
.ProseMirror-yjs-cursor > div {
  position: absolute; top: -1.2em; left: -1px; z-index: 20;
  font: 600 11px/normal -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  font-style: normal; user-select: none; color: #fff; white-space: nowrap;
  padding: 1px 5px; border-radius: 3px 3px 3px 0;
}

/* Dragging an image file over the editor. The page does not accept a drop unless dragover is
   preventDefault'd (mirror-editor-pane.js); this is the visible half of that contract, so the
   writer can see the editor will take the file before letting go. Deliberately a frame on the
   scroll host rather than a caret at the drop point: a figure is a BLOCK, inserted at the
   boundary of the paragraph under the pointer, so a precise caret would promise a precision the
   insert does not have. */
.mirror-mode .mirror-wysiwyg.mirror-drop-active {
  outline: 2px dashed #2e5c7a;
  outline-offset: -4px;
  background-color: rgba(46, 92, 122, 0.04);
}
