/* Page controls, horizon handle and type shelf. */
.controls {
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.45s ease;
  position: fixed;
  right: 14px;
  top: var(--ctl);
  /* one column, never wrapped: the families fold (ControlGroup), and the horizon stops where the folded
       stack still ends above the bottom edge (HorizonControl hzMax), so no button ever leaves the page */
  display: flex;
  flex-direction: column;
  gap: 10px;
  z-index: 10;
  overflow: visible; /* era menu and hover labels live left of the box */
}
.controls .horizon-control {
  position: fixed;
  right: 14px;
  top: calc(var(--hline) - 17px);
}
/* the horizon control is dragged: no scrolling or text selection under the finger */
.controls .horizon-control {
  touch-action: none;
  cursor: ns-resize;
  user-select: none;
  -webkit-user-select: none;
}
.controls .horizon-control {
  border: 0;
  border-radius: 0;
  background: none;
  display: flex;
  align-items: center;
  justify-content: flex-end; /* the right end stays pinned as the stroke grows left */
}
.home-jump {
  position: relative;
  display: flex;
}
.folder-jump {
  position: absolute;
  /* flush against the home button, the 10px air moved inside as padding: the hand can
       travel from the button onto the stack without the reveal dropping under it */
  right: 100%;
  padding-right: 10px;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 10px;
  /* the jumps rest hidden: hovering the home button reveals them */
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.25s ease;
}
.home-jump:hover .folder-jump,
.folder-jump:focus-within {
  opacity: 1;
  pointer-events: auto;
}
.controls .folder-jump-button {
  width: auto;
  height: 34px;
  padding: 0 13px;
  border-radius: 17px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 9.5pt;
  letter-spacing: 0.04em;
  color: var(--dim);
  white-space: nowrap;
  max-width: 220px;
  overflow: hidden;
  text-overflow: ellipsis;
}
.controls .folder-jump-button:hover,
.controls .folder-jump-button.on {
  color: var(--ink);
}
.horizon-line {
  display: block;
  width: 34px;
  flex: none; /* do not shrink the extending line back into its 34px handle */
  height: 1px;
  background: var(--hairline);
  transition:
    width 0.26s ease,
    background 0.26s ease,
    box-shadow 0.26s ease;
} /* the rings' width and stroke */
.controls .horizon-control:hover .horizon-line,
.controls .horizon-control:focus-visible .horizon-line {
  width: 43px;
  background: var(--ink);
  box-shadow: 0 0 8px color-mix(in srgb, var(--ink) 40%, transparent);
} /* as a ring turns ink on hover */
.controls .horizon-control.on .horizon-line {
  background: var(--ink);
}
:root.ui-awake .controls,
:root.horizon-drag .controls {
  opacity: 1;
  pointer-events: auto;
}

/* the plumb: the horizon's vertical companion - the pair is one set. Its line hangs from
   the top edge of the page down 34px, at the main text's right edge, where the width
   grip has always lived. Awake with the controls, hidden again at rest; the plumb is
   itself the width grip, and it shines ink on hover and while the drag holds */
.plumb {
  position: fixed;
  top: 0; /* tight to the page's top edge: the plumb hangs from it, like a plumb line does */
  /* and it hangs at the main text's right edge, where the width grip has always lived -
       the em in left must be the text's em, so the size is pinned on the element */
  left: calc(
    48px + var(--index-w, 300px) + 40px +
      min(var(--measure, 29em), 100vw - 48px - var(--index-w, 300px) - 40px - 56px) - 3px
  );
  width: 1px;
  height: 34px;
  background: var(--hairline);
  background-clip: content-box; /* the hairline stays 1px; the padding is the grip */
  padding: 0 8px 0 3px; /* 3px over the text's edge, 8px in the gap right of it */
  font-size: var(
    --fs
  ); /* --measure's em resolves in the text's em, like the old handle */
  opacity: 0;
  transition:
    opacity 0.45s ease,
    height 0.26s ease,
    background-color 0.26s ease,
    filter 0.26s ease;
  cursor: col-resize;
  touch-action: none;
  z-index: 11;
}
:root.ui-awake .plumb {
  opacity: 1;
}
.plumb:hover,
:root.measure-drag .plumb,
:root:has(.horizon-control:hover) .plumb,
:root.horizon-drag .plumb {
  background-color: var(
    --ink
  ); /* longhand: the shorthand would reset the content-box clip */
}
/* the index tick: the plumb's left twin. Its hairline hangs from the page's top edge at the
   main text's left edge; dragging it widens or narrows the index column, and the text and the
   plumb on its right ride with it toward the page's edges. Desktop only (the mobile story is one column) */
.plumb.plumb-index {
  left: calc(48px + var(--index-w, 300px) + 40px - 9px);
  padding: 0 3px 0 8px;
}
@media (max-width: 700px) {
  .plumb.plumb-index { display: none; }
}
.plumb:hover {
  height: 43px;
  filter: drop-shadow(0 0 5px color-mix(in srgb, var(--ink) 40%, transparent));
}
/* and the companion answers: hovering or dragging the plumb lights the horizon's line */
:root:has(.plumb:hover) .horizon-line,
:root.measure-drag .horizon-line {
  background: var(--ink);
}
/* the width drag is not a text selection: nothing highlights while the tick is held */
.plumb,
:root.measure-drag {
  -webkit-user-select: none;
  user-select: none;
}

