/* =========================================================
   mbrd - the text editor (ui/editor/view.ts), inside the viewer.
   Laid out as Microsoft Word is: one ribbon of labelled groups
   across the top, with a gallery of styles and the close at its end,
   the page on a desk, and a status bar along the foot. Made of the
   board's materials - its paper and grain, its glass and corners
   (chrome.css, items.css) - so it is Word's plan in this app's hand.
   ========================================================= */

/* The whole window: writing wants the room. It ends above a phone's keyboard,
   whose height ui/viewer.ts writes into --kb. */
#viewer[data-edit] {
  --ed-inset: env(safe-area-inset-top, 0px);
  /* The ribbon, one band flush with the window's edges. A desk has no title
     row - the name is on the sheet - and a phone gives it one for its top bar. */
  --ed-title-h: 0px;
  --ed-close-w: 56px;
  --ed-ribbon-h: 96px;
  --ed-bar-top: var(--ed-inset);
  --ed-bar-bottom: calc(var(--ed-bar-top) + var(--ed-title-h) + var(--ed-ribbon-h));
  --ed-top: calc(var(--ed-bar-bottom) + 24px);
  --ed-status-h: 28px;
  width: 100%;
  height: calc(100dvh - var(--kb, 0px));
  margin: 0;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  background: var(--paper);
}
/* The head keeps only its close, as the ribbon's last cell: the right end of
   the band, a rule before it as between groups. The name is the sheet's. */
#viewer[data-edit] #viewer-head {
  position: absolute;
  z-index: 4;
  /* The whole band's height, so its rule runs from the window's top edge as
     the groups' do. */
  top: var(--ed-inset);
  right: env(safe-area-inset-right);
  width: var(--ed-close-w);
  height: var(--ed-ribbon-h);
  justify-content: center;
  /* Level with the groups' commands, which sit above their labels. */
  align-items: flex-start;
  padding: 20px 0 0;
  border: 0;
  border-left: 1px solid var(--rule);
  background: var(--paper-card);
  pointer-events: none;
}
#viewer[data-edit] #viewer-names { display: none; }
#viewer[data-edit] #viewer-close {
  width: 40px;
  height: 40px;
  pointer-events: auto;
}
/* The viewer's body gives up its grid and its padding: the editor lays out its own room. */
#viewer[data-edit] #viewer-body {
  display: flex;
  place-items: stretch;
  padding: 0;
  overflow: hidden;
  background: none;
}

.ed {
  position: relative;
  flex: 1 1 auto;
  min-width: 0;
  min-height: 0;
}

/* The board's paper grain: the same tile, blend and dial as #grain (base.css). */
.ed-grain {
  position: absolute;
  inset: 0;
  background-image: url("../img/paper-grain.webp");
  background-size: var(--grain-tile, 512px 512px);
  mix-blend-mode: multiply;
  opacity: calc(0.8 * var(--grain));
  pointer-events: none;
}
/* In the dark, turned over as base.css turns #grain. */
:root[data-scheme="dark"] .ed-grain {
  filter: invert(1);
  mix-blend-mode: screen;
  opacity: calc(0.6 * var(--grain));
}

/* ── The ribbon ─────────────────────────────────────────────────────────────
   Word's, without its tabs: every group in one row, each its commands and its
   name beneath them, a rule between groups. One band across the top of the
   window, edge to edge, in the board's card paper, the close at its end. */

