/* sv3v2.css — SV3 · NOTES FOCUS DRAWER v3, task #7154 / walk 48 repair.
   #7207 follow-up (2026-09-04): THE THREE-COLUMN BAND IS DELETED. READ THIS FIRST.

   ══ WHAT THE DRAWER IS NOW · ONE VERTICAL STACK, ON EVERY SURFACE ══════════
   Founder, verbatim: "that drawer in the app is so ugly. i hate how its like
   main drawer | comments/designs/suggestions buttons | teleport stuff... IT
   SHOULD NOT HAVE COLUMNS, we have the main drawer then below we have little
   buttons to show comments, show designs (and teleport options here), and
   suggestions on the bottom of the main drawer."

   So the drawer is, top to bottom, at every width and every height:
     1. THE NOTE   — the identity head and the note field.
     2. THE BUTTON ROW — three LITTLE BUTTONS (COMMENTS · DESIGNS · SUGGESTIONS)
        in one horizontal row under the note, each carrying its live count.
     3. THE OPENED SECTION — reveals directly under the button row; one open at
        a time. TELEPORT LIVES INSIDE THE DESIGNS SECTION: the Teleport up /
        Update lays / Teleport down verbs and their reasons sit above the
        designs list, painted there by sv3-notes-drawer-teleport.js. There is
        no teleport cell of its own any more.
     4. THE DELETE ROW — pinned to the bottom; the drawer's slack sits above it.

   ── WHY THE GRID DIED, AND WHY IT IS NOT COMING BACK ──────────────────────
   Until #7207 the band form factor (`ff-h` without `tight`: any drawer under
   420px tall and 560px or wider — i.e. the app's resting dock at EVERY desktop
   width) was a 3-column CSS grid: IDENT+NOTE at a fixed `--idw` 300px · the
   accordion in a 1fr middle · TELEPORT at a fixed `--tpw` 240px. The other two
   form factors (`ff-side`, the browser's side column; `ff-h tight`, the narrow
   band) were already this vertical stack. So this change DELETES one form
   factor rather than inventing one — and that grid was the cause of most of
   walk 48's defects, because it created WIDTH CONTENTION that a stack cannot
   have:
     · two fixed-width outer cells starved the middle to 60px at a 600px band,
       and the summary rows rendered COMME / DESIG / SUGGE, clipped mid-word
       (walk 48 defect 3) — it survived every self-truncation check because
       `.nsd-sum .nm` is flex-shrink:0 and overflows its PARENT;
     · the teleport cell competed with the comment thread for the drawer's
       HEIGHT, which is what forced the four compaction levels (211/103/77/25px
       at the founder's cell), the WHY affordance, the RULING 1-C lift, the
       height cap that #7207 tried and reverted (642-800 DOM mutations/sec: a
       bistable layout across a level boundary), and the "4 comments vs 3"
       trade ORCH had to rule on;
     · three 22px summary rows plus a pinned cell cost ~90px of a 407px dock
       before one comment was shown — ONE whole comment was the arithmetic
       ceiling at the founder's own window.
   A vertical stack has no width contention to arbitrate: every region gets the
   full width, the three rows become one 34px row, and the teleport cell's
   25-211px go back to the section the founder opened. Nothing here reads a
   form factor class for LAYOUT any more: `ff-h`, `ff-side` and `tight` are
   still stamped by notes-<gen> (write-once) and are simply inert. The width
   rules that used to hang off `ff-h tight` hang off `nsd-narrow`, which NSD-FIT
   writes from the box's own clientWidth.

   ══ THE LAW THIS FILE ENFORCES ═════════════════════════════════════════════
   The founder's rule, 2026-09-02, has TWO clauses and they are read together:
     (1) "ALL INFO IN THAT NOTE FOCUS DRAWER MUST BE VISIBLE AT A GLANCE"
     (2) "NO SCROLL BAR ON NOTES FOCUS DRAWER ON EITHER APP OR BROWSER FOR ANY
          SV LEVEL"
   Clause (2) constrains HOW (1) is satisfied. It is NOT permission to delete
   content, and it is NOT permission to paint a scrollbar out.
     A region may render SMALLER than its content ONLY IF a visible, labelled
     pager lives in that region and can reach every hidden part.
     · Silent clipping is a BUILD FAILURE.
     · `overflow:hidden` with scrollHeight > clientHeight and no pager IS THE
       BUG. Not a styling detail — the bug itself.
     · `::-webkit-scrollbar{width:0;height:0}` is BANNED in this subtree: it
       hides evidence. The one copy in the notes-<gen>.jsx injected sheet (an
       immutable asset) is DELETED FROM THE CSSOM AT RUN TIME by NSD-FIT.
     · A REFUSED LAY IS NEVER HIDDEN (walk 48 defect 10). With teleport inside
       the DESIGNS section, the refusal is ANNOUNCED on the DESIGNS button
       itself (`.nsd-sum-flag`, written by the teleport module) while the
       section is closed, and the sentence is whole inside it when open.

   ── ALLOCATION PRIORITY when space is short ───────────────────────────────
   Implemented in sv3-notes-drawer-teleport.js (§ NSD-FIT), which measures and
   writes the custom properties this file consumes. Nothing here guesses a
   number. Earlier items keep their pixels first:
     1. NOTE TEXT — minimum 3 WHOLE lines; its client box is ALWAYS an integer
        multiple of its line-height (the air is BORDER, not padding — see § the
        note). Overflow goes to the shipped "Show rest" pager, whole lines.
     2. THE BUTTON ROW — always fully visible and hit-testable. Navigation.
     3. THE OPEN SECTION BODY — the rest, minimum ONE WHOLE item, then a
        counted pager ("1–2 of 4") for whatever it cannot show. The teleport
        verbs are part of the DESIGNS body and are sized with it.
     4. DELETE ROW — above any fixed chrome, never underneath it.
   Slack, when there is any, goes back UP the ladder to the note in whole lines;
   what the note cannot spend sits above the pinned delete row.

   ── WHY NO REGION'S HEIGHT IS WRITTEN AS A CONSTANT ───────────────────────
   v2.1 carried fifteen hand-measured pixel constants, each correct for exactly
   one viewport and one state. The matrix is 8 viewports × 4 accordion states ×
   2 content shapes × 2 surfaces × 2 rail states. Heights come from measurement
   at run time, and the engine converges in at most seven passes and then
   STOPS (a pass that decides the same allocation twice is the last one).

   SCOPE: everything is under .nsd-drawer.sv3-hero. SV1/SV2 keep the rail they
   shipped with (version-consistency rule: one implementation adopted per rung,
   never a fork). Un-gating is deleting `.sv3-hero` from these selectors. */