:root.measure-drag .page {
  user-select: none;
}
.controls button {
  width: 34px;
  height: 34px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--dim);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  padding: 0;
}
.controls button {
  transition:
    color 0.35s ease,
    border-color 0.35s ease,
    opacity 0.35s ease;
}
.controls button:hover,
.controls button:focus-visible {
  color: var(--ink);
  border-color: var(--ink);
  outline: none;
}
.controls button {
  position: relative;
}

.controls button:disabled {
  opacity: 0.3;
  cursor: default;
}
.controls button:disabled:hover {
  color: var(--dim);
  border-color: var(--hairline);
}

@media (max-width: 700px) {
  :root {
    --pin: calc(120px + var(--hz) + var(--vt));
    --head: calc(2 * 1.42 * var(--fs-mono) + 8px + 16px);
  }
  .page {
    padding: var(--pin) 20px 96px 18px;
  }
  .plumb {
    left: calc(18px + min(var(--measure, 29em), 100vw - 38px) - 3px);
  }
  .story {
    grid-template-columns: 1fr;
    margin: 0 0 26px;
  }
  .story-head {
    padding: 2px 0;
  }
  .story.open .story-head {
    margin: 0 0 16px;
    background: var(--bg);
    top: var(--pin);
  }
  .archive-end {
    margin: 40px 0 0 0;
    width: 280px;
  }
  .fold-dot {
    left: -15px;
    padding-right: 4px;
  }
  .audio-part {
    flex-wrap: wrap;
  }
  .audio-label {
    flex-basis: 100%;
    padding-left: 42px;
    margin-top: -6px;
  }
  .controls,
  .controls .horizon-control {
    right: 8px;
  }
}

/* top seam: the fade band at the top of the page (see .seam.standalone at the end) */
.seam {
  position: fixed;
  top: var(--vt);
  left: 0;
  right: 0;
  height: var(--seam-h);
  background: linear-gradient(
    to bottom,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 100%, transparent) 0%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 98.7%, transparent) 8.1%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 95.1%, transparent) 15.5%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 89.6%, transparent) 22.5%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 82.5%, transparent) 29%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 74.1%, transparent) 35.3%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 64.8%, transparent) 41.2%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 55%, transparent) 47.1%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 45%, transparent) 52.9%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 35.2%, transparent) 58.8%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 25.9%, transparent) 64.7%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 17.5%, transparent) 71%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 10.4%, transparent) 77.5%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 4.9%, transparent) 84.5%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 1.3%, transparent) 91.9%,
    color-mix(in srgb, var(--palette-seam-invert, #f4efec) 0%, transparent) 100%
  );
  pointer-events: none;
  z-index: 5;
}

/* draft-only controls: a divider and a color swatch among the icon ghosts */
/* a family: its button in the stack, its members in a column to the left, level with it (slid up by
   ControlGroup where the window ends first); the column's right padding bridges the gap for a mouse */
.ctl-group {
  position: relative;
  width: 34px;
  height: 34px;
  flex: none;
}
.ctl-members {
  position: absolute;
  right: 34px;
  padding-right: 10px;
  display: flex;
  flex-direction: column;
  align-items: flex-end; /* the members hug the stack's side - a wide row (the pdf pick) must not push the rest left */
  gap: 10px;
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
  transform: translateX(6px);
  transition:
    opacity 0.25s ease,
    transform 0.25s ease,
    visibility 0s linear 0.25s;
}
.ctl-group.open .ctl-members {
  opacity: 1;
  visibility: visible;
  pointer-events: auto;
  transform: none;
  transition:
    opacity 0.25s ease,
    transform 0.25s ease;
}
.ctl-glyph {
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 12px;
  letter-spacing: 0.02em;
  line-height: 1;
}

.controls button.draft-toggle:hover,
.controls button.draft-toggle:focus-visible {
  background: var(--ink);
  color: var(--bg);
  border-color: var(--ink);
}
.controls button.draft-toggle {
  transition:
    color 0.35s ease,
    border-color 0.35s ease,
    background-color 0.35s ease,
    opacity 0.35s ease;
}

