/* Draft pages, cover, account and profile search. */
:root {
  /* Inset the desktop reading and admin title axes together. The plus ends at
     x=34px; the number begins at x=59px, leaving the same 25px glyph gap as the
     three-space number/date gutter. The text column stays at x=388px. */
  --index-inset: 11px;
}

/* red caret and red-tinted selection, draft mode only */
.editable {
  caret-color: var(--palette-caret, #dc143c);
  cursor: text;
}
.editable:focus {
  outline: none;
}
:root ::selection {
  background: var(--palette-selection, #dc143c);
  color: var(--palette-selection-ink, #000000);
} /* full crimson, it bleeds */

/* editable title: ghost placeholder when empty */
span.story-title.editable:empty::before {
  content: attr(data-ph);
  color: var(--hairline);
}

/* editable body: an empty paragraph keeps its line only while the caret is inside it;
   every other empty line stays collapsed, so clicking into the text never opens
   gaps between the paragraphs */
.story-text.editable {
  min-height: calc(var(--lh) * 1em);
}
.story-text.editable > :is(p, div):empty[data-focus] {
  min-height: calc(var(--lh) * 1em);
}

/* draft heads don't fold; the stack under the title is the piece's version history */
.draft-story .story-head {
  cursor: default;
}
.draft-story .story-head:hover .story-title {
  color: var(--dim);
}
.draft-story .story-title:hover,
.draft-story .story-title:focus {
  color: var(--ink);
}
.version-stack {
  display: block;
  margin-top: 4px;
}
.story-when.version {
  display: block;
  background: none;
  border: 0;
  padding: 0;
  margin: 0; /* the stack already sits 4px under the title, exactly where the reading date sits */
  cursor: pointer;
  text-align: left;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  line-height: inherit; /* buttons don't inherit it on their own; the head's 1.42 is what reading uses */
  letter-spacing: 0.04em;
  color: var(--dim);
}
.story-when.version:hover {
  color: var(--ink);
}
.story-when.version.current {
  color: var(--dim);
} /* same grey as the reading date */
.draft-story.open .story-when.version:not(.current) {
  color: var(--hairline);
}
.draft-story.open .story-when.version:not(.current):hover {
  color: var(--ink);
}
.version-add {
  position: relative;
  display: block;
  width: 34px;
  height: 34px;
  margin-left: calc(1ch + 0.04em);
  margin-top: 4px;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  color: transparent;
  opacity: 0;
  pointer-events: none;
  transition: opacity 220ms ease;
}
.version-add::before,
.version-add::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  opacity: 0;
  transition: opacity 180ms ease;
}
.version-add::before {
  left: 0;
  top: 17px;
  width: 34px;
  height: 1px;
}
.version-add::after {
  left: 17px;
  top: 0;
  width: 1px;
  height: 34px;
}
/* The page's hairline plus reveals only when this version row is approached. */
.vrow.add:hover .version-add,
.vrow.add:focus-within .version-add,
.version-add.touch-revealed,
.version-add:focus-visible {
  opacity: 1;
  pointer-events: auto;
}
.version-add.reveal-h-first::before,
.version-add.reveal-v-first::after {
  opacity: 1;
  transition-delay: 0ms;
}
.version-add.reveal-h-first::after,
.version-add.reveal-v-first::before {
  opacity: 1;
  transition-delay: 150ms;
}
.version-add.reveal-h-first:hover::before,
.version-add.reveal-h-first:hover::after,
.version-add.reveal-v-first:hover::before,
.version-add.reveal-v-first:hover::after,
.version-add:focus-visible::before,
.version-add:focus-visible::after {
  background: var(--ink);
}
.version-add:focus-visible {
  outline: none;
}
@media (prefers-reduced-motion: reduce) {
  .version-add,
  .version-add::before,
  .version-add::after { transition-duration: 0s; transition-delay: 0s; }
}
.draft-remove {
  position: absolute;
  top: calc((0.817 + (var(--lh) - 1) / 2) * var(--fs) - 1.2 * var(--fs-mono));
  right: 0;
  background: none;
  border: 0;
  padding: 2px 0 2px 8px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  color: var(--hairline);
}
.draft-remove:hover,
.draft-remove:focus-visible {
  color: var(--ink);
  outline: none;
}

/* export/import overlay */
.io-overlay {
  position: fixed;
  inset: 0;
  background: var(--palette-extra-rgba-0-0-0-0-72, rgba(0, 0, 0, 0.72));
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 40;
}
.io-panel {
  width: min(620px, 86vw);
  background: var(--bg);
  border: 1px solid var(--hairline);
  padding: 18px;
  box-sizing: border-box;
}
.io-title {
  margin: 0 0 4px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  color: var(--ink);
}
.io-note {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 8.5pt;
  letter-spacing: 0.04em;
  color: var(--dim);
}
.io-panel textarea {
  width: 100%;
  height: 280px;
  box-sizing: border-box;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--hairline);
  padding: 10px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 8.5pt;
  line-height: 1.5;
  resize: vertical;
  caret-color: var(--palette-caret, #dc143c);
}
.io-panel textarea:focus {
  outline: none;
  border-color: var(--dim);
}
.io-error {
  margin: 8px 0 0;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 8.5pt;
  color: var(--palette-extra-e5484d, #e5484d);
}
.io-row {
  display: flex;
  gap: 10px;
  margin-top: 12px;
  justify-content: flex-end;
}
.io-row button {
  background: transparent;
  border: 1px solid var(--hairline);
  border-radius: 15px;
  padding: 6px 14px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 8.5pt;
  letter-spacing: 0.04em;
  color: var(--dim);
}
.io-row button:hover,
.io-row button:focus-visible {
  color: var(--ink);
  border-color: var(--ink);
  outline: none;
}

/* toggled modes glow like a pressed key */
.controls button.on {
  color: var(--ink);
  border-color: var(--ink);
}
/* draft text keeps every space and line exactly as typed */
.story-text.editable,
.story-text.editable p,
.story-text.editable > div {
  white-space: pre-wrap;
}
/* a typed Tab is a real tab character; four spaces wide reads as an indent, not a gap */
.story-text {
  tab-size: 4;
}
/* commitment mode: what was deleted stays, struck and leaning */
s.ov {
  font-style: italic;
  text-decoration: line-through;
  text-decoration-thickness: 1px;
  text-decoration-color: currentColor;
  color: var(--dim);
}
/* focus dim: while writing, every paragraph but the caret's own fades to a whisper, and so do
   titles and the other pieces; the page comes back the moment the caret leaves the text */
:root.focusdim .story-text.editable > *,
:root.focusdim .story-head,
:root.focusdim .story-audio {
  transition: opacity 0.35s ease;
}
:root.focusdim.focus-in .story-text.editable > *:not([data-focus]),
:root.focusdim.focus-in .story-head,
:root.focusdim.focus-in .story-audio {
  opacity: 0.18;
}

:root.platen .page {
  padding-bottom: 70vh;
}
/* folding a draft folds its version dates with the rest; the current date stays, like the reading index */
.vrow {
  position: relative; /* the shelf number hangs off the current row's date line */
  display: grid;
  grid-template-rows: 1fr;
  opacity: 1;
  /* the row's strut is the date font's, not the body's: a body-size strut was the empty line */
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  transition:
    grid-template-rows 0.55s ease,
    opacity 0.55s ease,
    margin-top 0.55s ease;
}
/* the version dates keep the head's own rhythm: the pitch between rows equals the pitch
   between the title line and the first date line */
.version-stack .vrow + .vrow {
  margin-top: 4px;
}
.vrow-inner {
  overflow: hidden;
  min-height: 0;
}
/* the shelf row's fixed gutter: six mono slots (three digits, three spaces) measured in the
   date font, so a proportional title font can never move the text column. The fold middot
   rides the second slot on the title line; the piece number leads the current date line. */
.gutter {
  position: relative;
  display: inline-block;
  width: calc(6 * (1ch + 0.04em));
  white-space: nowrap;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  color: var(--dim);
}
/* the middot sits over the number's second digit: one slot in, one slot wide, centered */
.story-head .fold-dot {
  left: calc(1ch + 0.04em);
  top: 0;
  width: 1ch;
  height: 100%;
  padding: 0;
  justify-content: center;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
}
/* the draft title leads its head-main block, the same first line reading sets */
.draft-story .story-title {
  display: block;
}
/* the date line leads with its own number gutter: pull it back to the row's left edge, so the
   number sits under the fold middot's slot and the date keeps the shared text column. Direct
   child only: the draft's version rows hang inside the version stack, which pulls itself. */
.story-head-main > .story-when {
  margin-left: calc(-6 * (1ch + 0.04em));
}
/* the draft's version stack leads with the same number gutter: pull it back the same six slots.
   The mono metrics come along so the ch in the pull is the date font's, not the title's. */
.story-head-main .version-stack {
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  margin-left: calc(-6 * (1ch + 0.04em));
}
/* a span head-main keeps the reading geometry but not the button's pointer */
.draft-story .story-head-main {
  cursor: default;
}
/* reading: the head's main button rides beside its gutter, tops level so the baselines meet */
.story-head .gutter,
.story-head-main {
  vertical-align: top;
}
.story-head-main {
  display: inline-block;
}
/* inside a version row the number shares the date's baseline, the same flow reading sets
   (the head-wide top alignment is for the title line's gutter, not the date rows) */
.vrow-inner .gutter {
  vertical-align: baseline;
}
/* a version date shares its line with its gutter */
.vrow-inner .story-when.version {
  display: inline-block;
}
.draft-story:not(.open) .vrow:not(.current) {
  grid-template-rows: 0fr;
  opacity: 0;
  margin-top: 0;
}
.draft-story:not(.open) .vrow:not(.current) button {
  pointer-events: none;
}
.version-stack {
  margin-top: 4px;
}
.vrow.add {
  display: block;
  height: 34px;
  overflow: visible;
  position: relative;
}
.vrow.add .vrow-inner {
  height: 34px;
  overflow: visible;
  position: absolute;
  inset: 0 auto auto 0;
  width: max-content;
}
.vrow.add .version-add {
  margin-top: 0;
}

/* ---- main page (Cover): one column, centered across, on the horizon - the folders, then + for a new one ---- */
.cover {
  /* on the horizon: the first folder's baseline is the baseline of a folder's first line of text.
       The page starts at the pin line; a piece's first line sits there on a wide screen, so no offset.
       On a phone the piece's head (title + date, then 16px) comes first - see the media rule below. */
  margin-top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
/* Pinned logo keeps the button's top edge and sits beside the top of the rail. */
.logo:not(.logo-roaming) {
  position: fixed;
  right: calc(14px + 34px + 8px);
  top: 12px; /* the word's baseline (y 34) sits on the index line, the button centre (y 33) beside it */
  height: 34px;
  display: flex;
  align-items: center;
  z-index: 11;
  pointer-events: none;
}
@media (max-width: 700px) {
  .logo:not(.logo-roaming) {
    right: calc(8px + 34px + 8px);
  }
}
/* The button is draggable: once it has been moved the pinned logo travels with it and stays on its left,
   on the button's row (--lb-left / --lb-top are the button's own left and top, set while dragging). */
:root.lb-moved .logo:not(.logo-roaming) {
  right: calc(100vw - var(--lb-left) + 8px);
  top: calc(var(--lb-top) - 4px);
}
/* The roaming mark stays beneath the UI, but above the body background. */
.logo.logo-roaming {
  position: fixed;
  left: 4px;
  top: 4px;
  z-index: -1;
  pointer-events: none;
}
.logo {
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  line-height: var(--lh);
  white-space: pre;
}
/* The pulled mark stands where a rail label would stand, without covering the button. */
.logo.logo-pulled {
  z-index: 11;
  transform: none;
}
.logo-mode-dots {
  display: inline-flex;
  align-items: center;
  gap: 0.32em;
  font-family: var(--font-mono);
  font-size: 13px;
  white-space: nowrap;
}
.logo-mode-eye {
  display: inline-block;
  transition:
    opacity var(--blink-ease, 200ms) ease-in-out,
    transform var(--blink-ease, 200ms) ease-in-out;
}
.controls .logo-mode-button {
  position: fixed;
  right: 14px;
  top: 16px; /* centred on the line that carries the index middot (y 33) */
  border: 0;
  user-select: none;
  -webkit-user-select: none;
}
@media (max-width: 700px) {
  .controls .logo-mode-button {
    right: 8px;
  }
}
.logo-mode-eye.blink-shut {
  opacity: 0.12;
  transform: scaleY(0.18);
}
@media (prefers-reduced-motion: reduce) {
  .logo-mode-eye {
    transition: none;
  }
}
.logo-shy .logo-word {
  text-shadow:
    0 0 0.35em var(--ink),
    0 0 0.8em var(--ink);
  color: var(--ink);
}
.logo-shy .logo-caret {
  box-shadow:
    0 0 0.35em var(--ink),
    0 0 0.8em var(--ink);
  background: var(--ink);
}
.logo-word {
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  line-height: 1;
  letter-spacing: 0.04em;
  color: var(--dim);
}
.logo-caret {
  display: inline-block;
  width: 1px;
  height: 1.05em;
  margin-left: 1px;
  vertical-align: -0.18em;
  background: var(--palette-accent, #dc143c);
}
.logo-sel {
  background: var(--hairline);
  color: var(--ink);
}
/* the caret standard (a24): crimson, a slow smooth blink at rest. The plus word in admin.css uses the same
   keyframe. Under reduced motion no caret shows. */
.logo-caret.rest {
  animation: caret-blink 1.2s ease-in-out infinite;
}
@keyframes caret-blink {
  0%, 45% { opacity: 1; }
  55%, 95% { opacity: 0; }
  100% { opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  .logo-caret {
    display: none;
  }
}
/* the logo mounts as an empty slot in the flow: the mark itself is pinned to the top rail
   (see .logo), so the slot takes no space and the title area keeps the horizon */
.cover-folders {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
}
.cover-folder {
  background: none;
  border: 0;
  padding: 0;
  line-height: var(--lh); /* same line box as the text, so the baselines meet */
  color: var(--dim);
  font: inherit;
  font-size: var(--fs);
  cursor: pointer;
  transition: color 0.35s ease;
}
.cover-folder:hover,
.cover-folder:focus-visible {
  color: var(--ink);
  outline: none;
}
/* the count hangs off the title's right edge (out of the flow), so the title alone is centered;
   raised like a superscript, set in oldstyle figures */
.cover-folder-count {
  position: absolute;
  left: 100%;
  top: calc(
    (var(--lh) - 1) / 2 * var(--fs) + 0.06 * var(--fs)
  ); /* half-leading, then just under the cap line */
  margin-left: 0.3em;
  font-size: 0.55em;
  line-height: 1;
  opacity: 0.6;
  color: var(--dim);
  white-space: nowrap;
  font-variant-numeric: oldstyle-nums;
  font-feature-settings: "onum" 1;
}
/* the add plus, drawn his way (27 Sep 18:59): a custom plus from the same strokes as
   the horizon line and its vertical companion - 34px by 1px each way, the hairline's own -
   pinned on the horizon at the left-most side of the screen, the horizontal stroke exactly
   on the line, running right; it never scrolls, and it rides the horizon's drag. One seat
   on the cover for a new folder, one inside a folder for a new piece (27 Sep 19:29) */
.hair-plus {
  position: fixed;
  left: 0;
  top: calc(var(--hline) - 17px);
  width: 34px;
  height: 34px;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
  z-index: 11;
}
.hair-plus::before,
.hair-plus::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  transition: background 0.2s ease;
}
.hair-plus::before {
  left: 0;
  top: 17px; /* the stroke lies on the horizon line itself */
  width: 34px;
  height: 1px;
}
.hair-plus::after {
  left: 17px;
  top: 0;
  width: 1px;
  height: 34px;
}
.hair-plus.shine-h::before {
  background: var(--ink);
}
.hair-plus.shine-v::after {
  background: var(--ink);
}
.hair-plus:focus-visible {
  outline: none;
}
.cover-new {
  margin-top: 22px;
  min-height: 1.4em;
}
/* a folder row: the title alone sets the centering; the count (or "delete") hangs off its right edge */
.cover-row {
  position: relative;
  display: inline-block;
  line-height: var(--lh);
  font-size: var(--fs);
}
.cover-delete {
  background: none;
  border: 0;
  padding: 0;
  color: var(--palette-accent, #dc143c);
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  letter-spacing: 0.04em;
  cursor: pointer;
  opacity: 0.85;
  animation: fx-rise 0.25s ease-out;
}
.cover-delete:hover,
.cover-delete:focus-visible {
  opacity: 1;
  outline: none;
}
/* a hit area wider than the word, reaching back over the gap to the title, so the way there never leaves it */
.cover-delete::after {
  content: "";
  position: absolute;
  inset: -0.6em -0.6em -0.6em -1.2em;
}
.cover-delete {
  position: absolute;
}
/* naming a folder: no line, no placeholder - the text and a blinking crimson caret, nothing else */
.cover-name {
  min-width: 1ch;
  max-width: 70vw;
  background: transparent;
  border: 0;
  color: var(--ink);
  font: inherit;
  font-size: var(--fs);
  text-align: center;
  padding: 2px 0;
  outline: none;
  caret-color: var(--palette-caret, #dc143c);
}
.cover-folder {
  -webkit-touch-callout: none;
  user-select: none;
}
@media (max-width: 700px) {
  /* phone: a piece's text starts under its head (two mono lines + 8px of padding, then 16px), so the folders do too */
  .cover {
    margin-top: calc(2 * 1.42 * var(--fs-mono) + 8px + 16px);
  }
}

/* ---- sync: code field and join button, in the same panel style as the face list ---- */
.sync-panel form {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
}
.sync-panel form .pin + .box-submit {
  margin-top: -5px;
} /* one grid: the word's row sits one grid gap under the code */
.sync-actions {
  display: flex;
  flex-direction: column; /* one word per row, each row on the code's own four-box grid */
  gap: 5px;
  align-items: flex-end;
}
.sync-panel form .sync-actions {
  margin-top: -5px;
} /* one grid: the words sit one grid gap under the code */

/* the code field: small boxes, one per character; a typed character flashes, then settles into a middot */
.pin {
  position: relative;
}
.pin-input {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  opacity: 0;
  border: 0;
  padding: 0;
  margin: 0;
  font-size: 16px;
  color: transparent;
  background: transparent;
  caret-color: transparent;
  cursor: text;
  z-index: 1;
}
/* the code and the action share one grid, four boxes wide: the code fills rows from the top, the word sits in the row(s) under it */
.pin-boxes,
.box-word {
  display: grid;
  grid-template-columns: repeat(4, 20px);
  gap: 5px;
  justify-content: end;
}
.pin-box {
  position: relative;
  width: 20px;
  height: 26px;
  box-sizing: border-box;
  border: 1px solid var(--hairline);
  border-radius: 5px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 13px;
  line-height: 1;
  color: var(--ink);
  transition: border-color 0.15s ease;
}
.pin-box.filled {
  border-color: var(--dim);
}
.pin-box.active {
  border-color: var(--ink);
}
.pin-box.active::after {
  content: "";
  width: 1px;
  height: 13px;
  background: var(--palette-accent, #dc143c);
  animation: pin-caret 1.06s steps(1) infinite;
}
.pin-char {
  animation: pin-in 0.12s ease-out;
}
.pin-dot {
  font-size: 22px;
  font-weight: 700;
  transform: translateY(-1px);
  animation: pin-seal 0.22s cubic-bezier(0.3, 1.6, 0.5, 1);
}
@keyframes pin-caret {
  50% {
    opacity: 0;
  }
}
@keyframes pin-in {
  from {
    transform: translateY(3px);
    opacity: 0;
  }
}
@keyframes pin-seal {
  from {
    transform: translateY(-1px) scale(0.2);
    opacity: 0.2;
  }
}
.pin-shake .pin-boxes {
  animation: pin-shake 0.36s ease;
}
@keyframes pin-shake {
  20%,
  60% {
    transform: translateX(-4px);
  }
  40%,
  80% {
    transform: translateX(4px);
  }
}
@media (prefers-reduced-motion: reduce) {
  .pin-char,
  .pin-dot,
  .pin-shake .pin-boxes {
    animation: none;
  }
  .pin-box.active::after {
    display: none;
  }
}
.sync-note {
  margin: 0;
  max-width: 170px;
  font-size: 11px;
  line-height: 1.35;
  color: var(--dim);
  text-align: right;
}
/* under the code, a note keeps to the code's own width (the four boxes: 4 x 20px + 3 x 5px), so a message
   never widens the panel or pushes its grid apart; a longer one wraps inside that column */
.sync-form .sync-note {
  width: calc(4 * 20px + 3 * 5px);
  max-width: none;
  overflow-wrap: anywhere;
}

/* ---- history: a piece's snapshots, entered through the blinking middots that end the text ----
   Hover the middots: the blink stops and "history" is typed beside them on the same row.
   Click the typed word: it stays there as a button, with its caret blinking. Hover the pinned word: the dates
   fall below it one line at a time, on the top layer, no background; the hovered date turns crimson. */
.draft-story {
  position: relative;
}
.story.open .story-body:has(.hist-end) {
  overflow: visible; /* the title and the dropdown stand outside the text's own box */
}
.hist-end {
  position: relative;
  margin: 14px 0 0;
  display: flex;
  align-items: baseline;
  flex-wrap: wrap;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  line-height: 1.42;
  color: var(--dim);
}
.hist-end button {
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  letter-spacing: inherit;
  color: inherit;
  cursor: pointer;
  text-align: left;
  white-space: nowrap;
}
.hist-end .hist-mark {
  margin: 0;
  font-family: var(--font-body);
  font-variation-settings: var(--fvs-body);
  font-size: var(--fs);
  line-height: inherit;
  color: var(--ink);
  word-spacing: 0.25em;
  outline: none;
}
.hist-end.hover .hist-mark,
.hist-end.pinned .hist-mark {
  animation: none;
  opacity: 1;
}
/* The typed title and pinned button are the same node, beside the middots on one row. */
.hist-pin {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 0.3em;
  margin-left: 1.4em;
}
.hist-end .hist-type {
  display: inline-block;
  min-width: 0;
  color: var(--dim);
  transition: color 0.25s ease;
  pointer-events: auto;
}
.hist-end.pinned .hist-type,
.hist-end.drop .hist-type,
.hist-end .hist-type:hover,
.hist-end .hist-type:focus-visible {
  color: var(--ink);
  outline: none;
}
.hist-end .hist-type:empty { display: none; }
.history-count {
  margin-left: 0.3em;
  font-size: 0.55em;
  vertical-align: 0.7em;
  line-height: 1;
  opacity: 0.6;
  font-variant-numeric: oldstyle-nums;
  font-feature-settings: "onum" 1;
}
/* the dropdown: floats over what follows, no background, dates fall in one by one */
.history-list {
  position: absolute;
  left: 0;
  top: 100%;
  z-index: 40;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
}
.history-date {
  color: var(--dim);
  animation: hist-fall 0.28s ease both;
  animation-delay: calc(var(--i, 0) * 55ms);
  transition: color 0.2s ease;
}
@keyframes hist-fall {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: none; }
}
.history-date:hover,
.history-date:focus-visible,
.history-date.on {
  color: var(--palette-accent, #dc143c);
  outline: none;
}
.history-actions {
  display: inline-flex;
  gap: 1.4em;
}
.history-act:hover,
.history-act:focus-visible {
  color: var(--ink);
  outline: none;
}
.history-act.strong {
  color: var(--dim);
}
@media (prefers-reduced-motion: reduce) {
  .history-date { animation: none; }
}
/* peeking: the past self stands where the text was, a shade quieter, the live editor hidden but kept */
.snap-hidden {
  display: none;
}
.snap-peek {
  opacity: 0.72;
  animation: fx-rise 0.22s ease;
}
.snap-peek-title {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  color: var(--palette-accent, #dc143c);
}
.snap-peek .story-text p {
  white-space: pre-wrap;
}

/* Search: the resting line follows the chrome; results occupy the third column only on use. */
.search-rail {
  position: fixed;
  left: calc(
    388px + min(var(--shelf-measure, 734px), max(0px, 100vw - 444px))
  );
  right: 76px;
  top: calc(var(--hline) - 17px);
  height: 34px;
  max-height: calc(100vh - var(--hline) + 5px);
  overflow-y: hidden;
  overscroll-behavior: contain;
  scrollbar-width: none;
  z-index: 12;
  background: transparent;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  line-height: 1.42;
  letter-spacing: 0.04em;
  transition:
    opacity 0.45s ease,
    visibility 0s linear 0.45s;
}
:root.ui-awake .search-rail {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transition: opacity 0.45s ease;
}
.search-rail.showing {
  height: calc(100vh - var(--hline) + 5px);
  overflow-y: auto;
  background: var(--bg);
}
.admin-finder {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
}
:root.ui-awake .admin-finder {
  opacity: 1;
  pointer-events: auto;
}
.search-rail::-webkit-scrollbar {
  display: none;
}
.search-field-row {
  height: 34px;
  position: relative;
  font-size: var(--fs-mono);
}
.search-field-row::after {
  content: "";
  position: absolute;
  left: 0;
  top: 17px;
  width: min(var(--find-width), 100%);
  height: 1px;
  background: var(--hairline);
  pointer-events: none;
  transition:
    width 0.26s ease,
    background 0.26s ease,
    box-shadow 0.26s ease;
}
.search-field-row:hover:not(:focus-within)::after {
  width: min(calc(var(--find-width) + 9px), 100%);
  background: var(--ink);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ink) 40%, transparent);
}
.search-field {
  display: block;
  width: min(calc(var(--find-width) + 12px), 100%);
  height: 17px;
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  border: 0;
  outline: 0;
  background: transparent;
  color: var(--ink);
  caret-color: var(--palette-caret, #dc143c);
  font: inherit;
  text-align: left;
  transition: width 0.26s ease;
}
.search-results {
  padding-top: 10px;
  font-size: var(--fs-mono);
}
.search-group {
  display: flex;
  flex-direction: column;
  margin: 0 0 1.42em;
}
.search-group-title {
  color: var(--dim);
  margin: 0 0 0.35em;
}
.controls .search-hit {
  display: block;
  width: 100%;
  height: auto;
  padding: 0 0 0 2em;
  border: 0;
  border-radius: 0;
  background: none;
  text-align: left;
  color: var(--dim);
  font: inherit;
  letter-spacing: inherit;
  line-height: inherit;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.search-hit-dot {
  display: inline-block;
  width: 2em;
  margin-left: -2em;
  color: var(--hairline);
}
.search-hit-title {
  color: var(--dim);
}
.search-hit-text {
  color: var(--dim);
}
.search-hit mark {
  background: none;
  color: var(--ink);
  text-decoration: none;
}
.controls .search-hit.on .search-hit-title,
.controls .search-hit:hover .search-hit-title,
.controls .search-hit.on .search-hit-text,
.controls .search-hit:hover .search-hit-text {
  color: var(--ink);
}
.search-results .sync-note {
  margin: 0;
  color: var(--dim);
}
::highlight(search-hit) {
  background-color: color-mix(in srgb, var(--palette-selection, #dc143c) 28%, transparent);
  color: inherit;
}
.search-flash {
  background: color-mix(in srgb, var(--palette-selection, #dc143c) 18%, transparent);
  transition: background 0.6s ease;
}
@media (max-width: 900px) {
  .search-rail {
    left: max(18px, calc(100vw - 370px));
    right: 56px;
  }
  .search-rail.showing {
    box-shadow: -16px 12px 22px 16px var(--bg);
  }
}
@media (max-width: 700px) {
  .search-rail {
    left: 18px;
    right: 55px;
    top: calc(var(--hline) - 17px);
    box-shadow: none;
  }
  .search-rail.showing {
    max-height: none;
  }
}
/* phone, portrait and landscape: one search seat. Awake and idle, the rail is a 46px hairline flush right beside the
   horizon handle, so it never covers a folder name; focused or showing results it opens to the full width. */
@media (max-width: 700px), (max-width: 1100px) and (max-height: 500px) {
  .search-rail:not(.showing):not(:focus-within) { left: auto; width: 46px; right: 55px; }
  .search-rail:not(.showing):not(:focus-within) .search-field-row::after { left: auto; right: 12px; }
  .search-rail:not(.showing):not(:focus-within) .search-field { margin-left: auto; }
  .search-rail.showing, .search-rail:focus-within { left: 18px; right: 55px; }
}
@media (max-width: 700px) {
  /* the folders sit between the plus (left) and the search line + rail (right), so no stroke or button covers a name */
  .cover-folders { padding: 0 calc(54px + 34px + 13px); }
}

/* submit as a word in boxes (join, next, change, make it mine) */
.controls .face-choice.box-submit {
  padding: 0;
  border: 0;
  background: none;
  color: var(--dim);
  cursor: pointer;
}
.box-word .box-gap {
  width: 20px;
  height: 26px;
}
.box-submit .pin-box {
  font-size: 12px;
  color: var(--dim);
  border-color: var(--hairline);
  transition:
    color 0.2s ease,
    border-color 0.2s ease;
}
.controls .face-choice.box-submit:not(:disabled):hover .pin-box,
.controls .face-choice.box-submit:not(:disabled):focus-visible .pin-box {
  color: var(--ink);
  border-color: var(--ink);
}
.controls .face-choice.box-submit:not(:disabled) .pin-box {
  color: var(--ink);
  border-color: var(--dim);
}
.controls .face-choice.box-submit:disabled {
  opacity: 0.4;
  cursor: default;
}

/* Menu words are lit at rest; hovering or keyboard focus on one quiets the others. */
.controls .sync-panel .sync-menu-item .pin-box {
  color: var(--ink);
  border-color: var(--dim);
}
.controls
  .sync-panel:has(.sync-menu-item:hover)
  .sync-menu-item:not(:hover)
  .pin-box,
.controls
  .sync-panel:has(.sync-menu-item:focus-visible)
  .sync-menu-item:not(:focus-visible)
  .pin-box {
  color: var(--dim);
  border-color: var(--hairline);
  opacity: 0.35;
}
.controls .sync-panel .sync-menu-item .pin-box {
  transition:
    color 0.25s ease,
    border-color 0.25s ease,
    opacity 0.25s ease;
}
/* Destructive word: white letters, crimson outlines. The two colors trade on hover. */
.controls .face-choice.sync-wipe .pin-box {
  color: var(--palette-extra-fff, #fff);
  border-color: var(--palette-accent, #dc143c);
  transition:
    color 0.25s ease,
    border-color 0.25s ease;
}
.controls .face-choice.sync-wipe:hover .pin-box,
.controls .face-choice.sync-wipe:focus-visible .pin-box {
  color: var(--palette-accent, #dc143c);
  border-color: var(--palette-extra-fff, #fff);
}
/* SURE starts pale. Four signs wake a soft crimson light. */
.controls .face-choice.sync-wipe:disabled .pin-box {
  color: var(--palette-extra-8a8a8a, #8a8a8a);
  border-color: var(--palette-extra-63313c, #63313c);
  box-shadow: none;
}
.controls
  .face-choice.sync-wipe:not(:disabled)[aria-label="sure, wipe this shelf"]
  .pin-box {
  color: var(--palette-extra-fff, #fff);
  border-color: var(--palette-accent, #dc143c);
  box-shadow: 0 0 7px color-mix(in srgb, var(--palette-selection, #dc143c) 60%, transparent);
  transition:
    color 0.28s ease,
    border-color 0.28s ease,
    box-shadow 0.28s ease;
}
.controls
  .face-choice.sync-wipe:not(
    :disabled
  )[aria-label="sure, wipe this shelf"]:hover
  .pin-box,
.controls
  .face-choice.sync-wipe:not(
    :disabled
  )[aria-label="sure, wipe this shelf"]:focus-visible
  .pin-box {
  color: var(--palette-accent, #dc143c);
  border-color: var(--palette-extra-fff, #fff);
}
/* a file dragged over the page: a quiet frame says it can land (App: font drop) */
html.font-dropping body {
  box-shadow: inset 0 0 0 1px currentColor;
}

/* a state word in the sync panel: the code's boxes, dimmed, no border colour of its own */
.sync-note.sync-word {
  width: auto;
}
.sync-word .pin-box {
  color: var(--dim);
  border-style: dashed;
}
/* one grid: a state word sits one box gap under the row above it, like the submit word under the code */
.sync-panel form > .sync-word {
  margin-top: -5px;
}

.sync-panel .box-submit .box-word + .box-word {
  margin-top: 5px;
}
.sync-panel form > .box-submit {
  margin-top: -5px;
}

/* After a wipe, one random logo birth precedes the first-visit cover. */
.cover.cover-welcome > :not(.logo) {
  opacity: 0;
  pointer-events: none;
}
.cover:not(.cover-welcome) > :not(.logo) {
  transition: opacity 0.45s ease;
}

/* Closing curtain after an acknowledged wipe, before the one-cycle welcome. */
.wipe-curtain {
  position: fixed;
  inset: 0;
  z-index: 100;
  background: var(--palette-extra-000, #000);
  color: var(--palette-extra-fff, #fff);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  line-height: 1.5;
}
.wipe-curtain-line {
  display: flex;
  gap: 1ch;
}

/* In this menu the crimson wipe frame stays crimson until another choice takes focus. */
.controls .sync-panel .sync-menu-item.sync-wipe .pin-box {
  color: var(--palette-extra-fff, #fff);
  border-color: var(--palette-accent, #dc143c);
}
.controls
  .sync-panel:has(.sync-menu-item:hover)
  .sync-menu-item.sync-wipe:not(:hover)
  .pin-box,
.controls
  .sync-panel:has(.sync-menu-item:focus-visible)
  .sync-menu-item.sync-wipe:not(:focus-visible)
  .pin-box {
  color: var(--palette-extra-8a8a8a, #8a8a8a);
  border-color: var(--palette-extra-63313c, #63313c);
  opacity: 0.35;
}
/* Reserved visual for an occupied code. Not connected to join until the owner
   decides whether an occupied code enters immediately or waits for a tap. */
.sync-occupied-hint {
  width: calc(4 * 20px + 3 * 5px);
  max-width: none;
  text-align: center;
  color: var(--dim);
}
.sync-occupied-hint span {
  display: block;
}

/* Wipe sits last in the menu, faded at rest; it turns crimson only under the pointer or keyboard focus. */
.controls .sync-panel .sync-menu-item.sync-wipe.sync-quiet .pin-box {
  color: var(--palette-extra-8a8a8a, #8a8a8a);
  border-color: var(--palette-extra-63313c, #63313c);
  opacity: 0.35;
}
.controls .sync-panel .sync-menu-item.sync-wipe.sync-quiet:hover .pin-box,
.controls .sync-panel .sync-menu-item.sync-wipe.sync-quiet:focus-visible .pin-box {
  color: var(--palette-accent, #dc143c);
  border-color: var(--palette-accent, #dc143c);
  opacity: 1;
}

/* Sync panel hover titles: the tip is drawn to the left of the word, outside the button and the panel.
   Both boxes clipped it (button overflow hidden for the ellipsis, panel overflow auto for scroll). */
.controls .sync-panel {
  overflow: visible;
}
.controls .sync-panel .face-choice {
  overflow: visible;
  max-width: none;
}

/* Every wipe word rests grayed out; crimson only under the pointer or keyboard focus.
   Covers the menu word, the WIPE confirm word and SURE (enabled or not). */
.controls .sync-panel .face-choice.sync-wipe:not(:hover):not(:focus-visible) .pin-box {
  color: var(--palette-extra-8a8a8a, #8a8a8a);
  border-color: var(--palette-extra-63313c, #63313c);
  box-shadow: none;
  opacity: 0.35;
}
.controls .sync-panel .face-choice.sync-wipe:not(:disabled):hover .pin-box,
.controls .sync-panel .face-choice.sync-wipe:not(:disabled):focus-visible .pin-box {
  color: var(--palette-accent, #dc143c);
  border-color: var(--palette-accent, #dc143c);
  box-shadow: none;
  opacity: 1;
}

/* Sync panel hover titles sit fully outside the panel: button inset (15px) + 11px gap.
   Titles grow leftward from this edge, so the longest one ("change e-mail") stays clear too. */


/* Home search appears only after its button (or keyboard shortcut) is used. Folder search keeps its activity gate. */
:root.ui-awake .search-home .search-rail:not(.open) { opacity: 0; visibility: hidden; pointer-events: none; }
@media (max-width: 700px), (max-width: 1100px) and (max-height: 500px) {
  .search-folder .search-rail:not(.open) { opacity: 0; visibility: hidden; pointer-events: none; }
  .search-folder .search-rail.open { left: 34px; right: 8px; width: auto; }
  .search-folder .search-field-row::after { left: auto; right: 0; width: 34px; }
  .search-folder .search-field-row:hover::after { width: 43px; }
  .search-folder .search-field { margin-left: auto; text-align: right; width: min(calc(var(--find-width) + 12px), 100%); }
  /* The finder uses the horizon stroke, never a second neighbouring line. */
  :root:has(.search-folder .search-rail.open) .horizon-line { visibility: hidden; }
}

/* Search opacity must not inherit its widget's activity fade a second time. */
.controls > .search-widget, :root.ui-awake .controls > .search-widget { opacity: 1; pointer-events: none; }
.controls > .search-widget > button { opacity: 0; pointer-events: none; transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms); }
:root.ui-awake .controls > .search-widget > button { opacity: 1; pointer-events: auto; }
.search-rail, :root.ui-awake .search-rail, .admin-finder, :root.ui-awake .admin-finder {
 transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms), visibility 0s linear calc(var(--ui-duration, 450ms) + var(--ui-delay, 0ms));
}
@media (prefers-reduced-motion: reduce) { .search-rail, .admin-finder, .controls > .search-widget > button { transition-duration: 0s; transition-delay: 0s; } }
/* The tap must focus synchronously, before the soft opacity transition ends. */
:root.ui-awake .search-rail.open { visibility: visible; transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms), visibility 0s; }

/* Writing temporarily parks the mark and quiets chrome without changing any preferences.
   The parent gate also covers open shelves and individually animated control families. */
.logo { transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms); }
:root.typing-focus :is(.logo, .controls, .plumb, .hair-plus, .search-rail, .admin-finder, .type-tip) {
  opacity: 0 !important;
  visibility: hidden !important;
  pointer-events: none !important;
}
:root.typing-focus .controls * { pointer-events: none !important; }
@media (prefers-reduced-motion: reduce) { .logo { transition-duration: 0s; transition-delay: 0s; } }

/* Keep peek actions inside the text column, including the narrow read surface. */
.hist-pin {
  max-width: calc(100% - 3.4em);
  flex-wrap: wrap;
}
.history-actions {
  flex-basis: 100%;
  flex-wrap: wrap;
  gap: 0.3em 1.4em;
}

/* history: the old title stands in the index, in the title's own place and colour; the body never moves */
.draft-head-main.peeking { position: relative; }
.draft-head-main.peeking .story-title.editable { visibility: hidden; }
.story-title.peek-title {
  position: absolute;
  left: 0;
  top: 0;
  right: 0;
  pointer-events: none;
}
.history-date.erasing { pointer-events: none; animation: none; }

/* a version's number shows on hover only, like its creation date */
.vrow-inner .gutter.num.serial-on { color: var(--dim); }

/* new version plus: dimmed, one blank row below the version list, left edge level with the dates' left edge */
.version-stack .vrow.add { margin-top: calc(var(--lh-mono, 1.42) * 1em + 4px); }
.version-add { font: inherit; letter-spacing: 0.04em; margin-left: calc(6 * (1ch + 0.04em)); }
.version-add::before,
.version-add::after { background: var(--hairline); }
.version-add.reveal-h-first::before,
.version-add.reveal-v-first::after,
.version-add.reveal-h-first::after,
.version-add.reveal-v-first::before { opacity: 0.6; }
.version-add.reveal-h-first:hover::before,
.version-add.reveal-h-first:hover::after,
.version-add.reveal-v-first:hover::before,
.version-add.reveal-v-first:hover::after,
.version-add:focus-visible::before,
.version-add:focus-visible::after { background: var(--dim); opacity: 0.8; }

/* draft head: the title block takes the width left beside the gutter and wraps inside it.
   As an inline-block it was placed under the gutter as soon as the title outgrew the line,
   which pushed the title down away from the fold middot and opened a gap above its first line. */
.draft-story .story-head { display: flex; align-items: flex-start; }
.draft-story .story-head > .gutter { flex: none; }
.draft-story .story-head > .story-head-main { flex: 1 1 0; min-width: 0; display: block; }

/* the hover version number carries a dim "v." that hangs left of the number's own slots,
   so the digits keep the column of the piece number above and below */
.vrow-inner .gutter.num .vpre {
  position: absolute;
  right: 100%;
  opacity: 0.55;
}
.vrow-inner { overflow-x: visible; overflow-y: clip; }

/* the delete cross sits at the head's right edge on the title's first line: the title text area
   narrows from the right by the cross's own box plus one cross width, so a long title never runs under it */
.draft-story .story-title { padding-right: calc(8px + 2 * 1ch * var(--fs-mono) / var(--fs)); }

/* Enter inside a title makes <p>/<div> blocks that pick up the browser's 1em margins: the title dropped
   13.33px under the middot and the lines sat a blank line apart. Blocks inside the title carry no margin. */
.draft-story .story-title p,
.draft-story .story-title div { margin: 0; }

/* history serials: each dropdown row carries a number whose left edge sits on the main text area's left
   edge and runs right from there (the date stays where it was), dimmer than the date, oldest = 001 */
.history-date { position: relative; }
.history-serial {
  position: absolute;
  left: var(--serial-x, -2.6em);
  top: 0;
  color: var(--dim);
  opacity: 0.55;
  pointer-events: auto;
  cursor: inherit;
  transition: color 0.2s ease, opacity 0.2s ease;
}
.history-date:hover .history-serial,
.history-date:focus-visible .history-serial,
.history-date.on .history-serial {
  color: var(--palette-accent, #dc143c);
  opacity: 1;
}

/* the add plus doubles as the wipe: on a hovered row it morphs into a cross (47px diagonals span 33.2px, so the
   tips touch the screen's left edge like the plus's arm; a hair smaller than the plus's 34px) and slides to that
   row on the same axis (x 17). Each morph runs one of 64 variations set from script (--m-*): which diagonal each
   stroke takes, which way it turns, its own delay, duration and starting tone. Hovering the cross turns it a quarter. */
html.plus-wipe .hair-plus, html.plus-wipe-out .hair-plus {
  transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms), top 0.32s var(--m-ease, ease-in-out);
}
html.plus-wipe .hair-plus { top: calc(var(--wipe-y) - 17px); opacity: 1; pointer-events: auto; }
html.plus-wipe .hair-plus-word { opacity: 0; }
html.plus-wipe .hair-plus::before, html.plus-wipe-out .hair-plus::before { transition: background 0.2s ease, transform var(--m-at, 0.34s) var(--m-ease, ease-in-out) var(--m-ad, 0s); }
html.plus-wipe .hair-plus::after, html.plus-wipe-out .hair-plus::after { transition: background 0.2s ease, transform var(--m-bt, 0.34s) var(--m-ease, ease-in-out) var(--m-bd, 0s); }
html.plus-wipe .hair-plus::before { transform: rotate(var(--m-a)) scaleX(1.382); animation: plus-tone var(--m-at) ease-out var(--m-ad) backwards; --from: var(--m-from-a); }
html.plus-wipe .hair-plus::after { transform: rotate(var(--m-b)) scaleY(1.382); animation: plus-tone var(--m-bt) ease-out var(--m-bd) backwards; --from: var(--m-from-b); }
html.plus-wipe.plus-wipe-flip .hair-plus::before { transform: rotate(calc(var(--m-a) + 90deg)) scaleX(1.382); }
html.plus-wipe.plus-wipe-flip .hair-plus::after { transform: rotate(calc(var(--m-b) + 90deg)) scaleY(1.382); }
@keyframes plus-tone { from { background: var(--from); } 70% { background: var(--from); } to { background: var(--hairline); } }
html.plus-wipe .hair-plus:hover::before, html.plus-wipe .hair-plus:hover::after { background: var(--ink); }
@media (prefers-reduced-motion: reduce) { html.plus-wipe .hair-plus::before, html.plus-wipe .hair-plus::after { animation-duration: 1ms; animation-delay: 0s; transition-duration: 0s; transition-delay: 0s; } }

/* reading mode's wipe: the plus's own hover title, typed upward from the morphed plus on the hovered row */
html[data-wipe-tip].plus-wipe .hair-plus-word { opacity: 1; bottom: calc(100vh - var(--wipe-y) + 17px + 14px); }

/* layout button: one attribute (data-layout) on the root, reading, draft and the admin page alike; the default sets none, so build 2135 rules stay untouched */
:root[data-layout] .story:not(.dialogue) .story-text { --lay-in: 1.5em; --lay-gap: .5em; }
:root[data-layout] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) {
  padding: 0; text-indent: 0; margin: 0;
}
/* 2 first-line: OASE 51/70/116 regime, compact first-line indent, no gap */
:root[data-layout="first-line"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { text-indent: 1.5em; }
/* 3 flush: gap compensates for the missing indent signal */
:root[data-layout="flush"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: .8em; }
/* 5 shoulder: deep opening edge (issue 34), capped so it never eats the measure */
:root[data-layout="shoulder"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio):first-child { padding-left: min(4em, 22%); }
:root[data-layout="shoulder"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: var(--lay-gap); }
/* 6 hanging */
:root[data-layout="hanging"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) { padding-left: var(--lay-in); text-indent: calc(-1 * var(--lay-in)); }
:root[data-layout="hanging"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: var(--lay-gap); }
/* 7 narrow-centre */
:root[data-layout="narrow-centre"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) { padding-inline: 5%; }
:root[data-layout="narrow-centre"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: .7em; }
/* 8 alternating: same width, left then right */
:root[data-layout="alternating"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio):nth-child(odd) { padding-right: var(--lay-in); }
:root[data-layout="alternating"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio):nth-child(even) { padding-left: var(--lay-in); }
:root[data-layout="alternating"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: .5em; }
@media (max-width: 700px) {
  :root[data-layout] .story:not(.dialogue) .story-text { --lay-in: 1em; }
  :root[data-layout="shoulder"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio):first-child { padding-left: 2.2em; }
  :root[data-layout="narrow-centre"] .story:not(.dialogue) .story-text > :is(p, div):not(.story-audio) { padding-inline: 3%; }
}
/* the layout button announces its name to screen readers only */
.layout-live { position: absolute; width: 1px; height: 1px; margin: -1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }

/* layout options: bare four-line marks in a 34 px cell inside the family column (ctl-members), no ring */
.controls .layout-opt { flex: none; width: 34px; height: 34px; padding: 0; border: 0; border-radius: 0; background: none; color: var(--dim); display: block; cursor: pointer; transition: color .15s ease, filter .15s ease; }
.controls .layout-opt svg { display: block; overflow: visible; }
.controls .layout-opt:hover, .controls .layout-opt:focus-visible { color: var(--ink); border: 0; filter: drop-shadow(0 0 4px color-mix(in srgb, var(--ink) 55%, transparent)); }
.layout-opt line { stroke-dasharray: 1 1; }
@media (prefers-reduced-motion: no-preference) {
  .controls .layout-opt:hover line, .controls .layout-opt:focus-visible line { animation: layout-draw .3s steps(8, end) both; animation-delay: calc(var(--i) * 70ms); }
}
@keyframes layout-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }

/* the layout column previews on the page: the text must stay at full strength while it is open (the phone rule dims the page for other groups) */
:root:has(.controls .layout-wrap .ctl-group.open) .page { opacity: 1; }

/* 8 caption rail: the title and its small facts sit in a narrow left column, the text beside it (grid on the story; head and fold are siblings) */
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) { display: grid; grid-template-columns: minmax(0, 8em) minmax(0, 1fr); column-gap: 1.6em; align-items: start; }
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) > .story-head { grid-column: 1; grid-row: 1; }
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) > .story-fold { grid-column: 2; grid-row: 1; }
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: .7em; }
/* 9 two columns: the text runs in two columns (no margins between paragraphs: a margin at a column top would stagger the columns) */
:root[data-layout="two-columns"] .story:not(.dialogue):not(:has(.story-audio)) .story-text { column-count: 2; column-gap: 2.4em; }
:root[data-layout="two-columns"] .story:not(.dialogue):not(:has(.story-audio)) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: 0; text-indent: 1.4em; }
/* 10 quiet page: a deep empty start, the text begins low on the page and breathes between paragraphs */
:root[data-layout="quiet-page"] .story:not(.dialogue):not(:has(.story-audio)) .story-text { padding-top: min(24vh, 10em); }
:root[data-layout="quiet-page"] .story:not(.dialogue):not(:has(.story-audio)) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: 1.3em; }
/* 11 dense justified: both edges even, hyphenated, no space between paragraphs, a small indent marks each new one */
:root[data-layout="dense-justified"] .story:not(.dialogue):not(:has(.story-audio)) .story-text { text-align: justify; hyphens: auto; -webkit-hyphens: auto; }
:root[data-layout="dense-justified"] .story:not(.dialogue):not(:has(.story-audio)) .story-text > :is(p, div):not(.story-audio) + :is(p, div):not(.story-audio) { margin-top: 0; text-indent: 1.2em; }
@media (max-width: 700px) {
  /* Phone proposals: retain a true caption margin; a short, ruled measure
     represents the two-column family without unreadably small actual columns. */
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) {
    grid-template-columns: minmax(0, 5.5rem) minmax(0, 1fr);
    column-gap: .7rem;
  }
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) > .story-head {
    font-size: 9px;
    --fs-mono: 9px;
    min-width: 0;
    padding-top: 0;
  }
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-head-main {
    min-width: 0;
    max-width: 100%;
    overflow-wrap: anywhere;
  }
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-when {
    white-space: normal;
    overflow-wrap: anywhere;
  }
  :root[data-layout="two-columns"] .story:not(.dialogue):not(:has(.story-audio)) .story-text:not(:has(> .story-audio)) {
    column-count: 1;
    border-left: 1px solid var(--hairline);
    padding-left: .8em;
    margin-right: 8%;
  }
}
/* Grid tracks never borrow the intrinsic width of title, date, or version rows. */
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) > :is(.story-head, .story-fold) { min-width: 0; }
:root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-title { overflow-wrap: anywhere; }
/* New layout geometry excludes mixed audio stories: players retain their
   original story measure and position, rather than fragmenting with prose. */
@media (max-width: 700px) {
  /* The editor's mobile correction aligns ordinary prose with the horizon.
     Quiet page deliberately starts lower, so do not subtract that whitespace. */
  :root[data-layout="quiet-page"] .page.folder-surface { padding-top: var(--pin); }
  :root[data-layout="quiet-page"] .folder-surface .story.open .story-head { top: var(--pin); }
  :root[data-layout="two-columns"] .story:not(.dialogue):not(:has(.story-audio)) .story-text:not(:has(> .story-audio)) { border-left-color: var(--dim); }
}

@media (max-width: 700px) {
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-head > .gutter { width: 24px; }
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-head-main > .story-when,
  :root[data-layout="caption-rail"] .story:not(.dialogue):not(:has(.story-audio)) .story-head-main .version-stack { margin-left: -24px; }
}