.nsd-drawer.rail.sv3-hero {
  --ms: var(--ndt-ms, 170ms);
  --bg-row-h: var(--bg-row-hover, #3A3B43);
  /* the fit engine's outputs. The fallbacks are only what renders in the one
     frame before the first measurement lands; nothing steady-state uses them. */
  --nsd-note-h: auto;
  --nsd-secs-h: auto;
  --nsd-body-h: auto;
  --nsd-thread-h: auto;
  /* the note field's vertical AIR (border, not padding — § the note): its base
     per compaction tier, plus the sub-line residual the engine could not spend
     anywhere else (§ write / roomToType in the engine). */
  --nsd-air-base: 9px;
  --nsd-air-t: 0px;
  --nsd-air-b: 0px;
  min-height: 0;
}
@media (prefers-reduced-motion: reduce) { .nsd-drawer.rail.sv3-hero { --ms: 0ms } }

/* ══ EVIDENCE IS NEVER PAINTED OUT ═════════════════════════════════════════
   notes-<gen>.jsx (WRITE-ONCE, cannot be edited in place) injects
   `.nsd-drawer.rail.sv3-hero::-webkit-scrollbar{width:0;height:0}` into
   #nsd-styles, which is appended to <head> after every <link> and therefore
   beats an equal-specificity rule here.
   Out-specifying it was NOT ENOUGH and the gate proved it: 128 of 128 cells
   red on assertion F, because the banned rule was still IN the sheet — one
   added class away from winning again, and readable by anyone auditing the
   CSSOM as proof that this subtree still paints its evidence out. NSD-FIT
   (§ unbanScrollbars) now DELETES that rule from the live sheet instead; the
   immutable file is never touched. These three are what remains, and they are
   the positive statement: if a scrollbar ever appears in this drawer it is a
   defect, and it must be SEEN. */
.nsd-drawer.rail.sv3-hero.nsd-v2::-webkit-scrollbar,
.nsd-drawer.sv3-hero.nsd-v2 .nsd-txt::-webkit-scrollbar,
.nsd-drawer.sv3-hero.nsd-v2 .nsd-thread::-webkit-scrollbar {
  width: 9px; height: 9px;
}
.nsd-drawer.rail.sv3-hero.nsd-v2::-webkit-scrollbar-thumb,
.nsd-drawer.sv3-hero.nsd-v2 .nsd-txt::-webkit-scrollbar-thumb,
.nsd-drawer.sv3-hero.nsd-v2 .nsd-thread::-webkit-scrollbar-thumb {
  background: var(--line-strong); border-radius: 5px;
}
/* and the drawer itself: it must never be the thing that scrolls. If the fit
   engine has done its job this is unreachable; if it has not, `nsd-overflow`
   below makes the failure loud instead of silent. */
.nsd-drawer.sv3-hero.nsd-v2 { overflow: hidden; min-height: 0 }

/* ══ RULING 1-C ON THE BROWSER SURFACE · THE DRAWER CLAIMS ITS COLUMN ══════
   ORCH, walk 48 round 4: "It applies to BOTH surfaces. The browser currently
   expands in 0 of 8 cells; that is the bug."

   MEASURED, 2026-09-03, closed vs COMMENTS-open, IDENTICAL RECTS in all eight:
     1280x800  [888,240,392,560] · 1440x900  [1048,240,392,660]
     1500x900  [1108,240,392,660] · 1920x1200 [1528,240,392,960]
   RULING 1 shipped as a `layout-v` rule in drawer-bottom.css — the bottom dock
   — and the browser surface is `layout-h`, a side rail, so not one line of it
   was ever reachable there. NSD-FIT was publishing `--nsd-open-h: 1082px` at
   1280x800 into a stylesheet that had nothing to read it.

   WHAT THE 240px ABOVE THE DRAWER ACTUALLY IS, measured at 1280x800:
     header.ss-topbar   [0,  0,1280, 78]   the app's own chrome
     div.ss-master-timeline [0, 78,1280,162]   the waveform / cue strip
     div.ns-wrap        [0,240,1280,560]   ← the drawer's flex line starts here
   162 of those 240 are content the founder is not looking at while he reads one
   note's comments; the other 78 are the app's fixed chrome. This rule claims
   the 162 and leaves the 78, which is the SAME trade the app surface makes:
   the founder's own arithmetic for his 780x848 window counts the 89px header
   and the 67px footer as immovable and puts the target at 848 − 89 − 67 = 692.
   The chrome is chrome on both surfaces; the content column is what the drawer
   takes. At 1280x800 that is 78 → 800, i.e. 722px against today's 560.

   THE MECHANISM IS A NEGATIVE CROSS-AXIS MARGIN, AND IT IS CHOSEN PRECISELY
   BECAUSE IT CANNOT FEED BACK. `.ns-mainwrap.layout-h` is a ROW: the drawer's
   height comes from `align-items: stretch`, which is the flex line's cross size
   MINUS the item's cross-axis margins. A margin-top of −162px therefore makes
   the drawer 722px tall and starts it 162px higher, and its OUTER cross size —
   722 + (−162) = 560 — is bit-for-bit what it was before. So the flex line
   cannot notice, `.ns-mainwrap` does not move, `.ns-main` does not change width
   or height, and the number this rule reads is not a function of anything this
   rule changes. An absolutely-positioned drawer would have been the obvious
   alternative and is the wrong one: it leaves `.nsd-slot` with no in-flow child,
   the slot collapses to 0px wide, and the cue list re-flows across the full
   1280 every time a section opens.

   ⛔ ROUND 5 CORRECTS THE PARAGRAPH ABOVE. "162 of those 240 are content the
   founder is not looking at" WAS NEVER MEASURED, AND IT IS FALSE. Those 162px
   are div.ss-master-timeline and they carry live controls. Measured on the
   rich fixture with COMMENTS open: overlap 392x162 at 1280x800, 1440x900 and
   1500x900 and 392x122 at 1920x1200; mtCoveredPx 0 -> 63504; and at 1280x800
   the Ingest button's rect [1103,209,62,24] is bit-for-bit unchanged in both
   states while elementFromPoint at its centre returns BUTTON.nt-btn closed and
   TEXTAREA.nsd-txt open. Export and the '?' the same. Three live controls dead,
   because a premise was asserted instead of measured. ORCH's round 5 ruling:
   "NOTHING YOU NEED MAY BE COVERED, EVEN AT THE COST OF THE FOURTH COMMENT."

   `--nsd-lift` IS WRITTEN BY NSD-FIT (§ publishLift / § spaceCeiling), not by
   CSS, and it is now capped at the MEASURED BOTTOM EDGE OF WHATEVER ALREADY
   OWNS THE SPACE above the drawer's flex line — found by walking `.ss-stage`
   for the visible boxes that overlap this rail's own column and end at or above
   that line, and taking the lowest of them. On today's layout that box is the
   master timeline and its bottom is the flex line itself, so the free space is
   0, the rail does not climb, and the strip and its three controls are never
   covered in any state at any width. No constant encodes 162 or 240: remove
   the strip and the rail climbs to the stage's own top; add another and it
   stops under that one. It is additionally capped at what the open section
   actually asks for, so a drawer that needs 80px does not claim more and sit on
   air (assertion S). Nothing is published while no section is open, so
   `var(--nsd-lift, 0px)` is 0 and this rule is inert — which is what "closing
   the section restores everything" means here.

   z-index 2 is the ONLY thing that says "over", and it is stated rather than
   inherited from tree order so that a future z-index on the master timeline
   cannot silently put the founder's comments underneath a waveform. */
.ns-mainwrap.layout-h > .nsd-slot > .nsd-drawer.rail.sv3-hero.sec-open {
  margin-top: calc(-1 * var(--nsd-lift, 0px));
  z-index: 2;
  transition: margin-top var(--ms, 170ms) ease;
}
@media (prefers-reduced-motion: reduce) {
  .ns-mainwrap.layout-h > .nsd-slot > .nsd-drawer.rail.sv3-hero.sec-open { transition: none }
}

/* ── the note ──────────────────────────────────────────────────────────────
   THE AIR IS BORDER, NOT PADDING, and that is the whole fix for the sliced
   glyphs. A textarea's clientHeight includes its vertical padding, so
   `height = 4 lines + 22px of padding` gave a 4.06-line client box: the pager
   moves the view by clientHeight, so every page after the first started
   0.06 of a line low and the founder saw letters cut through their middle.
   Border is OUTSIDE clientHeight. With vertical padding at zero the client box
   is exactly `lines × line-height`, the pager lands on line boundaries, and the
   9px of visual air is drawn by a border painted in the field's own background.
   The 1px frame is an outline (no layout cost) so the two cannot fight.
   line-height is an INTEGER px for the same reason: 1.55 × 13.5 = 20.925 could
   never be multiplied into a whole number of pixels. */
.nsd-drawer.sv3-hero .nsd-note { flex: 0 0 auto; min-height: 0; min-width: 0 }
.nsd-drawer.sv3-hero.nsd-v2 .nsd-txt,
.nsd-drawer.sv3-hero .nsd-txt {
  line-height: var(--nsd-lh, 20px);
  padding: 0 12px;
  border: 9px solid var(--bg-deep);
  border-left-width: 1px; border-right-width: 1px;
  /* THE RESIDUAL LIVES IN THE FIELD'S AIR, NOT ABOVE THE DELETE ROW. When the
     ladder is paging something and has a few pixels left that no region can
     spend whole (under one 20px line; under one comment), those pixels used
     to sit as a band of nothing above the pinned delete row — 25-45px once the
     paddings either side were added, in 17 cells of the old layout, while a
     pager in the same drawer said there was no room (assertion S). The engine
     now splits that residual into the field's top and bottom border, which is
     the field looking a little taller and its text no less whole: border is
     OUTSIDE clientHeight, so the whole-line guarantee is untouched. Nothing is
     written while nothing pages. */
  border-top-width: calc(var(--nsd-air-base, 9px) + var(--nsd-air-t, 0px));
  border-bottom-width: calc(var(--nsd-air-base, 9px) + var(--nsd-air-b, 0px));
  outline: 1px solid var(--line);
  outline-offset: -1px;
  border-radius: var(--r-3, 4px);
  height: var(--nsd-note-h, auto);
  /* `flex: 0 0 auto` IS THE WHOLE-LINE GUARANTEE. `.nsd-note` is a flex column,
     so the default `flex-shrink: 1` let the engine's measured height be treated
     as a maximum and shrunk to a fractional one: measured at the founder's own
     780x848 config, a written 267px box used 208.5px and gave a 9.55-line
     client box — the sliced glyphs again, arrived at by a different road. The
     box is the height it is told, and the ladder above it is what decides
     whether that height fits. */
  flex: 0 0 auto;
  /* …and `min-height: 0` with it. A flex item's AUTOMATIC minimum size is its
     content-based minimum, and a <textarea rows="3"> reports three rows as
     that minimum — so the engine could write 34px and the browser would still
     use 58px, and the note box was 2.40 lines however carefully the height was
     computed. This is the second half of the whole-line guarantee; without it
     the first half is arithmetic the layout ignores. */
  min-height: 0;
  max-height: none;
  /* clipped, yes — but ONLY because .nsd-notepg is mounted beside it and can
     reach every line. That is the whole of the licence this file grants. */
  overflow: hidden;
  resize: none;
}
.nsd-drawer.sv3-hero .nsd-txt:focus {
  border-color: var(--bg-deep);
  outline-color: var(--ss-accent-line);
}
/* the pager is chrome for the note, so it is never the thing that is dropped */
.nsd-drawer.sv3-hero .nsd-notepg {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px; padding: 2px 0 2px;
  font-family: var(--mono); font-size: var(--ep-fs-kbd, 10.5px);
  letter-spacing: .06em; color: var(--fg-dim);
}
.nsd-drawer.sv3-hero .nsd-notepg-n { opacity: .85 }
.nsd-drawer.sv3-hero .nsd-notepg-b {
  border: 1px solid var(--line); background: transparent; color: var(--fg-mute);
  border-radius: var(--r-1, 3px); padding: 0 6px; height: 17px; line-height: 15px;
  font: inherit; cursor: pointer; flex: 0 0 auto;
}
.nsd-drawer.sv3-hero .nsd-notepg-b:disabled { opacity: .4; cursor: default }
.nsd-drawer.sv3-hero .nsd-notepg-b:not(:disabled):hover {
  color: var(--fg-strong); border-color: var(--line-strong, var(--line));
}

/* ── the section stack: ONE ROW OF LITTLE BUTTONS, then the opened body ────
   PRIORITY 2. The three buttons are NAVIGATION, not slack. They are content-
   sized pills (`flex: 0 0 auto`, never shrunk — a button that does not fit the
   row WRAPS to a second row rather than clipping its own label, which is how
   COMME / DESIG / SUGGE shipped under the grid), in one wrapping flex row. The
   opened body is a full-width item that wraps under them (`order: 1`), so in
   DOM order [button, body, button, body, button, body] the three buttons still
   render first and the one un-hidden body renders below the row.
   NSD-FIT measures this container's chrome as `secs.offsetHeight − the open
   body's offsetHeight` (with every engine property at `auto`), so a row that
   wraps at a narrow band is charged at its real height, never at a constant.
   The body's height is written by the engine (`--nsd-body-h`, border-box) and
   the container's with it; the row itself is never sized by anything but its
   own buttons. */
.nsd-drawer.sv3-hero .nsd-secs {
  flex: 0 0 auto; min-height: 0;
  display: flex; flex-flow: row wrap; align-items: flex-start; align-content: flex-start;
  column-gap: 6px; row-gap: 0;
  padding: 0 10px;
  height: var(--nsd-secs-h, auto);
  border-top: 1px solid var(--line);
  background: var(--bg-app); overflow: hidden;
}
.nsd-drawer.sv3-hero .nsd-sum {
  order: 0; flex: 0 0 auto; min-width: 0; width: auto;
  display: inline-flex; align-items: center; gap: 5px;
  height: var(--nsd-sum-h, 22px); min-height: var(--nsd-sum-h, 22px);
  margin: 6px 0;
  padding: 0 8px; background: var(--bg-panel); color: var(--fg); cursor: pointer;
  border: 1px solid var(--line); border-radius: var(--r-2, 4px);
  text-align: left; font-family: var(--ui, inherit); white-space: nowrap;
}
.nsd-drawer.sv3-hero .nsd-sum:hover { background: var(--bg-row-h); border-color: var(--line-strong, var(--line)) }
.nsd-drawer.sv3-hero .nsd-sum.on {
  background: var(--bg-sub); border-color: var(--line-strong, var(--line));
}
.nsd-drawer.sv3-hero .nsd-sum:focus-visible { outline: 2px solid var(--lime, #CCDE49); outline-offset: -2px }
.nsd-drawer.sv3-hero .nsd-sum .car {
  width: 8px; flex-shrink: 0; color: var(--fg-dim); display: inline-flex;
  transition: transform var(--ms); font-size: 11px; line-height: 1;
}
.nsd-drawer.sv3-hero .nsd-sum.on .car { transform: rotate(90deg); color: var(--fg-mute) }
.nsd-drawer.sv3-hero .nsd-sum .nm {
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .14em;
  text-transform: uppercase; color: var(--fg-mute); flex-shrink: 0;
}
.nsd-drawer.sv3-hero .nsd-sum.on .nm { color: var(--fg-strong) }
.nsd-drawer.sv3-hero .nsd-sum .ct {
  font-family: var(--mono); font-size: 9.5px; font-feature-settings: "tnum" 1;
  color: var(--fg-dim); flex-shrink: 0;
}
/* THE PREVIEW ECHO STANDS DOWN ON A LITTLE BUTTON, at every width. It is a
   SECOND rendering of a comment that lives whole in the thread one click below
   this button, behind a button that already carries the section's name AND
   its live count — ORCH ruling 4(a)'s condition, met. (Under the grid it was
   measured cut mid-word at 119 of 177px, and a pill has no room for it at any
   band.) */
.nsd-drawer.sv3-hero .nsd-sum .pv { display: none }
/* #7141's mode whisper rides the SUGGESTIONS button; it is a whisper, never a
   shout. The rail's own head is display:none on this surface, so this is the
   one place the mode is stated while the section is closed. */
.nsd-drawer.sv3-hero .nsd-sum .nsd-word-mode {
  margin-left: 0; flex-shrink: 0; white-space: nowrap;
  font-family: var(--mono); font-size: 8.5px;
  letter-spacing: .06em; font-style: normal; text-transform: lowercase; opacity: .62;
}
.nsd-drawer.sv3-hero .nsd-sum .nsd-word-mode.clarify { opacity: .95; color: var(--fg-mute) }
/* ── A REFUSED LAY IS ANNOUNCED ON THE DESIGNS BUTTON ──────────────────────
   Teleport lives inside the DESIGNS section now, so with that section closed
   the sentence explaining a refused `Update lays from PT` is behind a click.
   Walk 48 defect 10 — "a failure is never hidden" — is kept by the teleport
   module writing this flag onto the DESIGNS button the moment a lay is refused
   and removing it the moment it is not (sv3-notes-drawer-teleport.js
   § flagDesigns). A founder who never clicks still knows; the reason is one
   click away, which is the whole of what the pager contract asks. Danger ink,
   because it is a failure and not a count. */
.nsd-drawer.sv3-hero .nsd-sum .nsd-sum-flag {
  flex-shrink: 0; white-space: nowrap;
  font-family: var(--mono); font-size: 8.5px; letter-spacing: .08em;
  text-transform: lowercase; font-style: normal;
  color: var(--st-danger, #B46868);
}
.nsd-drawer.sv3-hero .nsd-sum .nsd-sum-flag::before { content: '· '; color: var(--fg-dim) }
/* the mark form (the module writes "!" when the drawer is under 560px — the
   words would wrap the row and cost the thread a comment): a red exclamation
   in a hairline ring, still danger ink, still titled and labelled. */
.nsd-drawer.sv3-hero .nsd-sum .nsd-sum-flag.is-mark {
  display: inline-flex; align-items: center; justify-content: center;
  width: 13px; height: 13px; border-radius: 50%;
  border: 1px solid var(--st-danger, #B46868);
  font-size: 9px; font-weight: 700; line-height: 1; letter-spacing: 0;
}
.nsd-drawer.sv3-hero .nsd-sum .nsd-sum-flag.is-mark::before { content: none }
/* ── THE ROW STAYS ONE ROW AT THE FOUNDER'S OWN CELL ───────────────────────
   Measured at app 780x848 with the SFX rail open (a 354px drawer, 334px of
   row): COMMENTS 104 + DESIGNS 97 + SUGGESTIONS 160 + two 6px gaps = 373, so
   SUGGESTIONS wrapped to a second line and the row cost 68px instead of 34 —
   a third of a comment. Under `nsd-narrow` (NSD-FIT, clientWidth < 560) the
   three buttons drop the caret (the open state is already the filled button
   and its strong label), 2px of side padding each and 1px of gap: 39 + 12 + 2
   = 53px, and the row is 320px in 334. Every label, count and the mode
   whisper stay whole; a wrap remains LEGAL below that (the engine measures
   the block), it is just no longer spent where the founder works. */
.nsd-drawer.sv3-hero.nsd-narrow .nsd-secs { column-gap: 5px }
.nsd-drawer.sv3-hero.nsd-narrow .nsd-sum { padding: 0 6px }
.nsd-drawer.sv3-hero.nsd-narrow .nsd-sum .car { display: none }
.nsd-drawer.sv3-hero.nsd-narrow .nsd-sum .nm { letter-spacing: .1em }

/* the opened body: the ONE box the engine grows, and the only one that pages.
   It is a full-width flex item that wraps under the button row, flush to the
   container's padding box (the ±10px margins undo the row's side padding), and
   its border-box height is the engine's `--nsd-body-h`. */
.nsd-drawer.sv3-hero .nsd-secbody {
  order: 1; flex: 0 0 auto; width: calc(100% + 20px); margin: 0 -10px;
  height: var(--nsd-body-h, auto); min-height: 0;
  display: flex; flex-direction: column;
  background: var(--bg-app); border-top: 1px solid var(--line-soft);
  overflow: hidden; animation: nsd-in var(--ms) ease-out;
}
.nsd-drawer.sv3-hero .nsd-secbody[hidden] { display: none }
@keyframes nsd-in { from { opacity: 0 } to { opacity: 1 } }


/* comments: the thread is the list box, the composer is pinned chrome, and the
   pager sits between them so it reads as belonging to the list it pages. */
.nsd-drawer.sv3-hero .nsd-secbody .nsd-comments {
  flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column;
}
.nsd-drawer.sv3-hero .nsd-secbody .nsd-thread {
  flex: 0 0 auto; order: 1; min-height: 0; max-height: none;
  height: var(--nsd-thread-h, auto);
  /* clipped ONLY with .nsd-pager mounted below — see the law at the top */
  overflow: hidden;
}
.nsd-drawer.sv3-hero .nsd-secbody .nsd-thread-head { order: 0; flex: 0 0 auto }
.nsd-drawer.sv3-hero .nsd-secbody .nsd-pager { order: 2 }
.nsd-drawer.sv3-hero .nsd-secbody .nsd-composer { order: 3; flex: 0 0 auto }

/* ══ THE PAGER — the one affordance that makes a clipped box legal ═════════
   Mounted by the fit engine into any region it had to make smaller than its
   content. It states a COUNT, so the founder can see at a glance that there is
   more and exactly how much: "◂ 1–2 of 4 ▸". A region with hidden content and
   no .nsd-pager is a build failure. */
.nsd-drawer.sv3-hero .nsd-pager {
  flex: 0 0 auto; display: flex; align-items: center; gap: 6px;
  padding: 2px 10px 3px; min-height: 19px;
  border-top: 1px solid var(--line-soft);
  background: var(--bg-panel);
  font-family: var(--mono); font-size: 9px; letter-spacing: .12em;
  text-transform: uppercase; color: var(--fg-dim);
}
.nsd-drawer.sv3-hero .nsd-pager-n { flex: 1 1 auto; min-width: 0; white-space: nowrap }
.nsd-drawer.sv3-hero .nsd-pager-b {
  appearance: none; flex: 0 0 auto; height: 15px; min-width: 20px; padding: 0 5px;
  border: 1px solid var(--line); border-radius: var(--r-1, 3px);
  background: transparent; color: var(--fg-mute); font: inherit; cursor: pointer;
  line-height: 13px;
}
.nsd-drawer.sv3-hero .nsd-pager-b:not(:disabled):hover {
  color: var(--lime, #CCDE49); border-color: var(--line-strong, var(--line));
}
.nsd-drawer.sv3-hero .nsd-pager-b:disabled { opacity: .35; cursor: default }
.nsd-drawer.sv3-hero .nsd-pager-b:focus-visible { outline: 2px solid var(--lime, #CCDE49); outline-offset: -2px }

/* suggestions: the tucked chip rack */
.nsd-drawer.sv3-hero .nsd-secbody-sug { padding: 0 }
.nsd-drawer.sv3-hero .nsd-secbody-sug .nsd-word-rail {
  flex: 1 1 auto; min-height: 0; overflow: hidden; margin: 0; padding: 6px 10px;
  display: flex; flex-direction: column; gap: 5px;
}
/* the rail's own head duplicates the SUGGESTIONS summary row (which carries the
   same name AND the count AND #7141's mode whisper), so it is a duplicate, not
   dropped information. The "press 1–9" hint is NOT a duplicate and is restored
   on the rail's own pager row below — losing it when the section opened was
   walk 48's defect 5. */
.nsd-drawer.sv3-hero .nsd-secbody-sug .nsd-word-head { display: none }
.nsd-drawer.sv3-hero .nsd-secbody-sug .nsd-word-grid {
  flex: 0 0 auto; order: 0; min-height: 0; overflow: hidden;
  align-content: flex-start; gap: 5px;
}
.nsd-drawer.sv3-hero .nsd-secbody-sug .nsd-pager { order: 1; border-top: 0; background: transparent; padding-left: 0; padding-right: 0 }
/* a chip is its number and its word; the trailing sense description is what
   gives up room, never the WORD itself (no-truncation defect class). */
.nsd-drawer.sv3-hero .nsd-word-chip {
  min-height: 0; height: auto; min-width: 0; width: auto;
  padding: 2px 8px; align-items: center; gap: 6px;
}
.nsd-drawer.sv3-hero .nsd-word-chip .nsd-word-copy { min-height: 0 }
.nsd-drawer.sv3-hero .nsd-word-chip .nsd-word-num { min-height: 0; height: auto; width: auto; line-height: 1.2 }
.nsd-drawer.sv3-hero.chips-1line .nsd-word-chip SMALL,
.nsd-drawer.sv3-hero.chips-1line .nsd-word-copy SMALL { display: none }

/* ── the DESIGNS section: TELEPORT VERBS ABOVE THE DESIGNS LIST ────────────
   "show designs (and teleport options here)". sv3-notes-drawer-teleport.js
   mounts its whole section (`.sv3-ndt.sv3-ndt-stack`) INTO this body: the
   TELEPORT caption, the Teleport up / Update lays / Teleport down rows, and —
   when the cue has designs — the filter strip, the list and the pull control
   in `.sv3-ndt-designs` under them. One implementation of designs, not two,
   and one home for teleport, not a cell of its own.

   The verbs render in their ONE designed shape at every width: the verb and
   the sentence that says why it is (or is not) enabled, side by side, wrapping
   when the band is narrow. There are no compaction levels and no WHY
   affordance any more — those existed only because the pinned cell competed
   with the thread for height, and a section the founder opened has the body
   to itself. A refused lay keeps its verb, its sentence, its instruction and
   its support code, whole, at every width. */
.nsd-drawer.sv3-hero .nsd-secbody[data-sv3-slot="designs"] { padding: 0 }
.nsd-drawer.sv3-hero .nsd-secbody[data-sv3-slot="designs"] > .sv3-ndt {
  flex: 0 0 auto; min-height: 0; border-top: 0;
  padding: 6px 10px 6px; gap: 5px;
}
.nsd-drawer.sv3-hero .sv3-ndt-stack > .sv3-ndt-head { margin-bottom: 1px }
.nsd-drawer.sv3-hero .sv3-ndt-stack > .sv3-ndt-row {
  flex-direction: row; flex-wrap: wrap; align-items: center; gap: 4px 8px; min-width: 0; min-height: 0;
}
.nsd-drawer.sv3-hero .sv3-ndt-stack .sv3-ndt-btn {
  width: auto; flex: 0 0 auto; padding: 0 9px; white-space: nowrap;
  /* A TELEPORT VERB'S LABEL IS NEVER SLICED: a floor, never a fixed height.
     Measured under the grid at 1280x800 with a refused lay: 20px client
     against 22px of scroll on an INTERACTIVE control. */
  height: auto; min-height: 24px;
}
.nsd-drawer.sv3-hero .sv3-ndt-stack .sv3-ndt-why { flex: 1 1 120px; min-width: 0; font-size: 10.5px; line-height: 1.35 }
/* the UPDATE vs ALT choice and the destructive confirm keep a line of their own */
.nsd-drawer.sv3-hero .sv3-ndt-stack .sv3-ndt-choice { flex: 1 1 100% }
.nsd-drawer.sv3-hero .sv3-ndt-stack > .sv3-ndt-lays-confirm { flex-direction: column; align-items: stretch }
.nsd-drawer.sv3-hero .sv3-ndt-stack .sv3-ndt-quiet { flex: 0 0 auto; white-space: nowrap }
/* the designs list block, when the cue has designs. Its list already ships a
   pager of its own (sv3-ndt-pager) and fitRows() reads the body, so it
   complies as-is. */
.nsd-drawer.sv3-hero .sv3-ndt-stack > .sv3-ndt-designs {
  flex: 0 0 auto; min-height: 0; display: flex; flex-direction: column; gap: 5px;
  margin-top: 3px; padding-top: 5px; border-top: 1px solid var(--line-soft);
  overflow: hidden;
}
.nsd-drawer.sv3-hero .sv3-ndt-list { flex: 0 0 auto; min-height: 0; overflow: hidden }

/* an opened section that is genuinely empty says so rather than showing a void */
.nsd-drawer.sv3-hero .nsd-secbody:empty::after {
  content: 'Nothing here yet.';
  display: block; padding: 8px 10px; font-size: 11px; color: var(--fg-dim);
}

/* the old pinned teleport host. notes-<gen> (write-once) still renders it;
   nothing is painted into it any more, so it takes no pixels. */
.nsd-drawer.sv3-hero .nsd-tp { display: none }

/* ── PRIORITY 4 · the delete row sits above everything fixed, and it is PINNED
   to the bottom of the drawer: the drawer's slack goes above it, never under
   it (a row floating mid-drawer read as unfinished). `.ss-hold-delete::after`
   is a transparent hit-target expander (inset:-7px, no paint); containing it
   at the row keeps the row honest without hiding anything readable — the
   control measures 21px inside a 23px row. */
.nsd-drawer.sv3-hero > .nsd-delete-row { flex: 0 0 auto; margin-top: auto; overflow: hidden; min-width: 0 }
.nsd-drawer.sv3-hero .nsd-delete-quiet { padding: 4px 10px 6px }

/* ══ ONE STACK FOR EVERY FORM FACTOR ═══════════════════════════════════════
   notes-<gen> still stamps `ff-h` (a drawer under 420px tall), `ff-side` (the
   rest) and `tight` (a band under 560px wide). They decide NOTHING here: the
   drawer is a flex column whatever it wears, so a dock that grows past 420px
   when a section opens changes class and changes no pixel. The narrow-column
   rules key on `nsd-narrow` (§ 10 below), which NSD-FIT writes from the box's
   own clientWidth — the axis the decision actually belongs to. */
.nsd-drawer.sv3-hero.nsd-v2 { display: flex; flex-direction: column }
.nsd-drawer.sv3-hero > .nsd-head { flex: 0 0 auto; min-width: 0 }
/* narrow column (<360px) drops, unchanged from #683 */
.nsd-drawer.sv3-hero.narrow .nsd-sum .pv { max-width: 52% }

/* ══ THE TELEPORT VERBS' OWN TEXT ══════════════════════════════════════════
   (The four compaction levels — tp-l0..tp-l3 — and the `Why ›` affordance
   that lived here until #7207 are DELETED with the pinned cell they compacted.
   With the verbs inside the DESIGNS body there is nothing competing with them
   for height, so nothing is ever collapsed and no affordance is needed to
   bring it back.) */
.nsd-drawer.sv3-hero .sv3-ndt-why {
  /* never nowrap, never text-overflow:clip. Walk 48 defect 9 measured
     clientWidth 127 / scrollWidth 284 with white-space:nowrap and
     text-overflow:CLIP — truncated mid-word with no ellipsis and no title. */
  white-space: normal;
  overflow-wrap: anywhere;
  overflow: visible;
  text-overflow: clip;
  min-width: 0;
}
/* a failure keeps its sentence, its instruction and its code, at every width */
.nsd-drawer.sv3-hero .sv3-ndt-why.is-msg { white-space: normal; overflow: visible }
.nsd-drawer.sv3-hero .sv3-ndt-code {
  display: block; margin-top: 2px; font-size: 9px; line-height: 1.3;
  letter-spacing: .02em; font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  color: var(--fg-dim); opacity: .8; word-break: break-all;
}
/* a disabled verb still has to be READABLE. Measured 1.13:1 — rgb(62,60,72) on
   rgb(52,53,60) — which is not a dimmed control, it is an invisible one. */
.nsd-drawer.sv3-hero .sv3-ndt-btn:disabled {
  color: var(--fg-mute); border-color: var(--line); opacity: 1;
}

/* the placeholder assignee is STATIC COPY and must render whole; a real name is
   user data and keeps its ellipsis. */
.nsd-drawer.sv3-hero .nsd-hrow.ssmp-pair .ssmp-nm.none { min-width: max-content }

/* ══ THE LOUD FAILURE ══════════════════════════════════════════════════════
   If the engine could not satisfy the ladder — a viewport genuinely too small
   for three note lines, three summary rows, one item and a compact teleport —
   it stamps `nsd-deficit` and the drawer says so instead of eating the
   difference. Silence is the defect this file exists to prevent. */
/* It rides ON the delete row, which is a FLEX row — so as a pseudo-element it
   became a flex ITEM beside the button and the row stayed one button tall while
   its own warning overflowed it. A clipped warning about clipping would have
   been the fifth instance of this file's defect, committed by the warning. It
   takes a full line of its own, and the row grows by it. */
.nsd-drawer.sv3-hero.nsd-deficit > .nsd-delete-row { flex-wrap: wrap; overflow: hidden }
.nsd-drawer.sv3-hero.nsd-deficit > .nsd-delete-row::before {
  /* ONE line, and short enough to stay one line at a 350px band. The first
     draft wrapped to two and clipped itself — a warning about clipping that
     clipped, which is the joke this whole file is trying not to be. */
  content: 'Window too short — parts of this drawer are paged.';
  flex: 1 0 100%; order: -1;
  display: block; padding: 0; font-size: 9px; line-height: 13px;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  font-family: var(--mono); letter-spacing: .02em; color: var(--st-danger, #B46868);
}

/* ══ `nsd-short` · THE DRAWER'S OWN FURNITURE YIELDS BEFORE THE CUE DOES ═══
   Stamped by the fit engine (sv3-notes-drawer-teleport.js) when the founder's
   ladder cannot be met at the natural chrome. Read the ladder again: it ranks
   NOTE TEXT, the three accordion rows, the open body, the teleport cell. The
   drawer's furniture is not on it — so the furniture is what gives way, and it
   gives way BEFORE any of the four.

   Measured at 1280x800, which is the default MacBook logical size and the
   viewport that failed hardest: .nsd-head 115px and the note block's own
   caption/toggle/status furniture 144px — 259px of a 560px drawer spent before
   one word of the cue. Nothing below is a fact about the cue and nothing below
   is a control: the caption names a field that is unmistakably the note; the
   status line is an empty aria-live region reserving 18px for a message that
   is not there; the identity's four stacked rows carry exactly the same facts
   wrapped into two; the comment composer's three rows carry the same one
   textarea and the same one button. */
.nsd-drawer.sv3-hero.nsd-short .nsd-note-label { display: none }
.nsd-drawer.sv3-hero.nsd-short .nsd-note { padding-top: 4px; padding-bottom: 4px }
.nsd-drawer.sv3-hero.nsd-short .nsd-suggest-control { margin: 2px 0 0 }
.nsd-drawer.sv3-hero.nsd-short .nsd-suggest-toggle { height: 18px; padding: 0 7px; font-size: 10px }
/* the identity: the same rows, wrapped instead of stacked — this is the shape
   the narrow band has shipped since #7113 and it holds down to a 350px band. */
.nsd-drawer.sv3-hero.nsd-short > .nsd-head {
  flex-direction: row; flex-wrap: wrap; align-items: center;
  gap: 2px 8px; padding: 4px 10px 0;
}
.nsd-drawer.sv3-hero.nsd-short > .nsd-head > .nsd-hrow { flex: 0 1 auto; width: auto; min-width: 0; min-height: 0; order: 2 }
.nsd-drawer.sv3-hero.nsd-short > .nsd-head > .nsd-hrow.spread { flex: 1 0 100%; order: 1 }
/* the WHO/BY pair needs a full row of its own so `Unassigned` renders whole, so
   it goes LAST: in DOM order it sits between the status row and the category
   row and forced a line break on both sides, which cost a whole 28px row for
   nothing. Ordered last, the status chips and the category chip share one row
   and the identity is three rows instead of four. */
.nsd-drawer.sv3-hero.nsd-short > .nsd-head > .nsd-hrow.ssmp-pair { flex: 1 0 100%; order: 3 }
.nsd-drawer.sv3-hero.nsd-short .ns-statusrow { flex-wrap: nowrap; gap: 4px }
/* the identity's own rows carry no spare band at the floor. Density, not
   deletion: every fact the head shows before this rule it still shows after —
   the timecode, the status pair, the flag, WHO, BY, the category and the UCS
   chip — in 12px less of leading. Those 12px are the difference between a
   350px-wide window showing its reply field and clipping it. */
.nsd-drawer.sv3-hero.nsd-short > .nsd-head > .nsd-hrow { min-height: 0; line-height: 1.15 }
.nsd-drawer.sv3-hero.nsd-short .ns-seg button,
.nsd-drawer.sv3-hero.nsd-short .ns-flagbtn,
.nsd-drawer.sv3-hero.nsd-short .ssmp-btn,
.nsd-drawer.sv3-hero.nsd-short .nsd-cat > * {
  min-height: 0; height: 20px; padding-top: 0; padding-bottom: 0;
}
.nsd-drawer.sv3-hero.nsd-short .ss-cue-new-note { height: 20px; min-height: 0 }
/* the composer: one row, same textarea, same button, both still full size and
   still hit-testable — the ⌘↵ hint is the only thing that stands down, and the
   shortcut it names still works. */
.nsd-drawer.sv3-hero.nsd-short .nsd-composer { padding: 3px 10px 4px; gap: 7px; align-items: center }
.nsd-drawer.sv3-hero.nsd-short .nsd-secbody-sug .nsd-word-rail { padding: 3px 10px 4px; gap: 3px }
.nsd-drawer.sv3-hero.nsd-short .nsd-composer > div { display: flex; align-items: center; gap: 7px }
.nsd-drawer.sv3-hero.nsd-short .nsd-composer .ns-mention-wrap { flex: 1 1 auto; min-width: 0 }
.nsd-drawer.sv3-hero.nsd-short .nsd-composer .ns-cinput { min-height: 0; height: auto }
.nsd-drawer.sv3-hero.nsd-short .nsd-composer-foot { margin-top: 0; flex: 0 0 auto }
.nsd-drawer.sv3-hero.nsd-short .nsd-composer-foot .nsd-kbd { display: none }
/* the thread's own COMMENTS caption duplicates the accordion row two pixels
   above it, which carries the same word AND the count. A duplicate is what
   yields; the count itself never does. */
.nsd-drawer.sv3-hero.nsd-short .nsd-thread-head { display: none }
/* the navigation rows stay hit-testable at 24px — they are still the tallest
   thing the founder has to hit in this drawer, and 24 is 12 more than the
   hairline they collapsed to before. */
/* the navigation rows stay hit-testable at 22px — still one pixel MORE than
   the value this drawer shipped with, and eleven times the 0-2px hairline the
   walk measured. They never go below this. */
.nsd-drawer.sv3-hero.nsd-short .nsd-sum { --nsd-sum-h: 22px }
/* the note's visual air is FURNITURE, and furniture yields before content. It
   is drawn as border rather than padding (see the note section above), so
   trimming it costs the note nothing but breathing room — and buys 8px, which
   at a 325px dock is the difference between an open section showing its content
   and showing 16px of it. */
.nsd-drawer.sv3-hero.nsd-short { --nsd-air-base: 5px }
.nsd-drawer.sv3-hero.nsd-short .nsd-notepg { padding: 0; font-size: 10px }
/* the pagers stay legible and hit-testable, but they are chrome for the region
   they page, so at the floor they take the smallest box that still reads. */
.nsd-drawer.sv3-hero.nsd-short .nsd-pager { min-height: 16px; padding: 1px 10px 2px; font-size: 8.5px }
.nsd-drawer.sv3-hero.nsd-short .nsd-pager-b { height: 14px; line-height: 12px }
/* the reply field's own two pixels: it was 24 client against 26 of text. */
.nsd-drawer.sv3-hero.nsd-short .nsd-secbody .ns-cinput,
.nsd-drawer.sv3-hero.nsd-short .nsd-secbody textarea.ns-cinput { min-height: 0; height: auto }
.nsd-drawer.sv3-hero.nsd-short .nsd-notepg-b { height: 15px; line-height: 13px }
.nsd-drawer.sv3-hero.nsd-short .nsd-thread { padding-top: 5px; padding-bottom: 3px }

/* an empty aria-live region is 18px of nothing. It keeps its box the moment it
   has something to say, which is the only time the box is information. */
.nsd-drawer.sv3-hero .nsd-word-status:empty { min-height: 0; margin-top: 0 }

/* ══════════════════════════════════════════════════════════════════════════
   WALK 48 · CLOSING .ops/ss-nsd-visible-gate.js
   Every rule below answers a MEASURED failure the gate printed against the
   live build, and every number in these comments is one it printed. Nothing
   here hides anything: each rule either gives a region the pixels its content
   asks for, or stands down a lossy ECHO of content that is whole one row away.
   Baseline before this block: 435 failures, 128 of 130 matrix cells red.
   ══════════════════════════════════════════════════════════════════════════ */

/* 1 · AN INVISIBLE HIT-TARGET EXPANDER MAY NOT CLAIM PIXELS THE ROW HAS NOT GOT.
   `.ss-hold-delete::after { content:''; position:absolute; inset:-7px }`
   (cue-item-<gen>.css, a write-once asset) paints NOTHING — it only widens the
   press target. Being absolutely positioned it still contributes to its
   ancestor's scrollable overflow, so the delete row reported 350x23 client
   against 350x27 scroll at 350x760 and 300x37 against 300x38 at the founder's
   own 780x848: thirty-two cells of the matrix saying "4px of content
   DESTROYED" about a rectangle that has no content and draws nothing.
   Horizontal expansion is free and stays — the row's 9-14px of side padding
   absorbs it (measured: scrollWidth === clientWidth in every cell). Vertical
   is not free, so it is clamped to the row. The button the founder actually
   presses is not touched: it keeps its 30px (20px at the floor). */
.nsd-drawer.sv3-hero .nsd-delete-row .ss-hold-delete::after { top: 0; bottom: 0 }

/* 2 · THE SUGGESTION RACK'S COLUMNS ARE MEASURED, NOT COUNTED.
   notes-<gen> pins the rack to `repeat(3, minmax(0,1fr))`: three columns
   whatever the band is worth, and `minmax(0,…)` is an explicit licence for a
   column narrower than the word inside it. Measured at the founder's 780x848
   with the rack open: `.nsd-word-copy b` — THE WORD — 30px client against 42px
   of scroll (16 cells), and its sense line 30 against 43 (32 cells). The
   chip's own `text-overflow:ellipsis` made the amputation look deliberate.
   NSD-FIT measures the widest chip's natural content and publishes it as
   --nsd-chip-col; the rack then takes as many whole columns as FIT and the
   remainder pages by whole rows through the counted pager it already carries
   ("1–6 of 8 · press 1–9 for any"). Two columns of whole words is more
   information than three columns of stumps, and the 1-9 keys still reach
   every chip on every page because they index the model, not the DOM. */
.nsd-drawer.sv3-hero .nsd-secbody-sug .nsd-word-grid {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, var(--nsd-chip-col, 92px)), 1fr));
}

/* 3 · AN ECHO IS EITHER WHOLE OR IT IS NOT SHOWN.
   Measured at 780x848: `.nsd-sum .pv` 119px client against 177px of scroll —
   the newest comment cut mid-word on the closed COMMENTS row, 12 cells. This
   is the one region in the drawer where "give it a pager" is the wrong answer,
   because the preview is not a fact the drawer holds: it is a SECOND rendering
   of a comment that lives whole in the thread directly below it, behind a row
   that already carries the section's name AND its count. There is nothing to
   page to — the row IS the reach. So when the echo cannot be whole it stands
   down, which is exactly the decision this file already makes at `ff-h tight`
   (`display:none`, in the narrow-column block above) for the same reason at a
   narrower band; all that was wrong was that between "fits" and "tight" there
   was a band where it was cut instead. NSD-FIT measures it per row; this rule
   is what the measurement toggles. (Since #7207 the echo is display:none on
   the little buttons at EVERY width — § the section stack — so this rule is
   inert; it stays because NSD-FIT § fitPreviews still writes the class.) */
.nsd-drawer.sv3-hero .nsd-sum .pv.nsd-pv-cut { display: none }

/* 4 · A TELEPORT VERB'S LABEL IS NEVER SLICED — see § the DESIGNS section
   above: `.sv3-ndt-stack .sv3-ndt-btn { height:auto; min-height:24px }`.
   The compaction levels this rule used to floor are gone with the cell. */

/* 5 · A ROW WITH NOTHING TO SPREAD DOES NOT NEED A ROW.
   `.nsd-hrow.spread` is pinned to `flex: 1 0 100%` in the compaction block
   above so its two ends can sit at the two ends. Measured at 350x760 it holds
   ONE child — the timecode, 108px of natural width — and takes all 330 of the
   band, which pushes the status chips (176px) and the category chip (166px)
   onto separate lines: 350 of content in 330 of room, and a whole 25px line of
   the drawer spent on the 20px that did not fit. At 390 the same head is 84px
   and 3 rows; at 350 it is 109px and 4. Twenty pixels of width cost a line.
   When the row has a single child there is nothing to spread, so it packs with
   the rest and the head is 3 rows at 350 too. Every fact it showed before it
   still shows — this is density, not deletion.
   NSD-FIT (§ fitHead) measures whether the row's one RENDERED child and the row
   after it still fit the head's content width before setting this; a cue with a
   longer timecode, or a spread row whose second control is actually on screen,
   keeps its full row. */
.nsd-drawer.sv3-hero.nsd-short.nsd-head-pack > .nsd-head > .nsd-hrow.spread {
  flex: 0 1 auto;
}

/* 5b · A THREAD SHOWING NO WHOLE COMMENT HAS NO ROWS TO BREATHE AROUND.
   When the box cannot hold even the first comment the engine shows zero of them
   (its own rule: zero whole comments beats one clipped one, and the pager says
   "0 of 4 · too short" out loud). The 8px of list padding then frames nothing,
   in the one state where the drawer is short of exactly that kind of pixel. */
.nsd-drawer.sv3-hero .nsd-thread.nsd-thread-none { padding-top: 0; padding-bottom: 0 }

/* 6 · SEPARATION IS THE GAP'S JOB, AND IT IS ALREADY DOING IT.
   `.nsd-hrow` carries `margin-top:3px` from notes-<gen>, and the compacted head
   above also sets `gap: 2px 8px`. Both apply, so every wrapped line of the head
   pays 5px to be separated by 2. Measured: 3 lines x 3px on a drawer that is
   325px tall and 64px short of the founder's own ladder. The gap is the one
   this file wrote deliberately; the margin is the one that was never re-read
   after the head became a wrapping row. */
.nsd-drawer.sv3-hero.nsd-short > .nsd-head > .nsd-hrow { margin-top: 0 }

/* 7 · (deleted with the compaction levels — a refused lay keeps its verb, its
   sentence, its instruction and its code whole inside the DESIGNS section,
   and is announced on the DESIGNS button while the section is closed.) */

/* ══ 8 · nsd-floor — THE TIER BELOW nsd-short ══════════════════════════════
   `nsd-short` packs the drawer's FURNITURE. This is what happens when that was
   not enough, and NSD-FIT reaches it only after the ladder has been measured
   against a packed drawer and still could not be met — which in the whole
   matrix is one viewport, 350x760, and only with a section open or a refused
   lay. Measured there: a 325px drawer against 244px of ladder (rich) or 265px
   (a refused lay), with the note showing 1 whole line of 10.
   What it spends is the ladder's own order, cheapest first, and every pixel of
   it is furniture or a region that ranks BELOW the one being starved. Nothing
   here removes a fact or a control from the drawer. */

/* the note's visual air is FURNITURE — sv3v2.css says so where the border is
   defined, and nsd-short already took it from 9px to 5px. At the floor it is
   1px and the 1px outline still draws the frame. Buys 8px = 40% of a line. */
.nsd-drawer.sv3-hero.nsd-floor { --nsd-air-base: 1px }

/* the three navigation rows are PRIORITY 2 and the note text is PRIORITY 1, so
   when the drawer is genuinely short they yield BEFORE it does — that is what
   "earlier items keep their pixels first" means read from the bottom up. 18px
   is not the hairline the walk measured (0-2px): it is nine times it, two above
   the gate's own readable/hittable floor of 16, and every row still carries its
   whole label, its count and its caret. Buys 12px. */
.nsd-drawer.sv3-hero.nsd-floor .nsd-sum { --nsd-sum-h: 18px }

/* the last of the padding, on the two rows that are pure chrome. Buys 5px. */
.nsd-drawer.sv3-hero.nsd-floor .nsd-composer { padding-top: 2px; padding-bottom: 2px }
.nsd-drawer.sv3-hero.nsd-floor > .nsd-delete-row button { min-height: 18px }

/* 9 · THE WARNING ABOUT A SHORTFALL MUST NOT BE THE SHORTFALL.
   `nsd-deficit`'s banner takes a line of its own on the delete row, because at
   a wide band a wrapped warning would have clipped itself. At the FLOOR that
   line costs 13px, and 13px is measured to be exactly the difference between
   the founder's note showing 3 whole lines and showing 2: the banner announcing
   that content had to be paged was itself what forced a line of it to be paged.
   The delete row at the floor is one 18px button against 330px of band, so the
   warning rides beside it instead — same row, same words, no second line, and
   still the first thing on the row so it reads before the button. */
.nsd-drawer.sv3-hero.nsd-floor.nsd-deficit > .nsd-delete-row::before {
  content: 'Window too short — parts are paged.';
  flex: 1 1 auto; align-self: center;
}

/* ══════════════════════════════════════════════════════════════════════════
   WALK 48 · ROUND 3 · ORCH'S RULINGS 1, 2 AND 4(b)
   Round 2 failed acceptance a second time, on the same region, with the same
   twelve HIGH findings. ORCH's verdict was that the geometry was UNSATISFIABLE
   and the geometry therefore had to change: "Four comments at ~125px each need
   ~500px. The founder's drawer at his own working config is 407px tall and also
   has to hold the note, three accordion rows, the teleport cell and the delete
   row. No pager, however good, makes that 'visible at a glance'. Round 2 failed
   because it kept trying to win an argument with arithmetic."
   The box now grows (drawer-bottom.css § RULING 1, NSD-FIT § openWant). What is
   below is the other half of that ruling: with a bigger box, every pixel the
   drawer was spending on a SECOND rendering of something it already shows has
   to come back, because the box is still not infinite and a paged comment is
   still worse than a whole one.
   ══════════════════════════════════════════════════════════════════════════ */

/* 10 · A NARROW DRAWER IS NARROW WHATEVER ITS HEIGHT.
   notes-<gen> only spends `tight` on a drawer that is ALSO a band
   (`isBand && w < 560`), because until RULING 1 a narrow drawer was always a
   short one. Opening a section at the founder's own cell now grows a 351px-wide
   drawer past the 420px band threshold, so it correctly stops being `ff-h` —
   and incorrectly stops being `tight` with it, handing back the note caption,
   the suggestions toggle, the empty aria-live status line and the summary rows'
   preview echo at the exact moment the drawer is trying to show four comments
   in a 351px column. Measured, that is 40px of a 351-wide drawer, i.e. two
   whole lines of the founder's note, spent on furniture.
   NSD-FIT writes `nsd-narrow` from `clientWidth < 560` — the same number
   notes-<gen> uses, read on the axis it actually belongs to, and from the box
   rather than from a form factor, so it cannot latch the way defect 8 did. */
.nsd-drawer.sv3-hero.nsd-narrow .nsd-note-label,
.nsd-drawer.sv3-hero.nsd-narrow .nsd-suggest-control,
.nsd-drawer.sv3-hero.nsd-narrow .nsd-word-status { display: none }
/* the closed row's preview echo: a SECOND rendering of a comment that lives
   whole in the thread one click below, behind a row that already carries the
   section's name AND its live count (RULING 4(a)'s condition, met). At 351px it
   is also the echo that never fits — measured 119 client against 177 of scroll.
   `ff-h.tight` already stands it down for exactly this reason; the rule simply
   did not follow the drawer when the drawer stopped being a band. */
.nsd-drawer.sv3-hero.nsd-narrow .nsd-sum .pv { display: none }
.nsd-drawer.sv3-hero.nsd-narrow .ns-statusrow { flex-wrap: nowrap; gap: 3px; font-size: 10px }
.nsd-drawer.sv3-hero.nsd-narrow .ns-statusrow button {
  font-size: 10px; padding-left: 6px; padding-right: 6px; letter-spacing: 0;
}
.nsd-drawer.sv3-hero.nsd-narrow .ssmp-btn.fill { min-width: 0 }
.nsd-drawer.sv3-hero.nsd-narrow .ss-cue-new-note {
  flex: 0 0 auto; font-size: 0; gap: 0; padding: 0 9px; min-width: 0;
}
.nsd-drawer.sv3-hero.nsd-narrow .ss-cue-new-note svg { width: 14px; height: 14px; flex: 0 0 auto }
.nsd-drawer.sv3-hero.nsd-narrow > .nsd-delete-row { padding: 0 10px 2px }
.nsd-drawer.sv3-hero.nsd-narrow > .nsd-delete-row * { min-height: 0 }
.nsd-drawer.sv3-hero.nsd-narrow > .nsd-delete-row button {
  height: auto; min-height: 20px; line-height: 1.1; padding: 2px 8px;
}
.nsd-drawer.sv3-hero.nsd-narrow .nsd-secbody .ns-cinput,
.nsd-drawer.sv3-hero.nsd-narrow .nsd-secbody textarea.ns-cinput {
  min-height: 0; height: auto; padding: 4px 8px;
}
.nsd-drawer.sv3-hero.nsd-narrow .nsd-secbody .nsd-comments { gap: 3px }

/* 11 · AN 86px DASHED BOX REPEATING THE NAME PRINTED 8px TO ITS RIGHT.
   This is the single biggest reclaim in the drawer and it deletes nothing.
   `<Avatar id={c.author}/>` (notes-<gen>, WRITE-ONCE) falls back to
   `NtLabelChip` whenever the author token does not resolve to an account — a
   dashed chip up to 130px wide whose own `title` is "text label — not an
   account" and whose only text is the raw token. The very next element,
   `.ns-comment .meta .who`, renders `NT_USERS[c.author] ? name : c.author`:
   for an unresolved token, THE SAME STRING, 8px to the right, in a larger and
   more legible face.
   Measured at the founder's own 780x848 with the SFX rail open: the chip takes
   86px of a 331px comment, leaving the comment body 227px — so a 137-character
   comment wraps to FOUR lines at 18.75px each. Without it the body is 318px and
   the same comment is three. Across his four comments that is 92/73/73/92 =
   330px of thread becoming roughly 73/55/73/73 = 274px: 56px, most of a whole
   extra comment, bought by not printing one name twice.
   RULING 4(a) is the licence and its condition is met with room to spare: the
   author's name is still on the comment, and so is the timestamp. A RESOLVED
   avatar is NOT a duplicate — it is a face, it is 26px square, and it stays. */
.nsd-drawer.sv3-hero .nsd-thread .ns-comment > .nt-lbl { display: none }

/* 12 · THE GAP BETWEEN COMMENTS IS SEPARATION, NOT A MARGIN OF ERROR.
   13px between comments in a column that is trying to show four of them is 39px
   — two thirds of a comment — spent on air. 8px still separates them clearly
   (the thread is a single-column list of left-aligned blocks, each opening with
   a name in a stronger colour), and only at the tier where the drawer has
   already said it is short. */
.nsd-drawer.sv3-hero.nsd-short .nsd-thread { row-gap: 8px }

/* 13 · THE PAGER HAS NO ZERO STATE ANY MORE, SO NEITHER HAS THIS RULE.
   `nsd-thread-none` styled the thread that showed none of its comments. RULING
   2: "'0 OF 4 · TOO SHORT' is not a pager state, it is a layout failure: if one
   whole item does not fit, the layout is wrong, not the pager." NSD-FIT no
   longer produces that state — the drawer grows instead, and the ladder refuses
   to take the open body below `pinned + one whole item` — so the class is never
   written. The rule stays only so that a thread which somehow reaches that
   state is not ALSO padded; it is dead code that costs nothing and would
   otherwise have to be removed from a file the gate reads. */