/* era control: one icon; hover unfolds the choices leftward, random leftmost */
.era-widget {
  position: relative;
  width: 34px;
}
.era-menu {
  position: absolute;
  right: 34px; /* flush against the icon: the right padding is a hover bridge, no dead gap to fall through */
  top: 50%;
  transform: translateY(-50%) translateX(8px);
  display: flex;
  align-items: center;
  gap: 11px;
  opacity: 0;
  visibility: hidden;
  /* leaving waits a beat, so a hand drifting between the years doesn't lose the fan */
  transition:
    opacity 0.35s ease 0.45s,
    transform 0.35s ease 0.45s,
    visibility 0s linear 0.8s;
  background: var(--bg);
  border-radius: 17px;
  padding: 3px 19px 3px 10px;
}
.era-widget:hover .era-menu,
.era-widget:focus-within .era-menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(-50%);
  transition:
    opacity 0.35s ease,
    transform 0.35s ease,
    visibility 0s;
}
.controls .era-choice {
  position: relative;
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  background: none;
  display: inline-block;
  padding: 4px 1px;
  cursor: pointer;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 8.5pt;
  letter-spacing: 0.04em;
  color: var(--dim);
}
.controls .era-choice {
  transition: color 0.35s ease;
}
.controls .era-choice:hover,
.controls .era-choice:focus-visible {
  color: var(--ink);
  outline: none;
}
.controls .era-choice.current {
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
}

.controls button.swatch {
  position: relative;
}
.controls .swatch-dot {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid var(--dim);
  display: block;
  pointer-events: none;
}
.controls .swatch input[type="color"] {
  position: absolute;
  inset: 0;
  opacity: 0;
  cursor: pointer;
}