.ed-bar {
  position: absolute;
  z-index: 3;
  top: var(--ed-bar-top);
  left: 0;
  right: 0;
  padding: var(--ed-title-h) env(safe-area-inset-right) 0 env(safe-area-inset-left);
  border-bottom: var(--hairline) solid var(--rule-2);
  background: var(--paper-card);
  box-shadow: var(--shadow-1);
  -webkit-user-select: none;
  user-select: none;
}
.ed-ribbon {
  height: var(--ed-ribbon-h);
  overflow: hidden;
}
.ed-panel {
  display: flex;
  align-items: stretch;
  height: 100%;
  /* The right end is the head's close (#viewer-head above). No room above:
     that is the groups' own (.ed-group), so the rules between them run from
     the window's top edge rather than stopping short of it. */
  padding: 0 var(--ed-close-w) 0 4px;
  /* Never scrolled: the ribbon folds to fit (below). What still does not fit
     at a text size far past the default is clipped rather than scrolled. */
  overflow: hidden;
}
.ed-group {
  flex: none;
  display: flex;
  flex-direction: column;
  padding: 6px 10px 0;
}
.ed-group + .ed-group { border-left: 1px solid var(--rule); }
.ed-group-body {
  flex: 1 1 auto;
  display: flex;
  align-items: center;
  gap: 4px;
}
.ed-group-label {
  flex: none;
  padding: 3px 0 6px;
  color: var(--ink-3);
  font-size: var(--t-tiny);
  text-align: center;
  white-space: nowrap;
}
/* Small commands stacked, as Word stacks Find over Replace. */
.ed-stack { display: flex; flex-direction: column; gap: 2px; }
.ed-stack .ed-btn { justify-content: flex-start; height: 28px; }
.ed-btn {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  min-width: 32px;
  height: 32px;
  padding: 0 8px;
  border: 0;
  border-radius: calc(var(--leaf) * 0.7);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: var(--t-small);
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.ed-find > * + * { border-left: 1px solid var(--rule); }
.ed-btn .ico { width: 17px; height: 17px; }
@media (hover: hover) {
  .ed-btn:hover:not(:disabled) { background: var(--paper-2); color: var(--ink); }
}
.ed-btn:active:not(:disabled) { background: var(--paper-3); }
.ed-btn:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; }
/* On: the accent's ink on a tint of it, as the board marks an armed tool - never a filled block. */
.ed-btn.is-active, .ed-btn[aria-pressed="true"] {
  color: var(--accent-deep);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.ed-btn:disabled { color: var(--ink-3); opacity: 0.6; cursor: default; }
.ed-bold { font-weight: 700; }
/* A serif at every whimsy, where --font-display can be the sans: an italic reads as one only in a serif. */
.ed-italic { font-family: var(--font-serif); font-style: italic; font-size: var(--t-body); }
.ed-strike { text-decoration: line-through; }
/* A highlighter's stroke under the letter, not a fill: a filled button reads as pressed. */
.ed-highlight {
  text-decoration: underline var(--highlight);
  text-decoration-thickness: 0.5em;
  text-underline-offset: -0.3em;
  text-decoration-skip-ink: none;
}
/* A large command, its glyph over its word, as Word draws the ones a group leads with. */
.ed-big {
  flex-direction: column;
  gap: 6px;
  min-width: 54px;
  height: 62px;
  padding: 6px 8px;
  font-size: var(--t-tiny);
}
.ed-big .ico { width: 22px; height: 22px; color: var(--accent-text); }
.ed-big:disabled .ico { color: var(--ink-3); }
/* More, in a gallery: a chevron turned down, since it opens a list. */
.ed-more .ico { order: 2; width: 11px; height: 11px; rotate: 90deg; }
/* The Style button that stands in for the gallery: a folded ribbon's and a phone's, not a wide desk's. */
.ed-compact { display: none; }
/* Where a phone's toolbar starts its second row. */
.ed-break { display: none; }

/* ── The ribbon folding (ui/editor/view.ts fold) ─────────────────────────────
   Each step adds its class to the ones before, until the ribbon fits. */

/* One: the gallery becomes a Style button - a field naming the line, whose chevron opens the list. */
.is-fold-1 .ed-gallery { display: none; }
.is-fold-1 .ed-compact { display: flex; }
.is-fold-1 .ed-style {
  justify-content: space-between;
  width: 112px;
  height: 36px;
  padding: 0 12px;
  border: var(--hairline) solid var(--rule-2);
  background: var(--paper);
  color: var(--ink);
}
.is-fold-1 .ed-style .ed-btn-word { overflow: hidden; text-overflow: ellipsis; }
/* Two: Vomit Mode is its one button - what it is moves into its list - and Super a glyph. */
.is-fold-2 .ed-info { display: none; }
.is-fold-2 .ed-super { flex-direction: row; min-width: 32px; height: 32px; padding: 0 8px; }
.is-fold-2 .ed-super .ed-btn-word { display: none; }
.is-fold-2 .ed-super .ico { width: 17px; height: 17px; }
/* Three: the small commands lose their words, and the view's two stack as Find and Replace do.
   Each keeps its name in its tooltip. */
.is-fold-3 :is(.ed-stack, .ed-show) .ed-btn-word { display: none; }
/* And the groups close up, so the narrowest desk still takes the lot (a phone's toolbar begins below it). */
.is-fold-3 .ed-group { padding: 6px 6px 0; }
.is-fold-3 .ed-stack .ed-btn { justify-content: center; }
.is-fold-3 .ed-show .ed-group-body { flex-direction: column; justify-content: center; gap: 2px; }
.is-fold-3 .ed-show .ed-btn { flex-direction: row; min-width: 32px; height: 28px; padding: 0 8px; }
.is-fold-3 .ed-show .ico { width: 17px; height: 17px; color: inherit; }

/* A gallery: Word's Styles, each tile a sample of the line it makes. */
.ed-tile {
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 92px;
  height: 58px;
  padding: 0 8px;
  overflow: hidden;
  border: var(--hairline) solid var(--rule-2);
  border-radius: calc(var(--leaf) * 0.7);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
}
.ed-tile-sample { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
@media (hover: hover) {
  .ed-tile:hover { border-color: var(--accent); }
}
.ed-tile:focus-visible { outline: 2px solid var(--accent); outline-offset: 1px; }
.ed-tile.is-active {
  border-color: var(--accent-deep);
  box-shadow: inset 0 0 0 1px var(--accent-deep);
  background: color-mix(in srgb, var(--accent) 8%, var(--paper-card));
}
.ed-tile[data-style="p"] { font-size: var(--t-small); }
.ed-tile[data-style^="h"] { font-family: var(--font-display); font-weight: 600; }
.ed-tile[data-style="h1"] { font-size: var(--t-body); }
.ed-tile[data-style="h2"] { font-size: var(--t-small); }
.ed-tile[data-style="h3"] { font-size: var(--t-small); color: var(--ink-2); }
.ed-tile[data-el] { width: 84px; font-family: 'Courier Prime', 'Courier New', Courier, var(--font-mono); font-size: var(--t-tiny); }
.ed-tile[data-el="scene"] { font-weight: 700; }

/* The Vomit Mode countdown, in the status bar, in figures that do not jitter. */
.ed-timer {
  color: var(--accent-deep);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.ed-timer:empty { display: none; }
/* Locked text fades back: still there to read, plainly not there to change.
   A highlight, painted over the page without a node added to it. */
::highlight(ed-locked) { color: var(--ink-3); }

/* ── Find and replace: a second pill, hung under the first ───────────────── */

.ed-find {
  position: absolute;
  z-index: 3;
  top: calc(var(--ed-bar-bottom) + 8px);
  right: max(16px, env(safe-area-inset-right));
  max-width: calc(100% - 32px);
  display: flex;
  align-items: stretch;
  height: var(--chrome-button-h);
  outline: var(--hairline) solid var(--rule-2);
  outline-offset: calc(-1 * var(--hairline));
  border-radius: var(--leaf);
  overflow: hidden;
  background: var(--paper-card);
  box-shadow: var(--shadow-1);
}
.ed-find[hidden] { display: none; }
.ed-find input {
  flex: 0 1 200px;
  min-width: 0;
  padding: 0 14px 1px;
  border: 0;
  background: none;
  color: var(--ink);
  font: inherit;
  font-size: var(--t-small);
  outline: none;
}
.ed-find input:focus { background: var(--paper-2); }
.ed-find-n {
  display: flex;
  align-items: center;
  min-width: 6.5em;
  padding: 0 12px 1px;
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: var(--t-tiny);
}
.ed-find-n:empty { min-width: 0; padding: 0; }

/* The Custom Highlight API: painted over the page without a node added to it.
   An engine without it still finds - it scrolls to each match - and paints nothing. */
::highlight(ed-find) { background-color: color-mix(in srgb, var(--accent) 30%, transparent); }
::highlight(ed-find-now) { background-color: var(--accent); color: var(--accent-fg); }

/* ── The outline: a glass panel down the left, as the board's sidebar is ─── */

.ed-outline {
  position: absolute;
  z-index: 2;
  top: var(--ed-top);
  left: max(16px, env(safe-area-inset-left));
  bottom: calc(var(--ed-status-h) + 16px);
  width: 250px;
  padding: 8px;
  overflow: auto;
  overscroll-behavior: contain;
  outline: var(--hairline) solid var(--rule-2);
  outline-offset: calc(-1 * var(--hairline));
  border-radius: var(--radius);
  background: var(--paper-card);
  box-shadow: var(--shadow-2);
}
.ed-outline[hidden] { display: none; }
.ed-ol-item {
  display: block;
  width: 100%;
  padding: 7px 10px 8px calc(10px + (var(--level, 1) - 1) * 14px);
  border: 0;
  border-radius: var(--leaf);
  background: none;
  color: var(--ink-2);
  font: inherit;
  font-size: var(--t-small);
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}
.ed-ol-item[data-kind="section"], .ed-ol-item[data-kind="h"][data-level="1"] { font-family: var(--font-display); font-weight: 600; color: var(--ink); }
@media (hover: hover) {
  .ed-ol-item:hover { background: var(--paper-2); color: var(--accent-deep); }
}
.ed-ol-item:focus-visible { outline: none; background: var(--paper-2); color: var(--accent-deep); }
.ed-ol-item.is-here { color: var(--accent-deep); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.ed-ol-empty { margin: 0; padding: 7px 10px; color: var(--ink-3); font-size: var(--t-small); }

/* ── The status bar: along the foot, as Word's ───────────────────────────── */

.ed-status {
  position: absolute;
  z-index: 3;
  left: 0;
  right: 0;
  bottom: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  height: calc(var(--ed-status-h) + env(safe-area-inset-bottom));
  padding: 0 max(18px, env(safe-area-inset-right)) env(safe-area-inset-bottom) max(18px, env(safe-area-inset-left));
  border-top: var(--hairline) solid var(--rule-2);
  background: var(--paper-card);
  color: var(--ink-2);
  font-size: var(--t-tiny);
  -webkit-user-select: none;
  user-select: none;
}
.ed-counts { display: flex; gap: 12px; }
.ed-status-end { display: flex; align-items: center; gap: 12px; }
/* Page zoom: out, the level (which puts it back to 100%), in. */
.ed-zoom { display: flex; align-items: center; }
.ed-zoom .ed-btn { min-width: 26px; height: 24px; padding: 0 4px; }
.ed-zoom .ed-btn .ico { width: 14px; height: 14px; }
.ed-zoom .ed-zoom-level {
  min-width: 4.2em;
  font: inherit;
  font-variant-numeric: tabular-nums;
  justify-content: center;
}
.ed-count { white-space: nowrap; font-variant-numeric: tabular-nums; }

/* ── The desk and the page ──────────────────────────────────────────────── */

/* The desk scrolls under the floating controls, as the board moves under its
   glass; the room below the page keeps the last line off the bottom edge. */
.ed-scroll {
  position: absolute;
  inset: 0 0 var(--ed-status-h);
  overflow: auto;
  overscroll-behavior: contain;
  padding: var(--ed-top) 24px 30vh;
  /* The scrollbar's room kept from the start, on both sides so the sheet stays
     centred: a bar that arrives - as the document grows, or when the opening
     rise lets go of the scroll (ui/viewer.ts) - would narrow the desk and jolt
     the sheet sideways. */
  scrollbar-gutter: stable both-edges;
}
.is-finding .ed-scroll { padding-top: calc(var(--ed-top) + var(--chrome-button-h) + 8px); }
/* A preview (LaTeX's): the source on the left half, the page it makes on the
   right, each scrolling on its own. */
.has-preview .ed-scroll { right: 50%; }
.ed-preview {
  position: absolute;
  top: 0;
  right: 0;
  bottom: var(--ed-status-h);
  width: 50%;
  overflow: auto;
  overscroll-behavior: contain;
  padding: var(--ed-top) 24px 30vh;
  border-left: var(--hairline) solid var(--rule-2);
  scrollbar-gutter: stable;
}
.ed-preview[hidden] { display: none; }
.ed-preview-page {
  box-sizing: border-box;
  max-width: calc(680px * var(--ed-zoom, 1));
  min-height: calc(880px * var(--ed-zoom, 1));
  margin: 0 auto;
  padding: calc(clamp(24px, 4vw, 56px) * var(--ed-zoom, 1));
  background: var(--paper-card);
  box-shadow: inset 0 0 0 var(--hairline) var(--rule-2), var(--shadow-2);
  font-size: calc(var(--t-body) * var(--ed-zoom, 1));
}
/* An open outline takes its side, and the page centres in what is left. */
.has-outline .ed-scroll { padding-left: calc(max(16px, env(safe-area-inset-left)) + 250px + 24px); }

/* The sheet: a card of the board's, picked up - its paper, its hairline ring,
   and the lifted shadow every raised thing here wears. Letter's proportions,
   smaller than 96 dpi, one page tall at least and growing with the text. It
   holds the document's name at its head and the page under it. */
.ed-sheet {
  box-sizing: border-box;
  display: flex;
  flex-direction: column;
  width: 100%;
  /* Page zoom (--ed-zoom, the status bar's): the paper grows with its writing,
     until the desk is full and the lines wrap shorter instead. */
  max-width: calc(680px * var(--ed-zoom, 1));
  min-height: calc(880px * var(--ed-zoom, 1));
  margin: 0 auto;
  padding: calc(clamp(24px, 8vw, 72px) * var(--ed-zoom, 1));
  /* A sheet of paper is cut square at every whimsy, whatever the furniture's corners. */
  border-radius: 0;
  background: var(--paper-card);
  box-shadow: inset 0 0 0 var(--hairline) var(--rule-2), var(--shadow-2);
  cursor: text;
}
/* The name, as the title of the sheet: the display face, a rule under it, no box. */
.ed-name {
  flex: none;
  display: block;
  box-sizing: border-box;
  width: 100%;
  /* A long name wraps; the field grows to it (ui/editor/view.ts fitName). */
  field-sizing: content;
  resize: none;
  overflow: hidden;
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  margin: 0 0 1.2em;
  padding: 0 0 0.35em;
  border: 0;
  border-bottom: var(--hairline) solid var(--rule-2);
  border-radius: 0;
  background: none;
  color: var(--ink);
  font-family: var(--font-display);
  font-size: calc(var(--t-body) * 1.9 * var(--ed-zoom, 1));
  font-weight: 600;
  line-height: 1.2;
  outline: none;
}
.ed-name::placeholder { color: var(--ink-3); }
.ed-name:focus { border-bottom-color: var(--accent); }
.ed-name[hidden] { display: none; }
/* The page: the writing, filling the sheet under the name. */
.ed-page {
  flex: 1 0 auto;
  outline: none;
  color: var(--ink);
  caret-color: var(--accent-deep);
  font-size: calc(var(--t-body) * var(--ed-zoom, 1));
  line-height: 1.65;
  /* A soft line break is a newline in a run, and spaces are the writer's. */
  white-space: pre-wrap;
  overflow-wrap: break-word;
}
.is-plain .ed-page {
  font-family: var(--font-mono);
  font-size: calc(var(--t-small) * var(--ed-zoom, 1));
  line-height: 1.6;
}


/* A phone: the same editor, laid out for a thumb, and all of it at the top -
   the foot is where the keyboard comes up. A bar with the close and the
   counts; under it every command in two rows of glyphs; then the page on the
   desk, as on a desk. */
@media (max-width: 700px) {
  #viewer[data-edit] {
    --ed-title-h: 48px;
    --ed-ribbon-h: 96px;
    --ed-bar-top: calc(var(--ed-inset) + var(--ed-title-h));
    --ed-bar-bottom: calc(var(--ed-bar-top) + var(--ed-ribbon-h));
    --ed-top: calc(var(--ed-bar-bottom) + 16px);
  }
  /* The top bar: the status bar moved up - the counts, and a session's time -
     with the head's close over its right end, a thumb's size. */
  #viewer[data-edit] #viewer-head {
    top: var(--ed-inset);
    right: max(0px, calc(env(safe-area-inset-right) - 4px));
    width: 52px;
    height: var(--ed-title-h);
    align-items: center;
    padding: 0;
    border-left: 0;
    background: none;
  }
  #viewer[data-edit] #viewer-close { width: 48px; height: 48px; }
  .ed-status {
    top: 0;
    bottom: auto;
    height: calc(var(--ed-inset) + var(--ed-title-h));
    padding: var(--ed-inset) 56px 0 max(16px, env(safe-area-inset-left));
    border-top: 0;
    border-bottom: var(--hairline) solid var(--rule);
  }
  .ed-counts { gap: 12px; }
  /* The band under the top bar, edge to edge, carrying the pair's shadow. */
  .ed-bar { padding-top: 0; }
  .ed-ribbon { height: auto; }
  /* Every command in two rows, with no sideways scroll, each a thumb's target.
     The ribbon's groups stay together, ruled apart as on the desk, their
     names left to the desk: the first row is the writing - undo, the marks,
     the lists; the second the line's style, find, a session and the view
     (ui/editor/view.ts puts in the break). A screenplay breaks before its
     session, and plain text, with less, keeps to one row. */
  .ed-panel {
    display: flex;
    flex-wrap: wrap;
    align-content: flex-start;
    height: var(--ed-ribbon-h);
    padding: 2px 6px;
    overflow: visible;
  }
  /* The break is also the rule between the rows, edge to edge. */
  .ed-panel .ed-break {
    display: block;
    flex-basis: calc(100% + 12px);
    height: 1px;
    margin: 1px -6px 2px;
    background: var(--rule);
  }
  .ed-panel .ed-group {
    display: flex;
    flex: 1 1 auto;
    flex-direction: row;
    min-width: 0;
    padding: 0 4px;
    border-left: 1px solid var(--rule);
  }
  /* A rule between groups, as the desk's ribbon has, and none at a row's start. */
  .ed-panel .ed-group:first-child, .ed-panel .ed-break + .ed-group { border-left: 0; }
  :is(.ed-group-body, .ed-stack) { display: contents; }
  :is(.ed-group-label, .ed-desk), .ed-btn[hidden], .ed-panel .ed-gallery { display: none; }
  .ed-panel .ed-btn { flex: 1 1 0; justify-content: center; min-width: 34px; height: 44px; padding: 0 4px; }
  .ed-panel .ed-big { flex-direction: row; min-width: 34px; height: 44px; padding: 0 4px; }
  .ed-panel .ed-btn .ico { width: 19px; height: 19px; }
  /* Glyphs alone; Style keeps its word, which names the line. */
  .ed-panel .ed-btn:not(.ed-style) .ed-btn-word { display: none; }
  /* The style takes what its row leaves, so its word is read whole. */
  .ed-panel .ed-compact { flex-grow: 3; }
  .ed-panel .ed-style { flex: 1 1 104px; justify-content: space-between; gap: 4px; padding: 0 10px 0 12px; color: var(--ink); }
  .ed-panel .ed-style .ico { width: 11px; height: 11px; }
  .ed-panel .ed-style .ed-btn-word { overflow: hidden; text-overflow: ellipsis; }
  /* Plain text keeps to one row: the bar and the page close up to it. */
  .ed.is-plain {
    --ed-ribbon-h: 52px;
    --ed-bar-bottom: calc(var(--ed-bar-top) + var(--ed-ribbon-h));
    --ed-top: calc(var(--ed-bar-bottom) + 16px);
  }
  /* Find: two rows - what to find and the way through it, then what to put
     in its place - each field wide enough to read what is in it. */
  .ed-find {
    left: 8px;
    right: 8px;
    max-width: none;
    display: grid;
    grid-template-columns: 1fr auto 44px 44px 44px;
    grid-template-areas: "q n p x s" "r r o o a";
    height: auto;
  }
  .ed-find > * + * { border-left: 0; }
  .ed-find > * { height: 44px; }
  .ed-find-q { grid-area: q; }
  .ed-find-n { grid-area: n; }
  .ed-find-prev { grid-area: p; }
  .ed-find-next { grid-area: x; }
  .ed-find-shut { grid-area: s; }
  .ed-find-r { grid-area: r; border-top: 1px solid var(--rule); }
  .ed-find-one { grid-area: o; border-top: 1px solid var(--rule); }
  .ed-find-all { grid-area: a; border-top: 1px solid var(--rule); }
  .ed-outline {
    left: 8px;
    right: 8px;
    width: auto;
    bottom: 8px;
    z-index: 4;
  }
  /* The page on the desk: the paper runs to both edges of the screen, the
     desk showing above it, with room under it to write the last line clear
     of the keyboard. Find, open, pushes the page down under it. */
  .ed-scroll, .has-outline .ed-scroll {
    inset: 0;
    padding: var(--ed-top) 0 30vh;
    scrollbar-gutter: auto;
  }
  .is-finding .ed-scroll { inset: 0; padding: calc(var(--ed-top) + 88px + 8px) 0 30vh; scrollbar-gutter: auto; }
  /* No room for both: the preview, pressed, takes the screen, and pressed again gives the source back. */
  .has-preview .ed-scroll { display: none; }
  .ed-preview { inset: 0; width: auto; padding: var(--ed-top) 0 30vh; border-left: 0; }
  .ed-preview-page { min-height: 0; padding: 22px 20px 48px; }
  /* Edge to edge, a ring on the sides would be a line down each edge of the screen. */
  .ed-sheet { box-shadow: 0 var(--hairline) 0 var(--rule-2), 0 calc(-1 * var(--hairline)) 0 var(--rule-2), var(--shadow-2); }
  .ed-sheet {
    /* At least to the foot of the window: a short note still reads as a page. */
    min-height: calc(100dvh - var(--kb, 0px) - var(--ed-top) - 16px);
    padding: 22px 20px 48px;
  }
  .ed-name { font-size: calc(var(--t-body) * 1.55 * var(--ed-zoom, 1)); }
}

/* ── What is on the page ────────────────────────────────────────────────── */

.ed-page > .ed-b { margin: 0 0 0.9em; }
.is-plain .ed-page > .ed-b { margin: 0; }

.ed-page > :is(h1, h2, h3, h4, h5, h6) {
  margin: 1.4em 0 0.5em;
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.25;
}
.ed-page > :first-child { margin-top: 0; }
.ed-page > h1 { font-size: 1.7em; }
.ed-page > h2 { font-size: 1.35em; }
.ed-page > h3 { font-size: 1.15em; }
.ed-page > h4 { font-size: 1.05em; }
.ed-page > h5 { font-size: 1em; }
.ed-page > h6 { font-size: 1em; color: var(--ink-2); }
.ed-page mark { padding: 0 0.1em; background: var(--highlight); color: var(--highlight-ink); }
.ed-page > blockquote {
  padding: 0.1em 0 0.1em 1em;
  border-left: 3px solid var(--rule);
  color: var(--ink-2);
}
.ed-page code {
  padding: 0.12em 0.35em;
  border-radius: var(--radius-xs);
  background: var(--paper-3);
  font-family: var(--font-mono);
  font-size: 0.88em;
}
.ed-page .ed-link {
  color: var(--accent-deep);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.15em;
}
.ed-page > .ed-code {
  padding: 12px 14px;
  border-radius: var(--leaf);
  background: var(--paper-3);
  font-family: var(--font-mono);
  font-size: 0.88em;
  line-height: 1.55;
  /* Code does not wrap; it scrolls in its own box. */
  white-space: pre;
  overflow-x: auto;
}
.ed-page > .ed-rule hr {
  margin: 0.4em 0;
  border: 0;
  border-top: var(--hairline) solid var(--rule-2);
}

/* ── A screenplay ──────────────────────────────────────────────────────────
   The standard page: Courier, single-spaced, a wider left margin for the
   binding, and each element at its place across a line of sixty characters -
   which is why the indents are in ch. A blank line above is data-gap. */
.is-screen .ed-sheet { padding-left: calc(clamp(24px, 10vw, 104px) * var(--ed-zoom, 1)); }
.is-screen .ed-page {
  font-family: 'Courier Prime', 'Courier New', Courier, var(--font-mono);
  line-height: 1.25;
}
/* Top and bottom only: the sides are each element's indent, below. */
.is-screen .ed-page > .ed-b { margin-top: 0; margin-bottom: 0; }
.ed-page > .ed-sp[data-gap] { margin-top: 1.25em; }
.ed-page > .ed-sp:first-child { margin-top: 0; }
.ed-sp[data-el="scene"] { font-weight: 700; text-transform: uppercase; }
.ed-sp[data-el="character"] { margin-left: 22ch; text-transform: uppercase; }
.ed-sp[data-el="character"][data-dual]::after { content: '  ^'; color: var(--ink-3); }
.ed-sp[data-el="paren"] { margin-left: 16ch; max-width: 26ch; }
.ed-sp[data-el="dialogue"] { margin-left: 10ch; max-width: 36ch; }
.ed-sp[data-el="transition"] { text-align: right; text-transform: uppercase; }
.ed-sp[data-el="centered"] { text-align: center; }
.ed-sp[data-el="lyric"] { margin-left: 10ch; font-style: italic; }
/* What is not printed - sections, synopses, notes - reads as the writer's own marks. */
.ed-sp[data-el="section"] { color: var(--ink-3); font-family: var(--font-display); font-weight: 600; }
.ed-sp[data-el="synopsis"] { color: var(--ink-3); font-style: italic; }
.ed-sp[data-el="note"] {
  padding: 0 0.3em;
  border-left: 3px solid var(--accent);
  color: var(--ink-2);
}
/* A phone's line is half a page's: the speech indents close up. */
@media (max-width: 600px) {
  .ed-sp[data-el="character"] { margin-left: 10ch; }
  .ed-sp[data-el="paren"] { margin-left: 6ch; }
  .ed-sp[data-el="dialogue"] { margin-left: 3ch; }
  .ed-sp[data-el="lyric"] { margin-left: 3ch; }
}

/* What the editor does not model, shown as the source it is and kept as it
   was written: muted, monospaced, and not editable. */
.ed-page > .ed-raw {
  padding: 10px 12px;
  border: var(--hairline) dashed var(--rule);
  border-radius: var(--leaf);
  background: var(--paper-2);
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: 0.82em;
  line-height: 1.5;
  white-space: pre-wrap;
  cursor: default;
}
.ed-page .ed-raw-run {
  color: var(--ink-3);
  font-family: var(--font-mono);
  font-size: 0.85em;
}

/* Lists: one element per item, its level in --depth, its mark drawn beside it. */
.ed-page > .ed-li {
  position: relative;
  margin: 0 0 0.25em;
  padding-left: calc(1.7em * (var(--depth, 0) + 1));
}
.ed-page > .ed-li + :not(.ed-li) { margin-top: 0.9em; }
.ed-page > .ed-li::before {
  position: absolute;
  left: calc(1.7em * var(--depth, 0));
  width: 1.4em;
  color: var(--ink-3);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.ed-page > .ed-li[data-list="bullet"]::before { content: '•'; text-align: center; }
.ed-page > .ed-li[data-list="number"]::before { content: attr(data-n); }
.ed-page > .ed-li[data-checked] { color: var(--ink-3); }
.ed-box {
  position: absolute;
  top: 0.38em;
  left: calc(1.7em * var(--depth, 0) + 0.2em);
  width: 0.95em;
  height: 0.95em;
  box-sizing: border-box;
  border: 1.5px solid var(--ink-3);
  border-radius: var(--radius-xs);
  cursor: pointer;
}
.ed-li[data-checked] .ed-box {
  border-color: var(--accent);
  background: var(--accent);
}
/* The tick, drawn with two borders so it needs no icon and no text in the box. */
.ed-li[data-checked] .ed-box::after {
  content: '';
  position: absolute;
  left: 28%;
  top: 8%;
  width: 30%;
  height: 58%;
  border: solid var(--accent-fg);
  border-width: 0 2px 2px 0;
  transform: rotate(45deg);
}

/* ── A sticky growing into a document ──────────────────────────────────── */

/* The note, flying to the sheet and turning to paper on the way; ui/viewer.ts
   growFrom() places it over the sheet, animates it and takes it away. */
.viewer-grow {
  position: absolute;
  z-index: 2;
  background: var(--note-1);
  box-shadow: var(--shadow-1);
  pointer-events: none;
}
/* Unseen while it waits for the sheet to grow into (viewer.ts arrive()). */
#viewer.is-arriving { opacity: 0; }
/* No dimmed board behind a viewing that fills the window: the board shows
   only while a sticky grows, and there it should be seen as it is. */
#viewer[data-edit]::backdrop {
  background: none;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
}

/* The field that holds typing while a sticky becomes its document (ui/viewer.ts
   holdTyping). Focusable, so it is not display:none, and seen by nobody. */
.viewer-hold {
  position: fixed;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
  resize: none;
}

/* color-mix() fallback for WebKit < 16.2 — see tokens.css section 7. */
@supports not (color: color-mix(in srgb, red, blue)) {
  .ed-btn.is-active, .ed-btn[aria-pressed="true"] { background: rgb(var(--accent-c) / 12%); }
  .ed-ol-item.is-here { background: rgb(var(--accent-c) / 10%); }
  ::highlight(ed-find) { background-color: rgb(var(--accent-c) / 30%); }
}
