/* THE SHELL BARS -- the top bar, the bottom bar, the instruments and the
 * status readout. Every page of the shop wears these.
 *
 * THE REPO'S FIRST SHARED STYLESHEET, and it exists because the bars were
 * about to be copied. MODEL.html had the only set; PROJECT.html needed the
 * same ones (Movie, 23 Sep: "i need the project area to have the top and
 * bottom bars for sure like these (with the BONE/HOUSE)"), and then so did
 * Construction Layout, SPECS, and REAL ESTATE PLANS and ESTIMATES once they
 * exist. A second copy is how #325 happened and how .card came to mean two
 * different things on PROJECT and SPECS. Movie asked the question that
 * settles it -- "it will guarantee to be same style if i change one all will
 * change right" -- which is true of shared markup ONLY IF THE STYLING MOVES
 * TOO, so it did. This file is that guarantee.
 *
 * THE INSTRUMENTS ARE IN HERE, and that was a correction. They were left
 * behind as MODEL's on the first cut, on the grounds that PROJECT does not
 * draw. Then Movie: "put those top and bottom bars in the Construction
 * layout (with the LENGTH, ANGLE and other instruments ... we may need to
 * draw sometimes". So #strip-center is not one page's -- it is every DRAWING
 * page's. A page that does not draw never mounts the markup, and a rule with
 * nothing to match costs nothing. One file beats two and a rule about which
 * pages link which.
 *
 * WHAT IS NOT HERE: the rails, the drive-thru sign and the build bar. Those
 * are the drawing page's own furniture, and the sign is MODEL's way of
 * CHOOSING a house -- PROJECT chooses from the cards on its own sheet.
 *
 * HOW THIS WAS PROVED SAFE. These rules were SCATTERED through 1,560 lines of
 * MODEL.html's style block, interleaved with the drawing's, and moving a rule
 * moves it in the cascade. That page already has same-specificity collisions
 * that silently kill rules -- the @media (max-width:1500px) block below is
 * two-thirds dead for exactly that reason, which is how I learned not to
 * trust a reading of the source. So the acceptance instrument was the
 * browser's own answer: getComputedStyle over EVERY property of all 1,704
 * elements in these bars, across four skins and three widths, before and
 * after. 765,324 values, zero differences, and the instrument was watched
 * failing -- one pixel off --strip-h moves 5,636 of them.
 *
 * THE TWO-SPACE INDENT IS NOT A MISTAKE. These rules were inside a <style>
 * block and are indented as they were, because the move had to be provable:
 * proto/units-stack-mutants.js anchors on four of them by their exact text,
 * leading spaces included, and a tidy-up would have made the diff a rewrite
 * rather than a move. Reformat the day something else is already changing
 * these lines.
 *
 * THE COLOURS ARE ROLES, for palette.js's reason -- four skins, and a bar
 * that hardcoded its ink would be a white bar on a night page. This file does
 * not define the role table; the pages load palette.js, which is what makes
 * these names mean anything. A PAGE THAT LINKS THIS AND NOT palette.js GETS A
 * BAR WITH NO COLOURS -- the trap waiting for SPECS, SETTINGS and STANDARDS,
 * none of which has been converted.
 *
 * FOUR LITERALS SURVIVE, and they are named here rather than left for someone
 * to find and assume were missed. None of them is a surface the skin owns:
 *   rgba(255,64,51,0.75)  the lit bone's halo -- a LIGHT, not a colour, and
 *                         ROUGH does not use it at all (its ON state is its
 *                         own artwork, see the rule's own note).
 *   #fff + rgba(29,31,32,0.55)   the wallet number and its shadow, printed
 *                         ON the bone artwork. It tracks the art, which is
 *                         the same art on every skin, not the page under it.
 *   rgba(0,0,0,0.35)      the modal scrim. Black at 35% darkens whatever is
 *                         behind it, which is the job on all four skins.
 * If a fifth appears, it is probably a mistake.
 */


  /* THE COUNTERS READ AT THE FOOT OF THE SHEET (Movie, 15 Sep). They were
     moved to the head when the controls were scattered across the sheet and
     the foot belonged to the drive-thru sign; now every control lives in one
     of the two dark bars, so the band the numbers want is the one just above
     the bottom bar -- out of the drawing's centre, and beside nothing that
     grows with a level name. The view counter reads in the same panel: the
     level and the view are counts like the rest, not a separate instrument. */
  /* SHUT BY DEFAULT, BEHIND ITS OWN WORD. Movie: "make it collapsed into only
     TEXT that can be clicked to open this, similar to the DRAG TO PAN text on
     the right side, but put this text on the left side: STATUS READOUT". The
     panel is instrumentation -- twelve counts and six state fields -- and it
     was standing open over the bottom-left of the sheet at all times to say
     so. Collapsed it costs one line of the same quiet uppercase the hint uses
     on the other end of the same edge, so the two ends of the foot read as a
     pair: the hint tells you what the mouse does, the tab offers the numbers.
     THE TEXT IS NEVER REMOVED, only hidden -- updateReadout keeps writing to
     it shut, so the counts are already right the instant it opens, and the
     many specs that read the page's own scale and wall count out of it keep
     working whether the drafter has it open or not. */
  #readout[hidden] { display:none; }
  /* THE ROW CARRIES THE POSITION, not the tab. It held two tenants when that
     was written -- the count stood to the tab's left on the same line -- and
     the count went down a row on 25 Sep; the row keeps the rule because the
     alternative is a fixed inset written on the tab itself, which is where it
     was before and where it should not go back to. */
  #lower-left { position:fixed; left:12px; bottom:var(--readout-bottom);
    z-index:5; display:flex; align-items:baseline; gap:10px; }
  #readout-tab { color: var(--ink-quiet);
    font-family: var(--font-ui); font-size:12px; letter-spacing:0.04em;
    text-transform:uppercase; cursor:pointer;
    border:none; background:none; padding:0; }
  #readout-tab:hover { color: var(--accent); }
  /* OPEN, THE WORD GOES AND AN X TAKES OVER (Movie): the tab and the panel
     are one control, so having both on screen at once said the same thing
     twice. The X sits in the panel's own bottom-right, in the open area
     under the second line rather than on a number. */
  #readout-tab[aria-expanded="true"] { display:none; }
  /* OVER THE ROW, not beside it. The panel opens on the same corner the row
     stands in; one z above means it covers the count instead of sharing a
     line with it, and the tab hides itself as it always did. */
  #readout { display:flex; flex-direction:column; align-items:flex-end;
    position:fixed; left:12px; bottom:var(--readout-bottom); z-index:6;
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none);
    border:1px solid var(--edge-panel); border-radius:6px;
    /* THE PANEL STAYS CLICK-THROUGH and only the X takes the pointer: open,
       it covers a corner of the sheet, and a drafter who draws there should
       reach the drawing, not a wall of numbers. */
    padding:8px 11px; white-space:pre; pointer-events:none;
    /* Instrument text: tabular figures so the counts do not jitter as they
       change, and the mono face so a column of numbers reads as a column. */
    font-family: var(--font-mono); font-size:12px;
    font-variant-numeric:tabular-nums; letter-spacing:0.01em; }
  #readout b { color: var(--accent); font-weight:600; }
  #readout-text { align-self:flex-start; }
  #readout-close { pointer-events:auto; margin-top:2px; padding:0 2px; border:none; background:none;
    cursor:pointer; color: var(--ink-quiet);
    font-family: var(--font-ui); font-size:14px; line-height:1; }
  #readout-close:hover { color: var(--accent); }

  /* THE INSTRUMENT STRIP — one bar across the HEAD of the page, the shape
     MODEL.dc.html:1963 carries: the message at the left and the drafting
     instruments holding the centre. PROJECT went to the page row at the
     lower left and the switches to the mode corner at the upper left, both
     by §7b; what is left here is only what the drafter READS.

     A CHIP HAS THREE STATES AND THEY MEAN DIFFERENT THINGS, which is the
     whole reason the old strip reads as an instrument panel rather than a
     toolbar. `.lit` is engaged. The base state is an instrument that exists
     and is down. `.dormant` is an instrument this page has NOT built — drawn
     at a quarter of the ink, not clickable, and carrying a title that says
     so. Dormant rather than absent because the old strip's spacing IS the
     panel: six instruments flanking the cluster is what makes the ruler and
     the T-square sit dead centre, and a bar that drops them re-centres
     itself every time one is built.

     It is the one place on this page that says what state the board is in,
     so the readout sits below it rather than under it. */
  /* ONE HOME FOR THE STRIP'S HEIGHT. It was 34px here and the hint's 46px
     was 34 + 12 written out by hand, so the bottom band's size lived in two
     literals that had to agree and nothing made them. They did not: the
     sidebars' height was tuned to a hint at bottom:12px, the strip moved it
     to 46, and the pairwise chrome check went red on `right-rail overlaps
     hint` -- its sixth catch, and the second one this file has produced from
     one distance being written down twice. */
  /* THE BAR'S OWN TYPE, and this file has to name it. It reaches for
     var(--font-ui) twelve times and var(--font-mono) five, and defined
     NEITHER -- so the faces came from whichever page the sheet happened to be
     linked into. MODEL declares them; PROJECT and SPECS do not, so all
     seventeen resolved to nothing and the chips inherited the page's body
     font. Same 11px on all three, but Barlow Condensed is narrower than
     Barlow, so the model page's bar read visibly smaller than the other two.
     Movie saw it side by side: "the MODEL one has smaller text it looks like,
     can we make them all match".
  
     IT WAS A KNOWN GAP AND IT WAS LEFT OPEN TOO LONG. The first cut of this
     file kept the move byte-pure so MODEL could be proved unchanged, which
     meant taking no :root declarations that MODEL already had -- and the note
     at the time said to give the fonts a home "when PROJECT adopts". PROJECT
     adopted, then SPECS, and nobody did. A shared stylesheet that depends on
     the page to define its own type is not shared, it is half-shared, which
     is the state that looks fine on the page it came from.
  
     The values are MODEL's, unchanged, so that page renders identically and
     every page linking this sheet now gets the same faces without declaring
     anything. */
  /* AND THE BAR'S OWN BOX MODEL, for the fonts' reason one comment down: a
     shared sheet that leaves this to the page is not shared. MODEL.html has
     no global `* { box-sizing:border-box }` and PROJECT and SPECS do, so the
     same bar measured 41px on one page and 40px on the others -- the 1px top
     border counted inside the height or outside it depending on whose
     stylesheet the sheet happened to be linked into. --house-h says 40, so
     border-box is the intent and content-box was the accident.
  
     SCOPED TO THE SHELL, not declared globally, because a `*` rule from this
     file would reach the whole drawing page and change boxes that have
     nothing to do with the bars. */
  #strip, #strip *, #house-strip, #house-strip *,
  #lower-left, #lower-left *, #readout, #readout *,
  #file-guard, #file-guard *, #save-as, #save-as * { box-sizing: border-box; }

  :root {
    --font-ui:   'Barlow Condensed', system-ui, -apple-system, 'Segoe UI', sans-serif;
    --font-mono: 'DM Mono', ui-monospace, Menlo, Consolas, monospace;
  }
  :root { --strip-h: 44px;
    /* THE HOUSE STRIP, along the foot: BUNGALOW / BILEVEL / DETACHED GARAGE /
       BONE and the one DELETE. Named for the same reason --strip-h is: the
       hint, the page row and both sidebars all stop above it, and that
       distance was written out by hand three times the last time this file
       had two bands. */
    --house-h: 40px;
    /* THE LANE THE BROWSER KEEPS FOR ITSELF. Movie, 24 Sep, with Firefox's
       link preview sitting on top of the PROJECT chip: "see how that 'html'
       address pops up and covers my menu, do you think we could solve this by
       adding extra space at the bottom of the menu so when something pops up
       like that it won't cover our text/links?"

       That strip is the BROWSER'S, drawn over the page whenever a link is
       hovered, and nothing here can hide it, move it or style it. What a page
       can do is stay out of its way, which is what he proposed: the foot of
       the bar is padding rather than content, so the strip lands on the bar's
       own panel colour instead of on a nav chip.

       24px IS THE STRIP'S OWN HEIGHT, measured off his screenshot at default
       zoom -- it runs the bottom 23px of a 768px window. It is not exact
       across browsers or UI font sizes and does not need to be: too small and
       the strip clips a chip's descenders, too large and the bar wears a
       slightly deeper hem, and the cost either way is cosmetic.

       PADDING RATHER THAN A LIFT, which is the difference between his fix and
       the obvious one. Moving the whole bar up with `bottom` leaves the lane
       showing CANVAS, so the strip would sit over the drawing -- quieter than
       a covered chip but still ink under a tooltip. Padding keeps the bar's
       background across the full band. */
    /* AND IT ANSWERS FOR A PHONE'S FURNITURE WITH THE SAME NUMBER.
       env(safe-area-inset-bottom) is the band iOS keeps for the home
       indicator and Safari's own toolbar -- 0 on a desktop, ~34px on a
       recent iPhone -- so taking the greater of the two means one lane
       serves both and neither is special-cased. An iPad in landscape, which
       is what this app is drawn on, reports 0 and gets the 24. */
    --browser-lane: max(24px, env(safe-area-inset-bottom, 0px));
    /* THE BAND THE SIDEBARS MUST STAY OUT OF at the foot: the house strip,
       which now carries the page row inside it, and the counters panel that
       sits just above it. */
    --readout-bottom: calc(var(--house-h) + var(--browser-lane) + 12px);
    /* THE TOP BAND IS ONE BAND NOW. Every control that was loose on the sheet
       -- mode corner, file row, settings -- is a tenant of the strip, so the
       only things still derived from its height are the two file notes and
       the sidebars below them. */
    --note-top: calc(var(--strip-h) + 8px);
    /* HOW WIDE A SIDE RAIL IS -- every one of them, and any added later.
       Movie, 25 Sep, with both open: "make the right side expandable menu
       areas the exact same width as the one on the left (and maintain that
       for others that might be added".

       ONE NUMBER IS THE WHOLE OF "THE SAME", which is why this is a token on
       :root rather than a width written on each rail. Both were
       `position:fixed` with no width -- SHRINK-TO-FIT -- so each measured
       whatever its own widest child happened to want that day: 193px on the
       left for the tool grid, 195 here and 233 with a house loaded on the
       right, and the pair drifting apart again the next time either gained a
       control. A rail added tomorrow inherits this and is the same width
       without anybody measuring anything.

       195px IS THE WIDER OF THE TWO GRIDS, not a taste: the seats in LAYOUT
       PREVIEWS are `repeat(2, 84px)` with a 6px gap = 174, the tool keys are
       `repeat(4, 40px)` with 4px gaps = 172, and 174 + 10px padding either
       side + the 1px edge is 195. Taking the LARGER means nothing inside
       either rail has to yield a pixel -- the seat grid fits exactly, the
       tool grid keeps 2px of slack -- so this is a width change with no
       layout change underneath it.

       AND IT IS A CEILING AS WELL AS A FLOOR, which is what the right rail
       used `max-width:277px` for: past this width a level name ellipsises,
       which is a label the drafter can still read the start of, against a
       panel eating the drawing, which he cannot draw on.

       PLUS THE SCROLLBAR'S OWN LANE (Movie, 14 Oct, circling the slider under
       the seat thumbnails: "can you widen this menu so the RIGHT/LEFT scroll
       won't be needed"). The arithmetic above was right about everything
       except what the VERTICAL scrollbar takes: the rail scrolls, and on a
       desktop its bar eats about 15px off the inside of the box -- so the
       174px seat grid had 159px to stand in and the browser gave it a
       sideways slider to reach the rest. 195 + 15 is 210, and the grid fits
       beside the bar instead of under a second scroller.
       `scrollbar-gutter:stable` below reserves that lane whether the bar is
       showing or not, so a rail that grows past a screenful does not jog its
       contents sideways when the bar appears. */
    --rail-w: 210px; }
  /* AT THE TOP OF THE SHEET NOW, not the foot (§7b). Movie: the drive-thru
     sign rises from the bottom and covers the house row, so nothing the
     drafter reads WHILE DRAWING may live down there. */
  #strip { position:fixed; left:0; right:0; top:0; z-index:6; height:var(--strip-h);
    display:flex; align-items:center; gap:8px; padding:0 12px;
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none);
    border-bottom:1px solid var(--edge-panel);
    font-family: var(--font-ui); font-size:12px; font-weight:600;
    letter-spacing:0.04em; color: var(--ink-secondary);
    user-select:none; }
  #strip a, #strip button { font:inherit; letter-spacing:inherit; }
  #strip .grow { flex:1; }
  /* THE MESSAGE CAME OFF THE BAR (Movie, 18 Sep: "what is this text up in
     here?" -- "if its a warning of som sort we should move it down just into
     the model area below the top bar area").

     IT WAS ALWAYS GOING TO END UP GARBLED THERE, and the rule that replaced
     this one said so in as many words: "THE MESSAGE YIELDS. It shares the
     left end with the settings stack and the mode corner now, and a message
     long enough to push either of them off the bar would cost a control to
     report a sentence." So it was given 16vw and an ellipsis -- and 16vw is
     218px on a 1366 sheet, which cuts "Detached garages are not on this page
     yet -- the house outline is." off at about a third. Yielding was the
     right call for a control that had to be on that bar. Taking it off the
     bar is the better one: nothing yields, and the sentence is read whole.

     LINED UP WITH STATUS READOUT, in its type and at its inset (Movie: "move
     it to the left make it look like lined up and same text and size and the
     STATUS READOUT down below", then "STATUS READOUT same location leftwise
     but at top of model area"). Same left:12px, same 12px UI face, same quiet
     ink -- so the two ends of the sheet's left edge read as one voice, the
     page telling you something at the top and offering you the numbers at
     the bottom. --note-top is where this page already puts a line that sits
     just under the bar; #elsewhere uses it on the right.

     CLICK-THROUGH, for #readout's reason one line up the file: it lies over
     the sheet, and a drafter drawing under it should reach the drawing. The
     nowrap and the ellipsis stay as a backstop for a sentence longer than
     any this page has, not as the working constraint they used to be. */
  #strip-message { position:fixed; left:12px; top:var(--note-top); z-index:5;
    font-family: var(--font-ui); font-size:12px; letter-spacing:0.04em;
    text-transform:uppercase; color: var(--ink-quiet); pointer-events:none;
    white-space:nowrap; overflow:hidden; text-overflow:ellipsis;
    max-width:calc(100vw - 24px); }

  /* THE SETTINGS STACK, first thing on the bar (Movie, 15 Sep): SETTINGS and
     STANDARDS over each other and the unit toggle beside them -- MODEL.dc.html's
     own corner (:430-443), including its ruling that units are ONE button
     naming the unit in force, not two that fight for the same thumb. */
  #settings-corner a#home-logo { min-width:0; padding:0; border:0; background:none; }
  #home-logo { display:flex; align-items:center; flex:0 0 auto; border-radius:4px; }
  #home-logo img { display:block; width:26px; height:26px; }
  #home-logo:hover, #home-logo:focus-visible { outline:1px solid var(--accent); outline-offset:1px; }
  #settings-corner { display:flex; align-items:center; gap:6px; flex:0 0 auto; }
  #settings-stack { display:flex; flex-direction:column; gap:1px; }
  #settings-corner a, #settings-corner button {
    font-family: var(--font-ui); font-size:9px; font-weight:600;
    letter-spacing:0.05em; text-transform:uppercase; text-decoration:none;
    display:inline-flex; align-items:center; justify-content:center;
    min-width:56px; padding:2px 6px; cursor:pointer;
    border:1px solid var(--edge-panel); border-radius:3px;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    color: var(--ink-primary); }
  #settings-corner a:hover, #settings-corner button:hover {
    border-color: var(--accent); color: var(--accent); }
  /* THE UNIT STACK borrows the settings stack's rows exactly -- same font,
     same minimum, same 1px gap -- because the DC corner's fault was two 44px
     targets on top of each other, and the cure is the row height that
     already works two inches to the left, not a new shape.

     THE MINIMUM IS 56px AND IT WAS 64px. Two more stacked pairs came up to
     this bar on 17 Sep, and at 64 the bar overflowed 1280 by 10px --
     PRINTSCREEN off the sheet at 1213..1290, caught by model-html-shell's
     own guard, which is the second time that check has earned its keep.

     MEASURED RATHER THAN NUDGED. The widest label on any of these rows is
     DRAFTING at 35px of ink; with the 6px padding each side and the 1px
     border that is 49px, so 56 clears it by 7px and 64 was carrying 15px of
     slack that nothing asked for. Four columns at 8px each gives the bar 32px
     back, which is 1280 with 22px to spare. Still well over the 44px touch
     target the DC corner failed on.

     ONE NUMBER FOR THE WHOLE FAMILY, so a fifth pair cannot arrive built to a
     fifth width. Settings is unchanged by it: STANDARDS is wider than either
     minimum, so that stack is sized by its own word. */
  #units-corner { display:flex; align-items:center; flex:0 0 auto; }
  #units-corner .stack { display:flex; flex-direction:column; gap:1px; }
  #units-corner button {
    font-family: var(--font-ui); font-size:9px; font-weight:600;
    letter-spacing:0.05em; text-transform:uppercase;
    display:inline-flex; align-items:center; justify-content:center;
    min-width:56px; padding:2px 6px; cursor:pointer;
    border:1px solid var(--edge-panel); border-radius:3px;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    color: var(--ink-quiet); }
  #units-corner button:hover { border-color: var(--accent); color: var(--accent); }
  /* SHADED MEANS IN FORCE (Movie, 15 Sep). The same accent fill the mode
     corner uses, so a drafter reads "this one is on" once and it is true
     everywhere on the page. */
  #units-corner button[aria-pressed="true"] { color: var(--accent-ink);
    background-color: var(--accent); border-color: var(--accent); }

  /* THE INSTRUMENTS SIT IN THE BAR, not on top of it. They were centred by
     absolute position, which takes no room in the flow -- so the two grow
     spacers either side of them shared the whole bar between the corners and
     the instruments floated over whatever ended up in the middle. With
     SETTINGS, STANDARDS and UNITS added to the left end that turned out to be
     the mode corner: the TRIANGLE chip landed on DAY and ate the tap.
     A flex child between the same two spacers is centred by the same
     arithmetic and cannot overlap anything. */
  #strip-center { flex:0 0 auto; height:var(--strip-h);
    display:flex; align-items:center; gap:10px; padding:0 8px; }
  /* TWO HALVES AND A LINE BETWEEN THEM (Movie, 16 Sep): the bar reads as
     LENGTH on one side and ANGLE on the other, so the rule sits between the
     two boxes and names the split. It is CENTRED ON THE SHEET rather than on
     the cluster: the two halves are equal grid columns, so the middle column
     lands on the cluster's centre line, and the cluster's centre line is the
     window's -- which puts the rule on the same axis as the bone below. Flex
     would have centred the CONTENT and the line would drift with whichever
     side happens to be wider. */
  .strip-half { display:flex; align-items:center; gap:10px; }
  .strip-half-left { justify-content:flex-end; }
  .strip-half-right { justify-content:flex-start; }
  #strip-divide { width:1px; height:24px; flex:0 0 1px;
    background: var(--edge-panel); }
  /* CENTRED ON THE SHEET, not on what is left over. Two flex spacers centre
     the cluster only when the two corners weigh the same, and they never do
     -- the settings/units/mode stack is wide, the file row hides itself at
     narrow widths -- so the kit sat right of middle. Movie: "put all the
     instrument lights and textboxes centered".
     FROM 1440 UP, and the number is a measurement, not a taste: at 1280 the
     centred cluster's right edge already reaches NEW on an empty page, and a
     drawing with a length in the box carries it over the whole file row --
     absolute centring can slide a chip over a corner control, which is the
     bug the note above records. 1440 is the narrowest sheet where the
     cluster and both corners fit side by side. Below it the cluster goes
     back to being a flex child between spacers, where it cannot overlap
     anything -- the corners weigh nearly the same, so it sits within a
     chip's width of centre rather than exactly on it. */
  /* THE OVERLAY MUST NOT EAT CLICKS. An absolute cluster sits OVER the bar,
     and its box is wider than its ink -- the 1fr tracks are empty space, and
     a long live length widens the whole box symmetrically. That empty box
     reaching NEW was seven specs' 180-second timeout: "#strip-center
     intercepts pointer events". The box goes deaf; the tenants stay live. */
  @media (min-width: 1440px) {
    #strip-center { position:absolute; left:50%; transform:translateX(-50%);
      display:grid; grid-template-columns:1fr auto 1fr; pointer-events:none; }
    /* The halves' boxes equalise -- 1fr and 1fr -- so the quiet half is
       wider than its chips too. Deaf boxes all the way down to the ink. */
    #strip-center .strip-half { pointer-events:none; }
    #strip-center .strip-half > *, #strip-divide { pointer-events:auto; }
  }
  /* WHEN THE BAR RUNS OUT OF SHEET, the things with nothing behind them go
     first. At 1280 the tenants want 1422px, so the file row -- NEW, OPEN,
     SAVE, SAVE AS -- was pushed off the right edge and could not be clicked
     at all. A control that does nothing yet must never cost one that saves
     the drawing, so the three not-built-yet chips and the LENGTH caption are
     dropped on a narrow sheet and the instruments close up.

     THE THRESHOLD CAME DOWN when RUFF/ROUGH and NIGHT/DAY went to the bottom
     bar: that is ~150px the left corner no longer spends, and 1500 was still
     charging for it -- so a 1366 laptop, which now has room to spare, lost
     the brush and the rest of the not-built chips for nothing. Movie, 15
     Sep: "the drafting brush and a bunch of other unused instrument lights
     vanished can we put them back". */
  @media (max-width: 1180px) {
    #strip-center .chip.dormant { display:none; }
  }
  /* THE LABEL OUTLASTS THE WIDTH IT COSTS. Dropping the word LENGTH saved
     ~48px and spent the thing the box was for: an unlabelled field next to
     an unlabelled field is two boxes a drafter has to try. Movie, 15 Sep:
     "there is a big blank spot where it should say LENGTH". The box gives up
     the width instead -- 72px still holds 12'-11 1/2". */
  @media (max-width: 1500px) {
    #strip-center, .strip-half { gap:6px; }
    #frozen-length { width:72px; }
    #strip-len:not(:empty) { min-width:66px; }
  }
  /* AND THEY SIT AGAINST THE WORKING ONES. Movie: "snug them to the sides of
     the working ones". A dormant chip spaced like an instrument reads as one
     of the instruments; pulled tight to the live cluster it reads as what it
     is -- the rest of the kit, not yet in hand. */
  #strip-center .chip.dormant { margin-inline:-3px; padding:2px 2px; }
  .chip { display:inline-flex; align-items:center; gap:3px; padding:2px 4px;
    border:1px solid transparent; border-radius:4px; background:none;
    color: var(--ink-secondary); cursor:pointer; }
  .chip:hover { border-color: var(--edge-panel); }
  .chip.lit { color: var(--accent); border-color: var(--accent); }
  /* ARMED IS NOT LOADED, and the brush is the one instrument where the two
     come apart: up and empty it takes every press and changes nothing, up and
     loaded it repaints what it touches. One outline for "this is taking your
     presses", the accent for "and here is what it will do with them". */
  .chip.armed:not(.lit) { border-color: var(--ink-secondary); }
  .chip.dormant { color: var(--ink-quiet); opacity:0.35; cursor:default; }
  .chip.dormant:hover { border-color:transparent; }
  #strip .num { font-family: var(--font-mono); font-size:12px;
    font-variant-numeric:tabular-nums; color: var(--ink-primary); }
  /* THE READ-OUTS RESERVE THEIR WIDTH ONLY WHEN THEY ARE READING. The
     min-width is there so a number growing from 4' to 12'-11 1/2" does not
     shove the instruments sideways mid-gesture -- but with nothing in hand
     it was 118px of held-open nothing between the ruler and LENGTH, which is
     what Movie saw: "why big gap?". Empty, they take no room; the moment
     they have a number they take the same room as before, so the jitter the
     min-width was written for still cannot happen. */
  #strip-len:not(:empty) { min-width:74px; }
  #strip-len { text-align:right; }
  #strip-ang:not(:empty) { min-width:44px; }
  #strip-ang { color: var(--ink-quiet); }
  #strip-length-box { display:flex; align-items:center; gap:5px;
    font-size:11px; color: var(--ink-quiet); }
  #frozen-length { width:96px; text-align:right; padding:3px 6px;
    font-family: var(--font-mono); font-size:12px;
    background-color: var(--surface-chip); color: var(--ink-primary);
    border:1px solid var(--edge-panel); border-radius:4px; outline:none; }
  #frozen-length:disabled { color: var(--ink-quiet); opacity:0.5; }
  #frozen-length:focus { border-color: var(--accent); }
  /* LIVE: a line in hand (Movie, 12 Oct). An orange rim and glow round the
     outside, the inside left the dark chip so the white number reads. The
     page that lights it names the colour (MODEL: the tracking rays'). */
  #frozen-length.live, #frozen-length.live:disabled { opacity:1; color: var(--ink-primary);
    border-color: var(--length-live, var(--accent));
    box-shadow: 0 0 0 1px var(--length-live, var(--accent)), 0 0 9px 1px var(--length-live-glow, transparent); }
  /* THE WORD SITS AFTER ITS BOX, between the box and the protractor, where
     Movie put it: the instrument and its number read as one thing with the
     name in the middle naming both. It stays at every width -- the angle box
     is narrow enough to be taken for a second length box, and the label is
     what tells them apart. */
  #strip-angle-box { display:flex; align-items:center; gap:5px;
    font-size:11px; color: var(--ink-quiet); }
  #frozen-angle { width:62px; text-align:right; padding:3px 6px;
    font-family: var(--font-mono); font-size:12px;
    background-color: var(--surface-chip); color: var(--ink-primary);
    border:1px solid var(--edge-panel); border-radius:4px; outline:none; }
  #frozen-angle:disabled { color: var(--ink-quiet); opacity:0.5; }
  #frozen-angle:focus { border-color: var(--accent); }

  /* THE MODE CORNER, upper-left (§7b): what the drawing IS -- board, finish,
     day/night. It sat at the right-hand end of the foot strip; Movie moved it
     to the corner the old LEVEL / VIEW / DRAW WALL / SAVE bar vacated. The
     buttons and what they do are untouched: this is a position, not a
     re-scope. */
  #mode-corner { display:flex; align-items:center; gap:5px; flex:0 0 auto;
    font-family: var(--font-ui); font-size:12px; font-weight:600;
    letter-spacing:0.04em; }
  /* `#house-strip .set` came off these three rules on 17 Sep: both switches
     went back up to the mode corner and the bottom bar now carries no set at
     all. A selector kept "in case" is a selector nobody can reason about. */
  #mode-corner .set { display:flex; align-items:center;
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none);
    border:1px solid var(--edge-panel); border-radius:4px; overflow:hidden; }
  /* STACKED, and the stack is why the bar got NARROWER rather than wider
     when the units gained a second button: TOY over DRAFTING is the width of
     DRAFTING alone, where side by side it was both plus a divider. The bar
     overflowed 1280 by 142px once already (PRINTSCREEN, 15 Sep); a
     rearrangement that spent width would have walked back into it. */
  #mode-corner .set.stack { flex-direction:column; align-items:stretch; }
  #mode-corner button { font:inherit; letter-spacing:inherit;
    padding:4px 7px; font-size:11px;
    text-transform:uppercase; cursor:pointer; border:none; background:none;
    color: var(--ink-quiet); }
  #mode-corner .set.stack button { padding:2px 7px; font-size:9px; }
  /* EVERY STACKED PAIR IS THE UNIT STACK'S TWIN. Movie, first for the board
     switch -- "make the TOY / DRAFTING buttons same size as IMPERIAL / METRIC
     ... and same shading" -- and on 17 Sep for the two that came back up:
     "make them the same style as up top style". Stacked pairs standing side
     by side on one bar, built to different shapes, read as different KINDS of
     control -- so they borrow the unit rows outright: the 64px minimum, the
     9px row, the 1px gap, the chip fill and the accent for the one in force.
     The set's own frame goes with it, since the frame is what made a pair one
     welded block rather than two buttons.

     KEYED ON THE SHAPE, NOT ON WHICH SWITCH IT IS. This named
     [data-board-switch] while the board switch was the only stack up here,
     and the two arriving would each have had to be added to the selector by
     hand -- a rule that has to be edited every time it should already apply
     is the kind that goes stale silently. */
  #mode-corner .set.stack { border:none; background:none;
    gap:1px; overflow:visible; }
  #mode-corner .set.stack button {
    font-family: var(--font-ui); font-size:9px; font-weight:600;
    letter-spacing:0.05em;
    display:inline-flex; align-items:center; justify-content:center;
    min-width:56px; padding:2px 6px;
    border:1px solid var(--edge-panel); border-radius:3px;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    color: var(--ink-quiet); }
  #mode-corner .set.stack button:hover {
    border-color: var(--accent); color: var(--accent); }
  #mode-corner .set.stack button[aria-pressed="true"] {
    color: var(--accent-ink); background-color: var(--accent);
    border-color: var(--accent); }
  #mode-corner button[aria-pressed="true"] { color: var(--accent-ink);
    background-color: var(--accent); }

  /* THE BOARD LAMP (Movie, 15 Oct: "it ill be basically a LIGHT -- not a
     button"). It borrows the stacked pair's chip outright, for the reason the
     pairs borrow the unit rows: a control built to a different shape reads as
     a different KIND of thing, and this one belongs to the same family even
     though it is the only one that cannot be pressed.

     NO HOVER AND NO POINTER. The hover rule above is what tells a drafter a
     chip can be pressed, so the lamp must not have it -- and `cursor:default`
     says the same thing to the hand. */
  /* HIDDEN MEANS GONE. The lamp stands down on a page that does not set it
     (shell-bars' `board` verb), and `display:flex` on the stack would beat
     the UA's [hidden] -- the same bug the UNGROUP button had. */
  #mode-corner .set.stack.lamp[hidden] { display:none; }
  #mode-corner .set.stack.lamp > span {
    font-family: var(--font-ui); font-size:9px; font-weight:600;
    letter-spacing:0.05em;
    display:inline-flex; align-items:center; justify-content:center;
    min-width:56px; padding:2px 6px;
    border:1px solid var(--edge-panel); border-radius:3px;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    color: var(--ink-quiet); cursor:default; user-select:none; }
  /* LIT ON TOY, QUIET ON DRAFTING, and that is the whole of what a light is
     for: TOY is the state with a rule in it, so it is the state worth
     announcing. On DRAFTING the lamp still says which board the drawing is
     on -- the fact does not go away when the shading does. */
  #mode-corner .set.stack.lamp[data-lit] > [data-board-lamp] {
    color: var(--accent-ink); background-color: var(--accent);
    border-color: var(--accent); }
  #mode-corner .set.stack.lamp > [data-board-lamp-note] {
    font-size:8px; letter-spacing:0.08em; }

  /* AND WHAT A STACK LOOKS LIKE WHEN THE PAGE CANNOT WORK IT.
     shell-bars.js greys every bar verb a page does not wire, and these two
     pairs were the ones where greying did not SHOW: their resting colour is
     already --ink-quiet, so a disabled METRIC was pixel-for-pixel a live one
     and the only thing the drafter lost was the hover he had no reason to
     try. The page row's own dead chip is the bar's existing word for this --
     `opacity:0.35; cursor:not-allowed` a hundred lines down -- so it is that
     word, not a new one.
     THE ONE IN FORCE KEEPS ITS FILL. IMPERIAL stays shaded on a page that
     cannot switch units, because shaded means "this is what you are reading"
     and that is still true -- it is the CHOICE that is gone, not the fact.
     Fading it to 0.35 with the rest would have greyed out the answer along
     with the question. It loses the hover and the pointer, which is the part
     that was lying. */
  #units-corner button:disabled[aria-pressed="false"],
  #units-corner button:disabled[aria-pressed="false"]:hover,
  #mode-corner .set.stack button:disabled[aria-pressed="false"],
  #mode-corner .set.stack button:disabled[aria-pressed="false"]:hover {
    color: var(--ink-quiet); opacity:0.35; cursor:not-allowed;
    border-color: var(--edge-panel); }
  #units-corner button:disabled[aria-pressed="true"],
  #mode-corner .set.stack button:disabled[aria-pressed="true"] {
    cursor:not-allowed; opacity:0.72; }

  /* THE FILE ROW, upper-right (§1): what the FILE is -- NEW, OPEN, SAVE with
     its three words, SAVE AS, and the extension the generated name takes.
     The row from MODEL.dc.html:573-590 without its PROJECT button: Movie has
     another place for that and it is the page row at the lower left. */
  /* THE ROW IS ALWAYS THERE (Movie): it came up hidden until a drawing
     loaded, so an origin with nothing stored showed a bar with no way to
     start one -- NEW and OPEN, the two that need no drawing, were the ones
     hidden hardest. The row stands from the first paint and the two WRITE
     buttons are dead until there is something to write, which is the rule
     the lease already uses below: a missing button reads as a broken page,
     a dead one says the drafter is in the right place. */
  #file-row { flex:0 0 auto; display:flex; align-items:center; gap:6px; }
  #file-row[hidden] { display:none; }
  #file-row button, #file-row select {
    font-family: var(--font-ui); font-size:11px; font-weight:600;
    letter-spacing:0.06em; text-transform:uppercase;
    color: var(--ink-primary); cursor:pointer;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    border:1px solid var(--edge-panel); border-radius:5px; padding:5px 9px; }
  #file-row button:hover, #file-row select:hover { border-color: var(--accent); }
  #file-row select { padding:5px 6px; text-transform:none; }
  #file-row button:disabled, #file-row button:disabled:hover {
    color: var(--ink-quiet); border-color: var(--edge-panel); cursor:default; }
  /* SAVE IS ALSO THE STATUS, and that is a decision rather than a shortcut.
     §1 draws NEW · OPEN · SAVE · status · SAVE AS, and the .dc page has two
     elements there because its SAVE is a download and its status describes a
     different write. Here they are one write, so a separate word beside the
     button would be a second reading of one fact -- the drift this page has
     paid for twice -- and the three words SAVE / UNSAVED / SAVED are already
     load-bearing in the specs. `data-save-status` is on the button that
     carries them. */
  #save:disabled { color: var(--ink-quiet); cursor:default; }
  /* Unsaved edits. The accent is the page's one attention colour, so the
     button stops being furniture the moment there is something to lose. */
  #save.dirty { color: var(--accent); border-color: var(--accent); }

  /* THE PAGE ROW, lower-left (§7b): where the drafter GOES. PROJECT stayed
     where it was and gained five neighbours.

     A BUTTON THAT GOES NOWHERE LOOKS LIKE IT GOES NOWHERE -- the dormant
     chip's own treatment, quarter ink and no pointer, because a control that
     lights and does nothing is a worse lie than one that is plainly down. */
  #page-row, #sheet-row { flex:0 0 auto; display:flex; align-items:center; gap:4px;
    font-family: var(--font-ui); font-size:11px; font-weight:600;
    letter-spacing:0.06em; }
  /* THE SWITCH SPANS ARE NOT PAGES. `#page-row span` is the chip treatment
     for MODEL's you-are-here, and RUFF/ROUGH sitting in the same row would
     have taken it -- a switch wearing a page's border, inside the row that
     means "places you can go". */
  /* AND THE SHEET ROW'S YOU-ARE-HERE TOO, which it went without until SPECS
     took the bars. Both of the rules here named only #page-row spans, because
     when they were written only MODEL and PROJECT could be the current page
     and both of those live in the LEFT row. The first page to be current in
     the RIGHT row got no box and no accent -- it was simply unstyled text
     sitting between two chips. Movie saw it in a screenshot of the three bars
     stacked: "looks like the box is missing around the last SPECIFICATIONS".

     The asymmetry was invisible for as long as the sheet row held only links.
     It is the shape of bug a shared row grows the day a new page joins it. */
  #page-row a, #page-row button, #page-row > span:not(.set),
  #sheet-row a, #sheet-row button, #sheet-row > span:not(.set) { font:inherit;
    letter-spacing:inherit; display:inline-flex; align-items:center;
    height:24px; padding:0 8px; text-transform:uppercase; text-decoration:none;
    border-radius:4px; border:1px solid var(--edge-panel);
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none);
    color: var(--ink-primary); cursor:pointer; }
  #page-row a:hover, #page-row button:hover,
  #sheet-row a:hover, #sheet-row button:hover { border-color: var(--accent);
    color: var(--accent); }
  /* HERE, not a link to here. A button that reloads the page you are on
     loses an unsaved corner to a stray thumb. */
  /* AND IT HAS TO OUT-SPECIFY THE CHIP RULE, which it did not. The chip
     selector above is `#page-row > span:not(.set)` -- and :not() contributes
     its argument's weight, so that scores (1,1,1) where a bare
     `#page-row [aria-current]` scores (1,1,0). The chip rule won EVERY
     property: the current page was drawn in ordinary ink with an ordinary
     border and a POINTER cursor, on a chip that does nothing when pressed.
  
     So the whole rule below has been dead since the :not(.set) guard was
     added, reading correctly and doing nothing -- the same shape as the
     @media (max-width:1500px) block still sitting dead in MODEL.html. Found
     while giving the sheet row its box; measured rather than reasoned about,
     because this file has now taught that lesson twice.
  
     The `> span` matches the chip rule's shape and takes it past (1,1,1). */
  #page-row > span[aria-current="page"]:not(.set),
  #sheet-row > span[aria-current="page"]:not(.set),
  #page-row [aria-current="page"],
  #sheet-row [aria-current="page"] { color: var(--accent);
    border-color: var(--accent); cursor:default; }
  #page-row button:disabled, #page-row button:disabled:hover,
  #sheet-row button:disabled, #sheet-row button:disabled:hover {
    color: var(--ink-quiet); opacity:0.35; cursor:not-allowed;
    border-color: var(--edge-panel); }
  /* THE PAGE'S OWN BUTTONS at the head of the right-hand row: NORTH, and
     HOUSE ROTATE at half again a chip's size (Movie, 1 Oct: "a slightly
     larger 150% sized PAGE ROTATE button"). Icons, so square-ish. */
  #sheet-row .bar-tool { padding:0 6px; justify-content:center; min-width:28px; }
  #sheet-row .bar-tool-big { height:36px; min-width:42px; padding:0 8px; }
  /* THE CHANGE NOTE USED TO STEP DOWN WHEN THE BANNER WAS UP -- 34px for the
     banner's line, 68px to clear it -- and the column is where that goes: a
     hidden child is `display:none`, which leaves the stack, so the two are
     never in the same place and nobody has to measure the one to place the
     other. */

  /* THE HOUSE STRIP, along the foot (§7b): what the drafter PICKS. This is
     the region the drive-thru sign rises into and covers, which is why
     nothing read while drawing lives here -- and why DELETE, which does live
     here, is unavailable while the sign is up.

     THREE GROUPS ACROSS IT (Movie, 15 Sep): the two live places on the left,
     the bone in the middle, the sheets that come off this model on the far
     right. The middle is what the sign covers, and the bone is the only
     press there for exactly that reason -- a control the sign hides is a
     control the drafter cannot reach while ordering. */
  #house-strip { position:fixed; left:0; right:0; bottom:0; z-index:6;
    --foot-press-h:34px;
    /* The hem is the browser's lane; --house-h still names what the bar is,
       so nothing that measures the bar has to know about the lane. */
    min-height:calc(var(--house-h) + var(--browser-lane));
    display:flex; align-items:center; gap:8px;
    padding:0 12px var(--browser-lane);
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none);
    border-top:1px solid var(--edge-panel); }
  #house-strip .grow { flex:1; }
  /* THE LOWEST ROW, standing in the hem (Movie, 25 Sep). shell-bars.js's
     FOOTLANE comment has the request and why the lane is the row he meant;
     this is only where it stands.

     `bottom:0` REACHES THE HEM BECAUSE THE HEM IS PADDING. An absolutely
     positioned child resolves its offsets against the PADDING box, so this
     lands ON the lane while every flex child of the same bar clears it --
     the fact #dt-bar's comment below records from the other side.

     `margin-left:auto` ON THE NOTE, NOT `justify-content:space-between`. The
     count's slot is `display:none` while the count has not arrived, and a
     lane laid out by space-between with one child left would have swung the
     clock over to the left edge every time the counter host was slow, blocked
     or offline -- which is most of the time, by design.

     AND NO HEIGHT OF ITS OWN BEYOND THE LANE'S: `top` is left alone so a
     reading that grows a pixel taller than 24 leans up into the bar rather
     than down under the sheet. */
  #foot-lane { position:absolute; left:12px; right:12px; bottom:0;
    height:var(--browser-lane); display:flex; align-items:center; }
  #foot-lane > [data-foot-note] { margin-left:auto; }
  /* AN EMPTY SLOT TAKES NO ROOM -- the rule #lower-left kept while the count
     lived there, and for the same reason: a slot the count never arrives in
     must not be a gap holding the lane open. */
  #foot-lane > :empty { display:none; }

  /* THE CLOCK'S TYPE, AND IT BELONGS HERE. Movie, 29 Sep, with the six pages
     side by side: *"see over in bottom right corner the TIME - text is
     different in most of them its bigger, can you make them all look the same
     as the MODEL.html"*.

     THE SOCKET-WITHOUT-THE-LAMP FAILURE ONE LAYER UP. shell-bars.js mounts
     the clock into [data-foot-note] on every page carrying this bar -- its
     own comment says why: *"the clock is the same on every page carrying this
     bar"* -- but the rule that makes it a clock and not a paragraph stayed in
     MODEL.html's stylesheet, where it was written the day MODEL was the only
     page with a corner for it. So five pages mounted a bare <div> and got the
     page's body type: 16px, mixed case, proportional figures, three times the
     size of the visit count it shares the lane with.

     THE SAME DECLARATIONS MODEL ALREADY HAD, and the reasoning is MODEL's, in
     its own stylesheet beside the rule: the counter's type so the lane's two
     ambient readings are one voice, --ink-quiet because a literal that is ink
     for a white page is invisible on the night skin, and tabular figures so a
     clock does not twitch sideways when the minute turns. Both --font-ui
     (:root, above) and --ink-quiet (palette.js, which every one of these
     pages loads) resolve here.

     MODEL KEEPS ITS COPY. The declarations are identical, so the cascade
     lands on the same paint either way, and this thread was asked not to
     touch that page. */
  #clock { font-family: var(--font-ui); font-size:10px; font-weight:600;
    letter-spacing:0.06em; text-transform:uppercase; color: var(--ink-quiet);
    font-variant-numeric:tabular-nums; white-space:nowrap; }
  /* AN EMPTY SLOT TAKES NO ROOM -- the visit counter's slot beside it keeps
     the same rule for the same reason. */
  #clock:empty { display:none; }
  /* THE ONE DELETE (§7a). Not per type, and not only for walls: it acts on
     the selection, whatever is in it. It is on screen exactly while there is
     something to delete -- and the iPad has no Delete key, so this button is
     the only way to delete anything at all there. */
  #delete, #model-undo { font-family: var(--font-ui); font-size:12px; font-weight:600;
    letter-spacing:0.06em; text-transform:uppercase; cursor:pointer;
    color: var(--ink-primary);
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    border:1px solid var(--edge-panel); border-radius:6px; padding:6px 14px; }
  #delete:hover, #model-undo:hover { color: var(--accent); border-color: var(--accent); }
  #delete[hidden], #model-undo[hidden] { display:none; }

  /* THE MIDDLE PRESS: the bone, the one press the sign covers. DELETE, COPY
     and PASTE travel with it because they are verbs, not places.

     THE BONE STANDS ON THE SHEET'S CENTRE LINE (Movie, 16 Sep), the same
     axis the instrument rule at the top of the page stands on -- so it is
     placed absolutely at 50% rather than centred by flex spacers, which
     centre on what is LEFT OVER between two corners that never weigh the
     same. The verbs line up to its right, clear of the bone's own box, so a
     selection appearing cannot walk the bone off the axis. */
  /* STOPS ABOVE THE LANE. `bottom:0` on an absolutely positioned child
     resolves against the PADDING box, so the bar -- and the bone centred
     in it -- sat over the browser's strip while every other tenant of the
     row cleared it. Measured: the bone's foot was 15px off the floor
     against the page row's 32. */
  /* THE VERBS USED TO CLEAR THE TRIO BY RESERVING PADDING HERE -- half the
     bone plus an arrow and two gaps -- which put UNDO hard against the trio's
     right. Movie, 14 Oct: "too close to the bone", and then "actually can
     these UNDO etc buttons go on the LEFT side of the bone, there is more
     space because the button text on that side isn't as long". They are in
     #dt-verbs now, placed by seatFootVerbs(), so this box carries nothing in
     flow and reserves nothing: it is the anchor the trio and the verbs are
     both measured from. */
  #dt-bar { position:absolute; left:50%; top:0; bottom:var(--browser-lane);
    display:flex; align-items:center; gap:8px; }
  /* CENTRED ON THE BONE'S OWN LINE, not on #dt-bar's -- "it should be
     centered UP/DOWN same as the bone please". That is the same
     `50% + lane/2` the trio uses, and for the reason written against it: the
     lane is the bar's hem and half of it is not the middle of the bar.
     `left` is written by the seat; the transform is what makes that number
     the group's MIDDLE rather than its left edge, which is what "center
     them both out" asks for when a second verb arrives. */
  #dt-verbs { position:absolute; top:calc(50% + var(--browser-lane) / 2);
    transform:translate(-50%, -50%); display:flex; align-items:center; gap:8px;
    white-space:nowrap; }
  #dt-verbs[hidden] { display:none; }
  /* THE TWO ARROWS ARE ONE SIZE, which is what makes the trio symmetrical:
     a wider UP than DOWN would shift the bone off the axis by half the
     difference. Square, and the same height as the verbs beside them. */
  #trio-up, #trio-down {
    width:var(--foot-arrow-w, 30px); height:var(--foot-arrow-w, 30px);
    display:flex; align-items:center; justify-content:center;
    font-size:11px; line-height:1; cursor:pointer;
    color: var(--ink-primary);
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    border:1px solid var(--edge-panel); border-radius:6px; padding:0; }
  #trio-up:hover, #trio-down:hover {
    color: var(--accent); border-color: var(--accent); }
  #trio-up[hidden], #trio-down[hidden] { display:none; }
  /* THE FOOT'S BONE is the same red bone that sits on the sign's post --
     one artwork for one press, so the two bones cannot start looking like
     two different verbs. Its own box is centred on the strip's 50% axis,
     the same axis the instrument divider above it stands on. */
  /* AND ON THE STRIP'S OWN MIDDLE VERTICALLY, not #dt-bar's. Movie, 25 Sep,
     looking at the foot in both skins: "move the bone / house both down so
     they are centered/ top/bott in the menu at the bottom".
     WHAT HE WAS SEEING, measured at 1366x668: the bar stands 64px tall and
     the press sat at y=608..642 inside it -- 4px of air above, 26px below --
     because #dt-bar stops above the browser lane and 50% of a 40px lane is
     not the middle of a 64px bar. The lane is the bar's own hem, painted in
     the bar's own panel colour, so to the eye it is bar; the one thing on the
     row big enough to show it was riding high was the 34px press.
     `+ lane/2` AND NOT `bottom:0` ON #dt-bar, which would have been the
     one-token version: DELETE, COPY and PASTE ride in that same box and they
     line up with the page row across the bar, which is an alignment the verbs
     should keep. Only the press moves, because only the press is tall enough
     for the difference to read. */
  /* UP / BONE / DOWN, ONE TRIO ON ONE LINE (Movie, 14 Oct): "put the UP arrow
     to the left of the bone and DOWN arrow to the right ... so they all line
     up (UP / BONE / DOWN)", "(make it look symetrical makes it more
     appealling".
     THE TRIO TAKES THE BONE'S PLACE ON THE AXIS, which is the same thing said
     twice: the two arrows are one size and sit one either side, so centring
     the trio leaves the bone exactly where centring the bone put it -- on the
     sheet's centre line, the axis the instrument rule above it stands on.
     Written as ONE absolutely-placed box rather than three, because three
     boxes measured off each other is how a hidden arrow (LAYOUT and PROJECT
     ship both hidden) would walk the bone off the axis. A hidden flex child
     takes no room, and the box stays centred on whatever is left. */
  #dt-trio { position:absolute; left:0; top:calc(50% + var(--browser-lane) / 2);
    transform:translate(-50%, -50%); display:flex; align-items:center; gap:10px; }
  #bone { padding:0; border:none;
    background:none; line-height:0; cursor:pointer; }
  #bone img { display:block; height:var(--foot-press-h, 34px); width:auto; }
  #bone:hover img { filter:brightness(1.12); }
  /* THE BONE LIGHTS BEFORE THE BOARD RISES, which was the house button's job
     until the house button came off the strip. One artwork, so the glow is a
     filter rather than a second file -- and it is the same two seconds. */
  /* THE GLOW'S RED IS NAMED ONCE. shared-shell-harness.js allows each colour
     literal in this file exactly ONE occurrence, so the pulse below cannot
     repeat it -- and should not want to: the lit state and the ask are the
     same light at different strengths, which is what one name says and three
     copies would not. */
  #bone { --bone-glow:rgba(255,64,51,0.75); }
  #bone[data-lit] img { filter:brightness(1.3)
    drop-shadow(0 0 7px var(--bone-glow)); }
  /* AND ROUGH'S GLOW IS DRAWN, NOT FILTERED. Its ON state is its own file --
     the neon is painted into it, with a falloff and a white-hot core no
     filter produces -- so the swap IS the light, and the rule above would
     only wash it out. A red halo around a blue house would be a second light
     source besides, and the two seconds before the board rises are exactly
     when the press has the drafter's eye. */
  html[data-theme="rough"] #bone[data-lit] img { filter:none; }
  /* AND IT ASKS FOR THE PRESS, not just states it. data-ready is MODEL's
     "this order can be placed"; it reached only the SIGN's bone, so the foot
     press never pulsed -- and on ROUGH there is no sign bone at all, which
     left a chosen house, a full board and nothing on screen asking to be
     pressed. Movie, 24 Sep: "when the 'BONE' is pulse glowing the 'HOUSE'
     should be 'pulse glowing' but doesn't so user is confused if it doesn't
     do this".
     ONE ATTRIBUTE, TWO PICTURES -- his own rule for these buttons: "the
     style is different but the bone and house are the same button". */
  /* AND THE PULSE ADDS NO COLOUR AT ALL. It breathes on BLUR and BRIGHTNESS
     at the lit state's own red, so the ask is plainly the same light turned
     up rather than a second one. Caught by the harness, not by eye: the first
     draft breathed between three alphas and put two more literals in a file
     that is allowed one of each. */
  @keyframes bone-foot-ask {
    0%, 100% { filter:brightness(1.12) drop-shadow(0 0 4px var(--bone-glow)); }
    50%      { filter:brightness(1.38) drop-shadow(0 0 13px var(--bone-glow)); }
  }
  #bone[data-ready]:not([data-broke]) img {
    animation:bone-foot-ask 1.4s ease-in-out infinite; }
  /* ROUGH PULSES THE PICTURE, NOT A FILTER, for the same reason its lit
     state is a file rather than a glow: the neon is painted in, and a red
     halo round a blue house would be a second light source. A breath of
     scale reads on artwork that already carries its own light, and it is
     the same 1.4s so the two themes ask at one rhythm. */
  @keyframes bone-foot-ask-rough {
    0%, 100% { transform:scale(1); }
    50%      { transform:scale(1.07); }
  }
  html[data-theme="rough"] #bone[data-ready]:not([data-broke]) img {
    animation:bone-foot-ask-rough 1.4s ease-in-out infinite;
    transform-origin:50% 50%; }
  /* AN EMPTY WALLET STILL WINS, which is why both rules above exclude it
     rather than relying on order: a press pulsing for a build it cannot pay
     for is the same contradiction the grey-out was written against. */
  @media (prefers-reduced-motion: reduce) {
    #bone[data-ready] img,
    html[data-theme="rough"] #bone[data-ready] img { animation:none; }
  }
  /* THE NUMBER RIDES ON THE PRESS (board #261, MODEL.dc.html:558), and WHERE
     it rides is a fact about the ARTWORK rather than about the wallet --
     which is why the offset lives in BONE_ART beside the two pictures and
     not here. Movie, 19 Sep: "put the number on the bone under the bone in
     the red area and put the number in the house centered in the middle of
     the house outline", and then, on being shown why those are one rule:
     "yes exactly the style is different but the bone and house are the same
     button".

     aria-hidden, and the title carries the wallet in words instead. A screen
     reader reading "3" off a button called BONE says nothing useful; the
     title says three bones, when the next one lands, and what a build costs. */
  #bone-balance { position:absolute; left:0; right:0;
    transform:translateY(-50%); text-align:center; pointer-events:none;
    font-family: var(--font-ui); font-weight:700; color:#fff;
    text-shadow:0 1px 2px rgba(29,31,32,0.55); letter-spacing:0.02em;
    line-height:1; }
  #bone-balance:empty { display:none; }
  /* AN EMPTY WALLET GREYS OUT, and grey beats the lit glow: a bone glowing
     with nothing to spend is a contradiction. The rule sits after
     [data-lit] so it wins on the one press where both are true. */
  #bone[data-broke] img { filter:grayscale(1) brightness(0.82); }
  #bone .said {
    position:absolute; width:1px; height:1px; margin:-1px; padding:0;
    overflow:hidden; clip:rect(0 0 0 0); white-space:nowrap; border:0; }
  /* AND THE SAME SHELL AGAIN for the two file questions, for the same reason:
     three kinds of modal would teach the drafter that they are three
     different kinds of thing. They are one -- a question that must be
     answered before the page does what was asked. */
  /* PROJECT's BUILD question (DRAW OUTLINE / NO OUTLINE) is one more of
     them, so it wears this shell rather than a scrim of its own. */
  #file-guard, #save-as, #project-build-ask { position:fixed; inset:0; z-index:7; display:flex;
    align-items:center; justify-content:center; padding:24px;
    background:rgba(0,0,0,0.35); }
  #file-guard[hidden], #save-as[hidden], #project-build-ask[hidden] { display:none; }
  #save-as-name { width:100%; box-sizing:border-box; margin:0 0 12px;
    padding:7px 9px; border-radius:3px; border:1px solid var(--edge-panel);
    background-color: var(--surface-chip); color: var(--ink-primary);
    font-family: var(--font-mono); font-size:13px; }
  #save-as-name:focus { border-color: var(--accent); outline:none; }

  /* ══ THE RAILS ══════════════════════════════════════════════════════════
     The two pull-out sidebars and their tabs, moved here on 23 Sep so
     PROJECT can wear the same one. MODEL's own heading for this block was
     already "THE SHELL" -- the rails were always part of it; they simply did
     not come across when the bars did.

     THE SHELL IS SHARED, THE CONTENTS ARE NOT, which is the same split the
     bars settled into. A tab and a panel that slides in beside it are the
     same furniture on every page; what goes INSIDE is the page's own and
     stays there -- MODEL keeps its drafting tools, its levels and its
     previews, and PROJECT will put the project's own information in.

     A PURE MOVE, NO VALUE CHANGED. That is said because the last thing this
     file took from MODEL -- the box model -- changed one, and a 1px strip
     moved the drawing's camera half a pixel and broke a boneyard drag. The
     rails feed fit() the same way, so this one was proved the same way the
     bars were: getComputedStyle over every property of every element in both
     rails, open and shut, on two skins, before and after.

     The comments below are MODEL's own and travel with the rules they
     explain. */
  /* ── THE SHELL ─────────────────────────────────────────────────────────
     Two pull-out sidebars and their tabs. The SHAPE is MODEL.dc.html's
     (.rail-tab at :147-150): a full-height tab on each edge, vertical
     lettering, the panel sliding in beside it. The stylesheet is not carried
     across -- that page has one light skin and hardcodes #fff and #1d1f20,
     so every colour here is a palette token.

     BOTH START CLOSED, which is the old page's own default
     ("pull-out tabs: both side rails start hidden", :3009) and the only
     state that costs the drafter no drawing area at all. The four
     combinations are measured in tests/model-html-shell.spec.js. */
  /* THE TAB IS AS TALL AS ITS WORD, not as tall as the sheet. MODEL.dc.html's
     tabs run the full edge (:147, top:0 bottom:0) because that page's canvas
     is inset; here the canvas is full-bleed, so a full-height tab is a full-
     height bite out of the drawing. Measured: the full-height pair plus a
     full-height collapsed strip hid 9.7% of the house with both panels SHUT,
     which was worse than the 5.5% of the corner rail they replaced. */
  /* TOP-ALIGNED, NOT CENTRED, and this is the largest single number in the
     shell. fit() centres the drawing, so a vertically centred panel sits
     exactly where the house is: centred cost 4.5% of the drawing with both
     panels shut, top-aligned costs 1.3%. Bottom-aligned ties it at 1.2% and
     loses, because the readout and the hint already live along that edge. */
  /* BELOW THE TOP ROW, not beside it. The row spans the sheet's top edge, so
     a panel starting at the same y sits under it -- measured with a pairwise
     box check across every piece of chrome, and top:12 put the row over BOTH
     rails (over the first seat row on the right, over the tool slot on the
     left when open). Bottom-anchoring is cheaper still but puts the rails on
     #readout and #hint, which already live along that edge.
     Only this clears everything: shut 7.3% of the drawing against 3.4% at
     top:12. Four points is what a top bar costs, and chrome that covers
     chrome is a defect where drawing area is a price -- both panels collapse,
     so the drafter can have the sheet back. */
  .rail-tab { position:fixed; top:var(--rail-top); z-index:6;
    height:auto; max-height:52vh; padding:14px 6px;
    display:flex; align-items:center; justify-content:center;
    border:1px solid var(--edge-panel); cursor:pointer;
    background-color: var(--surface-chip); background-image: var(--surface-chip-tex, none);
    color: var(--ink-quiet); font-family: var(--font-ui); font-size:13px;
    font-weight:600; letter-spacing:0.14em; line-height:1;
    writing-mode:vertical-rl; text-transform:uppercase; }
  .rail-tab:hover { color: var(--accent); border-color: var(--accent); }
  .rail-tab[hidden] { display:none; }
  /* THE LEFT EDGE CARRIES THREE (Movie, 29 Sep). Same sequence rule the right
     edge's two use: each tab starts where the last one's CAP ends, so the
     stack is derived from one number rather than eyeballed at the window
     height I happened to open.

     18vh, NOT THE 32vh THE RIGHT PAIR USE, and the arithmetic is written down
     because three tabs is where this stops being obvious. The last tab's foot
     is at most `--rail-top + 3*cap + 16`, and it has to clear the bottom band.
     At the three heights that are actually tested -- 700 (the elevation spec),
     768 (the commonest laptop) and 900 (the config default) -- 18vh leaves
     70px, 102px and 162px of clearance. 22vh passes at 768 and 900 and FAILS
     at 700 by 14px, which is exactly the kind of "works where I looked"
     spacing the right edge's own note warns about. */
  #left-tab, #build-tab, #props-tab { left:0; border-left:none;
    border-radius:0 4px 4px 0; max-height:18vh; }
  #build-tab { top: calc(var(--rail-top) + 18vh + 8px); }
  #props-tab { top: calc(var(--rail-top) + 2 * (18vh + 8px)); }
  /* The right tabs read bottom-to-top so both edges' tabs run outward from
     the edge they hang on. */
  #right-tab { right:0; border-right:none;
    border-radius:4px 0 0 4px; writing-mode:vertical-lr;
    max-height:32vh; }
  /* THE TAB OF THE OPEN PANE IS LIT, so the edge says which of the two the
     panel is showing without the drafter opening both to find out. */
  .rail-tab[aria-selected="true"] { color: var(--accent);
    border-color: var(--accent); }
  /* A TAB WITH SOMETHING BEHIND IT, when you are not looking at it. Arming a
     tool fills PROPERTIES whatever tab is up, and the page will not jump the
     drafter onto it -- its own rule, that a tool arming must not yank a panel
     under him. So the tab has to say so instead. A DOT, not the accent
     colour: `aria-selected` already owns that, and a tab that is both
     selected and full would otherwise have one appearance for two facts. */
  .rail-tab[data-has-props]:not([aria-selected="true"])::after {
    content:''; position:absolute; inset-inline-end:2px; inset-block-start:4px;
    width:5px; height:5px; border-radius:50%; background: var(--accent); }
  /* A panel is pinned to its own edge and is as tall as it needs to be, for
     the same reason as the tab: full height costs drawing area that a panel
     holding three rows of seats is not using. */
  /* INSIDE A MENU, THE ACCENT IS THE MARK COLOUR. Movie, 17 Sep: "small
     things for NIGHT version only to turn gold - the stuff outlines and text
     in the menu areas (easier to see when its small if gold when black
     background)", with the SELECT key's red border and red label ringed on
     the screenshot he sent back.

     ONE REDEFINITION, NOT THIRTY-FIVE EDITS. The accent is read through
     var(--accent) at 35 line-and-text sites, and rewriting each to name a
     second token would be 35 chances to miss one -- and a miss would be
     invisible, since a red hairline on black looks like a styling choice
     rather than a bug. Redeclaring the property on the subtree lets every one
     of them pick the mark up unchanged, including any added later.

     AND IT CARRIES NO SKIN LOGIC. accent-mark EQUALS accent on three of the
     four skins, so this rule is true everywhere and the one place the two
     differ is the palette table. An html[data-theme][data-mode] selector here
     would have put the same fact in two files.

     THE RAIL TABS NEED THEIR OWN NAME because they are fixed siblings of the
     panel rather than children of it -- they are the menu's edge, and the
     drafter reads them as part of it. */
  aside, .rail-tab { --accent: var(--accent-mark); }
  aside { position:fixed; top:var(--rail-top);
    /* STOPS ABOVE THE HINT. 100vh - 60 let the panel run to within 12px of the
       bottom, which was fine while it held a rail and an empty slot and is not
       once the LEVELS / LAYERS panel is inside it: expanded, it reached the
       "drag to pan" hint at bottom:12px and the pairwise chrome check caught
       it -- the fifth collision that check has found, and the fifth that was
       invisible until something was measured rather than looked at. The hint
       sits above the strip, so the panel has to end above the hint's top.

       PINNED BY `bottom`, NOT BY max-height, and that is the fix for a fault
       this cost twice. max-height sizes the CONTENT box, so with padding:10px
       the panel stood 20px taller than the number asked for -- 644 where 624
       was written -- and overlapped the hint by a single pixel. Giving the box
       a top AND a bottom lets the browser do that arithmetic, and deriving the
       bottom from --strip-h means the strip can move without this going stale
       again. The collapsed cap below is a max-height still, and being smaller
       it wins. */
    bottom:var(--bottom-band); z-index:5; overflow-y:auto;
    /* BORDER-BOX, AND THE PAGE DOES NOT GET A VOTE. --rail-w is one number
       for every rail on every page, and :176 above records that MODEL has no
       global `* { box-sizing:border-box }` while PROJECT and SPECS do -- so
       without this line the same token would mean 195px on one page and
       195 + 20 + 1 on another, which is the opposite of what it was written
       for. Named here for the same reason #file-guard names it at :187. */
    box-sizing:border-box; width:var(--rail-w);
    /* THE BAR'S LANE IS ALWAYS THERE, showing or not -- see --rail-w. */
    scrollbar-gutter:stable;
    overscroll-behavior:contain; padding:10px;
    background-color: var(--surface-panel); background-image: var(--surface-panel-tex, none); }
  aside[hidden] { display:none; }
  /* `min-width:120px` CAME OFF BOTH ENDS OF THE SAME CHANGE. It was the floor
     under a shrink-to-fit panel -- the rail could not collapse to the width of
     its narrowest section when a pane held only a line of text -- and a rail
     with a width has no shrink to put a floor under. */
  /* AS TALL AS WHAT IS IN IT, ONCE THE COLUMN CAME APART. `aside` above pins
     a rail top AND bottom, which was right while the left one held a single
     691px column -- it was always taller than the box. Split across three
     tabs the tallest pane is about 350px, so a pinned bottom leaves 180px of
     empty panel under nine tool keys. Movie, looking at the mock: the rail
     "probably wants to shrink to its content".
     THE PIN BECOMES A CEILING, not nothing. `bottom:auto` alone would let a
     tall properties panel run down over the foot bar; `max-height` keeps the
     exact same floor the pin gave and lets anything shorter stop early. The
     scroll in `aside` still catches whatever exceeds it.
     LEFT ONLY. The right rail holds one bounded panel that is meant to fill
     its height, and its seats are measured against that box by three specs. */
  #left-rail { left:28px; border-right:1px solid var(--edge-panel);
    bottom:auto;
    max-height: calc(100vh - var(--rail-top) - var(--bottom-band)); }
  /* THE PANEL IS BOUNDED, and --rail-w is the rule that keeps it off the
     sheet. It used to be `max-width:277px` here, and the history is worth
     keeping because it is the reason the bound is a bound and not a trim.
     `aside` was position:fixed with no width, so it was SHRINK-TO-FIT: as
     wide as its widest content's MAX-content, with nothing stopping it. That
     was survivable while the LEVELS panel held level cards; the boneyard's
     card put a title AND a + SHELF button on one line and took the rail from
     277px to 343px, which moved its left edge to x=909 and put it over the
     drawing. model-html-draw-delete caught it: a tap aimed at world (4,-3)
     reached the right sidebar instead of the canvas. I shipped that in the
     boneyard commit because the run covered the boneyard cascade and not that
     spec.
     WHY A BOUND RATHER THAN A SHAVE. The card was not uniquely guilty --
     measured, FOUNDATION's card wanted exactly the same 343px -- so trimming
     the boneyard's label would have handed the width to the next card and the
     bug would have come back wearing different clothes. The same answer the
     instrument strip got when PRINTSCREEN overflowed it at 1280: bound the
     furniture and let its contents yield, rather than trim whichever tenant
     happens to be longest this week.
     THE OLD 277 WAS MEASURED, NOT ESTIMATED, and the difference mattered. I
     first bounded this at 288 -- the seat grid's own width, worked out from
     two 82px seats and their gaps -- and model-change-broadcast still failed:
     at 288 the rail's left edge sits at x=964, and a tap aimed at world (6,-2)
     lands at 967, three pixels inside it. 277 was what the rail measured on
     main, where that tap clears by eight. An estimate that is nearly right is
     a panel that nearly stays off the sheet.
     195 IS 82px NARROWER THAN THAT AND SO CANNOT REOPEN IT: every tap those
     two specs aim at the canvas clears this rail by more than it ever cleared
     277. What the narrower bound costs is ellipsis on the longest level names,
     which the paragraph beside --rail-w already rules on. */
  #right-rail { right:28px; border-left:1px solid var(--edge-panel); }
  /* THE RIGHT PANEL COLLAPSES TO A SEAT, NOT TO NOTHING (Devin, 12 Sep).
     MODEL.dc.html's rail comment (:1766) says the open LEVELS panel covers
     only the outer column and "the inner column always keeps its seat, so
     every view stays one tap away" -- a property it protects deliberately,
     and one that a panel closing to zero would have destroyed.
     So collapsed still holds all six seats and drops the properties, which has
     no such claim on the edge.

     BUT NOT AS A SEAT-WIDE STRIP, and the measurement is why. A strip one seat
     across is six seats TALL, and a tall narrow panel is the worst possible
     shape here: fit() centres a house that is wider than it is deep, so a
     column runs down through it while a squat block sits past its end. On
     repro-garage-house, collapsed, percentage of the DRAWING hidden:

         1 column   97x486   9.4%     <- the strip, and the worst of them
         2 columns 187x246   6.5%
         3 columns 277x166   4.5%     <- widest and shortest, the best
         (expanded 195x254   6.7%)

     One column also cost MORE than leaving the panel open, which would have
     made collapsing pointless, and more than the 5.5% of the corner overlay
     this shell replaced. So collapsed goes WIDE and SHORT: same six seats,
     same order, no properties, 4.5%. */
  /* COLLAPSED IS CAPPED, AND THE CAP IS THE ONLY THING THAT BOUNDS IT once
     the chart is derived. At six seats "wide and short" was enough -- 3
     columns beat 1 at 4.5% against 9.4%. At FOURTEEN there is no shape that
     works, because the panel is large in both directions whichever way it is
     folded; measured on repro-garage-house, collapsed:

         3 columns  277x406  13.2%      4 columns  367x326  14.3%
         5 columns  457x246  14.5%      6 columns  547x246  19.9%

     Every one of those is worse than the 9.7% full-height version rejected
     during #389 for being worse than the corner overlay it replaced. So the
     height is capped and the rest scrolls, which is what MODEL.dc.html does
     with its own rail (:183, top/bottom pinned with overflow-y:auto):

         3 columns, capped 150px   277x162   4.3%   <- shipped
         2 columns, capped 220px   187x232   5.8%
         3 columns, capped 220px   277x232   8.5%

     150px is two rows, so collapsed still shows SIX seats at a glance -- the
     whole rail as it stood before the chart grew -- and the other eight are
     one scroll away. Devin withdrew "simultaneously visible" in favour of
     "reachable means one click"; this is that ruling costing eight seats a
     scroll rather than costing the drafter 13% of the sheet. */
  /* SHUT IS SHUT (Movie, 16 Sep): shown two presentations of the levels
     panel side by side he kept the long one and said "delete the 2nd
     shorter version" -- so the charts above are history, not law. A
     collapsed rail shows NOTHING: the tabs on the edge are the whole
     collapsed state, and each pane has exactly one face, its open one.
     §7c's worry (a shut rail takes the level switch away) is answered by
     the tab itself: LEVELS / LAYERS is one press, same as the chips were. */
  #right-rail[data-collapsed] { display:none; }
  /* THE TOOL COLUMN. Four square keys a row, which is the old page's own
     shape and not a taste: at four across, DRAW/EDIT is three rows and BUILD
     is two, and the whole roster is reachable without the panel scrolling on
     a laptop. Three across would push it to six rows and start scrolling the
     one thing a drafter reaches for constantly.

     THE COMMAND LETTER SITS TOP-LEFT AND THE NAME ALONG THE BOTTOM, leaving
     the middle of the face clear. That gap is deliberate: the old page's keys
     carry an icon there and this page has none yet, so the space is held open
     rather than closed up and re-opened later at every caller. */