/* type shelf */
.face-widget {
  position: relative;
  width: 34px;
}
.face-list {
  position: fixed;
  max-height: min(calc(100vh - 24px), 520px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: none;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  padding: 12px 14px;
  background: var(--bg);
  border: 1px solid var(--hairline);
  border-radius: 14px;
  z-index: 12;
}
.face-list::-webkit-scrollbar {
  display: none;
}
.controls .face-choice {
  width: auto;
  height: auto;
  border: 0;
  border-radius: 0;
  background: none;
  display: block;
  flex: none;
  padding: 3px 0;
  white-space: nowrap;
  max-width: 18ch; /* long face names can't widen the panel */
  overflow: hidden;
  text-overflow: ellipsis;
  font-size: calc(13px + 1pt); /* face names: +1pt */
  letter-spacing: 0;
  color: var(--dim);
  cursor: pointer;
  transition: color 0.35s ease;
}
.controls .face-choice.wing {
  margin-top: 12px;
}
.controls .face-choice:hover,
.controls .face-choice:focus-visible {
  color: var(--ink);
  outline: none;
}
.controls .face-choice.current {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 4px;
}

.size-field {
  position: relative;
  width: 34px;
  height: 34px;
  display: block;
}
.size-field input {
  display: block; /* an inline input sinks below the label's baseline - the ring sat 5px low of its mates */
  width: 34px;
  height: 34px;
  box-sizing: border-box; /* the border rides inside the 34, the same ring as the hyphen's */
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: transparent;
  color: var(--dim);
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 10px;
  letter-spacing: 0;
  text-align: center;
  padding: 0;
  outline: none;
  caret-color: var(--palette-caret, #dc143c);
  transition:
    color 0.35s ease,
    border-color 0.35s ease;
}
.size-field input:hover,
.size-field input:focus {
  color: var(--ink);
  border-color: var(--ink);
}
.size-field input::selection {
  background: var(--palette-selection, #dc143c);
  color: var(--palette-selection-ink, #000);
}
/* the picked-numbers picker: two number rings with the hyphen in a ring of its own */
.pdf-pick {
  display: flex;
  align-items: center;
  gap: 6px;
}
.pdf-pick-dash {
  width: 34px;
  height: 34px;
  box-sizing: border-box; /* the border rides inside the 34, level with the number rings */
  border-radius: 50%;
  border: 1px solid var(--hairline);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--dim);
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 10px;
  user-select: none;
  -webkit-user-select: none;
}



/* ---- the owner's fonts: the upload button, then his fonts as the first shelf of the face list ----
   Every entry keeps the list's size and right edge; the × sits to the left of a name */
.controls .face-choice.face-upload {
  border: 1px solid var(--hairline);
  border-radius: 999px;
  padding: 2px 12px;
  margin-bottom: 6px;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  color: var(--dim);
}
.controls .face-choice.face-upload:hover,
.controls .face-choice.face-upload:focus-visible {
  color: var(--ink);
  border-color: var(--dim);
}
.face-upload-note {
  margin: 0 0 4px;
  font-size: 11px;
  line-height: 1.3;
  opacity: 0.6;
  text-align: right;
  max-width: 180px;
}
.face-own {
  display: flex;
  align-items: baseline;
  justify-content: flex-end;
  gap: 6px;
}
.controls .face-remove {
  width: auto;
  height: auto;
  flex: none;
  border: 0;
  border-radius: 0;
  background: none;
  color: var(--dim);
  font: inherit;
  font-size: 11px;
  opacity: 0.6;
  cursor: pointer;
  padding: 0;
}
.controls .face-remove:hover {
  opacity: 1;
  color: var(--ink);
  background: none;
}

/* ---- knobs of a variable face (AxisKnobs): under its name in the face list, right-aligned like the list ----
   name, a thin line with a small dot, the value in oldstyle figures; the line is the whole hit area */
.face-list .face-choice {
  font-variation-settings: normal;
} /* names are set in their own faces, not the slot's knobs */
.face-axes {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  margin: 2px 0 8px;
  font-family: var(--font-mono);
  font-variation-settings: normal;
  font-size: 11px;
  color: var(--dim);
}
.face-axis {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 8px;
  cursor: default;
}
.face-axis-name {
  white-space: nowrap;
  cursor: pointer;
  user-select: none;
  -webkit-user-select: none;
}
.face-axis-value {
  width: 3.2em;
  text-align: left;
  font-variant-numeric: oldstyle-nums tabular-nums;
  color: var(--ink);
  opacity: 0.8;
}
.face-axis input[type="range"] {
  -webkit-appearance: none;
  appearance: none;
  width: 96px;
  height: 22px;
  margin: 0;
  padding: 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  touch-action: none;
}
.face-axis input[type="range"]::-webkit-slider-runnable-track {
  height: 1px;
  background: var(--hairline);
}
.face-axis input[type="range"]::-moz-range-track {
  height: 1px;
  background: var(--hairline);
}
.face-axis input[type="range"]::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 9px;
  height: 9px;
  margin-top: -4px;
  border-radius: 50%;
  background: var(--dim);
  border: 0;
  transition: background 0.2s ease;
}
.face-axis input[type="range"]::-moz-range-thumb {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--dim);
  border: 0;
}
.face-axis:hover input[type="range"]::-webkit-slider-thumb,
.face-axis input[type="range"]:focus-visible::-webkit-slider-thumb {
  background: var(--ink);
}
.face-axis:hover input[type="range"]::-moz-range-thumb,
.face-axis input[type="range"]:focus-visible::-moz-range-thumb {
  background: var(--ink);
}
.face-axis input[type="range"]:focus {
  outline: none;
}
.face-axis:hover .face-axis-name {
  color: var(--ink);
}
@media (max-width: 600px) {
  .face-axis input[type="range"] {
    width: 84px;
    height: 28px;
  }
}

/* standalone mirror: with no host header above the page, the top fade is the
   page's own background thinning out (mask), so it follows --bg and inversion */
.seam.standalone {
  top:0;
  background:var(--palette-seam-dark, var(--bg));
  -webkit-mask-image:linear-gradient(to bottom,#000 0%,rgba(0,0,0,.75) 35%,rgba(0,0,0,.35) 70%,transparent 100%);
  mask-image:linear-gradient(to bottom,#000 0%,rgba(0,0,0,.75) 35%,rgba(0,0,0,.35) 70%,transparent 100%);
}
:root.inverted .seam.standalone { background:var(--palette-seam-invert, var(--bg)); }
.face-own .face-remove {
  width: 18px;
  color: var(--dim);
  font-size: 15px;
  opacity: 0;
  pointer-events: none;
}
.face-own:hover .face-remove,
.face-own:focus-within .face-remove {
  opacity: 1;
  pointer-events: auto;
}
.face-own .face-remove:hover,
.face-own .face-remove:focus-visible {
  color: var(--ink);
}
.face-widget.body,
.face-widget.title {
  display: flex;
  align-items: center;
  width: auto;
  gap: 4px;
}
/* Keep the font button at the column edge even when no axes button is present. */
.face-widget.body > button:last-child,
.face-widget.title > button:last-child {
  margin-left: auto;
}
.controls .face-widget .face-axes-toggle {
  width: 26px;
  height: 26px;
  flex: none;
  font-family: var(--font-mono);
  font-size: 14px;
}
.face-axes-back {
  align-self: flex-end;
  margin-bottom: 10px;
  font-family: var(--font-mono);
}

/* the mailing icon over the add plus, only while a sync-panel button is hovered
   (hover-icon.js). The overlay is drawn from the plus's own strokes and takes its seat
   at the same instant the real plus steps aside, so the hand-off never shows. */
.hover-icon {
  position: fixed;
  left: 0;
  top: calc(var(--hline) - 17px);
  width: 34px;
  height: 34px;
  pointer-events: none;
  z-index: 12;
  display: none;
}
.hover-icon.on {
  display: block;
}
.hover-icon line {
  stroke: var(--ink);
  stroke-width: 1;
  stroke-linecap: square;
}
html.icon-live .hair-plus::before,
html.icon-live .hair-plus::after {
  background: transparent;
  transition: none;
}

/* Typed hover titles share the existing mono/dim palette; no layout participation. */
.type-tip {
  position: fixed;
  z-index: 100;
  pointer-events: none;
  white-space: nowrap;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: 9.5pt;
  line-height: 1.3;
  letter-spacing: 0.04em;
  color: var(--dim);
}
.tip-caret {
  display: inline-block;
  vertical-align: baseline;
  width: 1px;
  height: 0.8em;
  background: var(--palette-accent, #dc143c);
  opacity: 0;
}
.tip-caret.on { opacity: 1; animation: tip-caret-blink 1.2s ease-in-out infinite; }
@keyframes tip-caret-blink { 0%, 100% { opacity: 1; } 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .tip-caret { display: none; } }
/* The starting range and dash stay silent until a destination exists. */
.pdf-pick input:disabled, .pdf-pick-dash[data-disabled] { opacity: .35; pointer-events: none; }

/* a19 phone: controls stack in two columns when one does not fit; the page keeps clear of the awake rail */
@media (max-width: 700px), (max-height: 500px) {
  /* a74 (team spec F): one column that scrolls inside its box instead of wrapping into a second column over the text */
  .controls {
    flex-wrap: nowrap;
    max-height: calc(100vh - var(--ctl) - 14px);
    overflow-x: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    scrollbar-width: none;
    padding-left: 0;
  }
  .controls::-webkit-scrollbar { display: none; }
  .controls > * { flex: none; }
  /* members leave the scroll box: fixed, level with their head (ControlGroup sets top) */
  .ctl-members { position: fixed; right: 48px; }
  /* owner profile: two rings sit pinned at the bottom (bridge 52px, admin 8px, 34px each): keep the stack above them */
  :root:has(.instinct-bridge) .controls {
    max-height: calc(100vh - var(--ctl) - 14px - 88px);
  }
  /* soft fade where rings are clipped (flags set by controls.js) */
  :root.ui-awake .controls[data-more-up]::before,
  :root.ui-awake .controls[data-more-down]::after {
    content: ""; position: fixed; right: 8px; width: 46px; height: 22px; pointer-events: none; z-index: 1;
  }
  :root.ui-awake .controls[data-more-up]::before { top: var(--ctl); background: linear-gradient(var(--bg), transparent); }
  :root.ui-awake .controls[data-more-down]::after { bottom: 14px; background: linear-gradient(transparent, var(--bg)); }
  :root.ui-awake:has(.instinct-bridge) .controls[data-more-down]::after { bottom: 102px; }
}
@media (max-width: 700px) {
  .page { padding-right: calc(8px + 34px + 8px); }
  .plumb { left: calc(18px + min(var(--measure, 29em), 100vw - 18px - 50px) - 3px); }
}

@media (max-width: 700px) {
  .page.folder-surface { padding-left: 34px; padding-top: calc(var(--pin) - var(--mobile-head-correction, 0px)); }
  .folder-surface .story.open .story-head { top: calc(var(--pin) - var(--mobile-head-correction, 0px)); }
  .plumb { left: calc(34px + min(var(--measure, 29em), 100vw - 34px - 50px) - 3px); }
}

/* Each control follows the existing activity gate, with an independent timing on every cycle. */
.controls, :root.ui-awake .controls, :root.horizon-drag .controls { opacity: 1; transition: none; }
.controls > * { opacity: 0; pointer-events: none; transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms); }
:root.ui-awake .controls > *, :root.horizon-drag .controls > * { opacity: 1; pointer-events: auto; }
.plumb { transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms), height .26s ease, background-color .26s ease, filter .26s ease; }
.search-rail, :root.ui-awake .search-rail, .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)); }
:root.ui-awake .search-rail { visibility: visible; }
@media (prefers-reduced-motion: reduce) { .controls > *, .plumb, .search-rail, .admin-finder { transition-duration: 0s; transition-delay: 0s; } }

:root:has(.search-folder .search-rail.open) .horizon-control { z-index: 14; }
.hair-plus { opacity: 0; pointer-events: none; transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms); }
:root.ui-awake .hair-plus, :root.horizon-drag .hair-plus { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .hair-plus { transition-duration: 0s; transition-delay: 0s; } }

/* Wada colour shelf: the same quiet popup idiom as the font shelf, usable on a phone. */
.wada-panel.face-list { width: min(292px, calc(100vw - 70px)); max-height: min(490px, calc(100vh - 36px)); overflow-y: auto; padding: 10px; scrollbar-width: none; }
.wada-panel::-webkit-scrollbar { display: none; }
.wada-find { display: block; width: 100%; box-sizing: border-box; padding: 0 0 6px; border: 0; border-bottom: 1px solid var(--hairline); border-radius: 0; outline: none; background: none; color: var(--ink); caret-color: var(--palette-caret, #dc143c); font: inherit; }
.wada-edition { margin: 8px 0; font-size: 9px; line-height: 1.42; color: var(--dim); }
.wada-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px 8px; }
.controls .wada-chip { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; width: 100%; height: auto; border: 0; border-radius: 0; padding: 0; text-align: left; color: var(--dim); font: 9px/1.42 var(--font-mono); }
.wada-chip-colour { display: block; width: 100%; height: 24px; border: 1px solid var(--hairline); box-sizing: border-box; }
.wada-chip.selected .wada-chip-colour { outline: 1px solid var(--ink); outline-offset: 2px; }
.wada-chip-name { white-space: normal; }
.controls .wada-chip:hover, .controls .wada-chip:focus-visible { color: var(--ink); }
.controls .wada-reset { width: auto; height: auto; margin-top: 7px; border: 0; border-radius: 0; font: inherit; padding: 0; }

.wada-panel { align-items: stretch; box-sizing: border-box; }
.controls .wada-widget:focus-within { opacity: 1; }
.wada-panel { font: var(--fs-mono)/1.42 var(--font-mono); font-variation-settings: var(--fvs-mono); }
.controls .wada-panel .wada-find, .controls .wada-panel .wada-reset { font: inherit; }

.wada-panel.face-list { z-index: 30; }

/* Families keep their open/close gate, while each visible member joins the activity cycle independently. */
.controls > .ctl-group, :root.ui-awake .controls > .ctl-group { opacity: 1; pointer-events: none; }
.controls .ctl-head, .controls .ctl-members > * { opacity: 0; pointer-events: none; transition: opacity var(--ui-duration, 450ms) ease-in-out var(--ui-delay, 0ms); }
:root.ui-awake .controls .ctl-head, :root.ui-awake .controls .ctl-members > * { opacity: 1; pointer-events: auto; }
@media (prefers-reduced-motion: reduce) { .controls .ctl-head, .controls .ctl-members > * { transition-duration: 0s; transition-delay: 0s; } }

.controls:has(.wada-panel) { z-index: 40; }
/* The palette shelf must stay readable above the roaming logo's explicit z=101 layer. */
.controls:has(.wada-panel) { z-index: 120; }

/* The existing background ring now opens every personal colour state. */
.palette-choices { position:fixed; right:54px; top:14px; width:min(310px,calc(100vw - 76px)); max-height:calc(100dvh - 28px); overflow-y:auto; scrollbar-width:none; background:var(--bg); color:var(--ink); padding:8px; z-index:220; font:10pt var(--font-mono); }
.palette-choices::-webkit-scrollbar { display:none; }
.palette-row { display:flex; align-items:center; gap:8px; min-height:34px; }
.palette-choices button { font:inherit; color:inherit; border:0; border-radius:0; background:none; padding:6px 0; text-align:left; cursor:pointer; }
.palette-state { flex:1; min-width:0; }
.palette-toggle { color:var(--dim)!important; }
.palette-toggle[aria-pressed=true] { color:var(--ink)!important; }
.palette-editions { display:flex; gap:20px; margin:10px 0; }
.palette-editions button[aria-pressed=false] { color:var(--dim); }
.palette-choices input { width:100%; box-sizing:border-box; font:inherit; color:var(--ink); background:none; border:0; border-bottom:1px solid var(--hairline); padding:8px 0; outline:none; caret-color:var(--palette-caret,#dc143c); }
.palette-note { color:var(--dim); font-size:8pt; margin:10px 0; }
.palette-grid { display:grid; grid-template-columns:repeat(8,minmax(0,1fr)); gap:0; }
.palette-grid .palette-chip { display:block; padding:0; height:29px; width:100%; }
.palette-chip span { position:absolute; width:1px; height:1px; clip-path:inset(50%); overflow:hidden; }
.palette-chip:focus-visible,.palette-chip[aria-pressed=true] { outline:1px solid var(--ink); outline-offset:-3px; }
.palette-choices button:focus-visible { outline:1px solid var(--ink); }
.palette-choices button { width:auto!important; height:auto; min-height:28px; flex-shrink:0; line-height:1.3; white-space:normal; }
.palette-choices .palette-state { text-align:left; }
.palette-choices .palette-back { display:block; width:100%!important; }
.palette-choices .palette-editions button { flex:1; }
.palette-grid .palette-chip { width:100%!important; min-height:29px; height:29px; }
.controls:has(.palette-choices) { z-index:220; opacity:1; pointer-events:auto; }
.palette-choices .palette-state { display:block; width:auto!important; text-align:left!important; justify-content:flex-start; }
.palette-choices .palette-back,.palette-editions button { text-align:left!important; justify-content:flex-start; }
.palette-state-buttons { position:fixed; right:54px; top:calc(var(--hline) - 3px - 8px); max-height:calc(100dvh - var(--hline) + 3px + 8px - 14px); overflow-x:hidden; overflow-y:hidden; scrollbar-width:none; display:flex; flex-direction:column; align-items:center; gap:8px; padding:8px 4px 0; touch-action:none; } /* the 8px padding is the dice tumble's room; the column rises 8px so the dice top stays 3px over the horizon */
.palette-state-buttons::-webkit-scrollbar { display:none; }
.controls .palette-state-dot { width:26px; height:26px; min-height:26px; flex:none; border:1px solid var(--dim); border-radius:50%; padding:0; position:relative; }
.controls:has(.palette-active) { z-index:220; opacity:1; pointer-events:auto; }
.palette-choices { right:94px; width:min(310px,calc(100vw - 116px)); }
.palette-choices { box-sizing:border-box; }
.type-tip { z-index:300; }
.controls .palette-random { display:flex; justify-content:center; align-items:center; width:26px; height:26px; flex:none; min-height:26px; padding:0; border:0; border-radius:0; background:none; color:var(--dim); }
.controls .palette-random:hover,.controls .palette-random:focus-visible { color:var(--ink); }
/* A small tumble settles back to the same 1-2-3 corner; no palette draw on hover. */
.palette-random svg { overflow:visible; transform-origin:50% 60%; }
.palette-random:hover svg,.palette-random:focus-visible svg { animation:wada-dice-tumble 680ms cubic-bezier(.3,.05,.3,1) both; }
@keyframes wada-dice-tumble {
  0% { transform:translateY(0) rotate(0) scale(1); }
  22% { transform:translateY(-4px) rotate(-22deg) scale(1.02); }
  48% { transform:translateY(-6px) rotate(20deg) scale(.95,1.05); }
  72% { transform:translateY(1px) rotate(-7deg) scale(1.06,.94); }
  100% { transform:translateY(0) rotate(0) scale(1); }
}
@media(prefers-reduced-motion:reduce) { .palette-random:hover svg,.palette-random:focus-visible svg { animation:none; } }

.controls .palette-random { height:30px; min-height:30px; }
.controls .palette-random:hover,.controls .palette-random:focus-visible { color:var(--dim); }
/* Middots gain a little body while the dice tumbles, without gaining brightness. */
.palette-random svg text { stroke:currentColor; stroke-width:0; paint-order:stroke fill; transition:stroke-width 280ms ease-in-out; }
.palette-random:hover svg text,.palette-random:focus-visible svg text { stroke-width:.35px; }
@media(prefers-reduced-motion:reduce) { .palette-random svg text { transition:none; } .palette-random:hover svg text,.palette-random:focus-visible svg text { stroke-width:0; } }

/* a tip that stands up from its anchor: reads bottom to top, growing upward from its foot */
.type-tip.tip-up { transform-origin: 0 100%; transform: rotate(-90deg); }

/* Colour library: the block opens a second column of the other states to the left, the way a rail family
   opens its members (right-aligned, 10px beside the opener's column, fading in with a 6px slide). */
.controls .palette-state-dot.palette-group-start { margin-top:8px; }
.controls .palette-state-dot.palette-group-start::before { content:"\00b7"; position:absolute; left:0; right:0; top:-8px; transform:translateY(-50%); text-align:center; font:16px/1 var(--font-mono); font-variation-settings:var(--fvs-mono); color:var(--dim); pointer-events:none; }
.controls .palette-state-dot.sub { border-color:var(--hairline); }
.controls .palette-lib { display:flex; align-items:center; justify-content:center; width:27px; height:27px; min-height:27px; flex:none; padding:0; border:0; border-radius:0; background:none; cursor:pointer; box-sizing:border-box; }
.controls .palette-lib .palette-mini { display:grid; grid-template-columns:repeat(2,13.5px); grid-template-rows:repeat(2,13.5px); gap:0; pointer-events:none; }
.controls .palette-lib .palette-mini-dot { display:block; width:13.5px; height:13.5px; border-radius:50%; box-sizing:border-box; border:1px solid var(--hairline); }
.controls .palette-lib { opacity:.9; transition:opacity .25s ease; }
.controls .palette-lib:hover, .controls .palette-lib:focus-visible, .controls .palette-lib.on { opacity:1; }
.palette-drawer-col { position:fixed; right:96px; top:0; overflow-x:hidden; overflow-y:hidden; display:flex; flex-direction:column; align-items:center; gap:8px; padding:0 4px; scrollbar-width:none; touch-action:none; opacity:0; visibility:hidden; pointer-events:none; transform:translateX(6px); transition:opacity .25s ease, transform .25s ease, visibility 0s linear .25s; }
.palette-drawer-col.open { opacity:1; visibility:visible; pointer-events:auto; transform:none; transition:opacity .25s ease, transform .25s ease; }
.palette-drawer-col::-webkit-scrollbar { display:none; }
@media(prefers-reduced-motion:reduce) { .palette-drawer-col { transition:none; transform:none; } }
.palette-widget.palette-drawer-open .palette-choices { right:140px; width:min(310px,calc(100vw - 162px)); }

/* the size fields' plus and minus: the page plus drawn at the same hairline weight (pages.css .hair-plus),
   the minus is its horizontal stroke alone. They sit to the left of the ring. */
.size-step { display: flex; align-items: center; gap: 10px; }
.controls button.step-btn {
  display: block;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 0;
  border-radius: 0;
  background: none;
  color: inherit;
  font-size: 0;
}
.step-btn::before,
.step-btn::after {
  content: "";
  position: absolute;
  background: var(--hairline);
  transition: background 0.2s ease;
}
.step-btn::before { left: 0; top: 17px; width: 34px; height: 1px; }
.step-btn.step-plus::after { left: 17px; top: 0; width: 1px; height: 34px; }
.step-btn.step-minus::after { display: none; }
.controls button.step-btn:hover::before,
.controls button.step-btn:hover::after,
.controls button.step-btn:focus-visible::before,
.controls button.step-btn:focus-visible::after { background: var(--ink); }
.controls button.step-btn:disabled:hover::before,
.controls button.step-btn:disabled:hover::after { background: var(--hairline); }

/* the fixed index middot: x on the title middots' vertical (page padding + index inset + the number's
   first slot, the same offset .story-head .fold-dot uses), y at the bottom end of the index tick's line
   (the tick hangs 34px from the top edge). It stays; a click hides or shows the index rows. Desktop only,
   like the tick it hangs from. */
.idx-toggle {
  position: fixed;
  z-index: 11;
  top: 23px;
  height: 20px;
  left: calc(48px + var(--index-inset, 11px) + 1ch + 0.04em);
  width: 1ch;
  box-sizing: border-box;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  margin: 0;
  background: none;
  border: 0;
  cursor: pointer;
  font-family: var(--font-mono);
  font-variation-settings: var(--fvs-mono);
  font-size: var(--fs-mono);
  letter-spacing: 0.04em;
  color: var(--ink);
}
.idx-toggle:focus-visible { outline: none; }
/* morse easter egg (hover): dim base while the Web Animations Morse timeline runs; no transition so the timing stays exact */
.idx-toggle.morse { opacity: 0.15; transition: none; }
/* phone: the same middot on the same axis (the title middots' vertical, the page's left edge here is 34px, the
   index has no inset on a phone); there is no tick above it, so it stays at the top edge like the desktop one.
   A touch needs more than one character of target: an invisible 44px square carries the tap. */
@media (max-width: 700px) {
  .idx-toggle { left: calc(34px + 1ch + 0.04em); }
}
@media (max-width: 700px), (hover: none) {
  .idx-toggle::before { content: ""; position: absolute; left: 50%; top: 50%; width: 44px; height: 44px; transform: translate(-50%, -50%); }
  .idx-toggle:active { opacity: .6; }
}
@keyframes idx-erase { from { clip-path: inset(0 var(--idx-r, 0px) 0 0); } to { clip-path: inset(0 100% 0 0); } }
@keyframes idx-fade-in { from { opacity: 0; } }
html.idx-out .story-head > .gutter,
html.idx-out .story-head .story-title,
html.idx-out .story-head .vrow:not(.add),
html.idx-out .story-head-main > .story-when,
html.idx-out .story-head .draft-remove { animation: idx-erase 160ms steps(var(--idx-n, 8), end) var(--idx-d, 0ms) both; pointer-events: none; }
html.idx-in .story-head > .gutter,
html.idx-in .story-head .story-title,
html.idx-in .story-head .vrow:not(.add),
html.idx-in .story-head-main > .story-when,
html.idx-in .story-head .draft-remove { animation: idx-fade-in 240ms ease var(--idx-d, 0ms) backwards; }
@media (prefers-reduced-motion: reduce) {
  html.idx-out .story-head > .gutter, html.idx-out .story-head .story-title, html.idx-out .story-head .vrow:not(.add),
  html.idx-out .story-head-main > .story-when, html.idx-out .story-head .draft-remove,
  html.idx-in .story-head > .gutter, html.idx-in .story-head .story-title, html.idx-in .story-head .vrow:not(.add),
  html.idx-in .story-head-main > .story-when, html.idx-in .story-head .draft-remove { animation-duration: 1ms; animation-delay: 0s; }
}

/* a20 phone: the opened members float over the reading text. Each ring and the plus/minus pair take the page
   colour as a fill, and the page recedes while a group is open, so the text does not run through them. On touch there is no hover to light a stroke,
   so strokes rest at the dim ink and the pressed one takes the ink. */
@media (max-width: 700px), (max-height: 500px) {
  .controls button, .controls .size-field { background: var(--bg); }
  .page { transition: opacity .35s ease; }
  :root:has(.controls .ctl-group.open) .page { opacity: .3; }
  .size-step { background: var(--bg); border-radius: 17px; padding: 0 3px; margin: 0 -3px; }
  .controls button.step-btn { background: none; }
}
@media (hover: none) {
  .step-btn::before, .step-btn::after { background: var(--dim); }
  .controls button.step-btn:active::before, .controls button.step-btn:active::after { background: var(--ink); }
  .controls button.step-btn:disabled::before, .controls button.step-btn:disabled::after { background: var(--hairline); }
}

/* a20 phone: a narrow screen (320) left no room for the title beside its number, so the title block dropped
   under the gutter and the number hung out of the page's left edge. The reading head takes the same flex the
   draft head has: the title takes what is left beside the gutter and wraps inside it. */
@media (max-width: 700px) {
  .story-head { display: flex; align-items: flex-start; }
  .story-head > .gutter { flex: none; }
  .story-head > .story-head-main { flex: 1 1 0; min-width: 0; display: block; }
}

/* The layout family stays below the open search row on short viewports. */
.layout-wrap .ctl-members {
  max-height: calc(100dvh - 28px - env(safe-area-inset-bottom, 0px));
  overflow-y: auto;
  overflow-x: hidden;
  overscroll-behavior: contain;
  touch-action: pan-y;
  scrollbar-width: none;
}
.layout-wrap .ctl-members::-webkit-scrollbar { display: none; }

/* a113 short windows: an open member column stacks above the always-present search row (they share the horizon band); only the buttons take the pointer */
@media (max-height: 500px) {
  .ctl-group.open .ctl-members { z-index: 20; pointer-events: none; }
  .ctl-group.open .ctl-members > * { pointer-events: auto; }
}
