/* metaeden-v4-membership.css -- TASK-1032[Q] Phase 1 (MEMBERSHIP BUREAU)
   Companion stylesheet to metaeden-v4.css: ONLY the membership bureau.  Win95
   chrome to match the site it lives in.  Repo readability rules hold: nothing
   readable below 12px, all text at 4.5:1+ on the #c0c0c0 chrome (checked;
   #333 = 5.3:1, #1c1c1c = 10.9:1, #0000bb link blue = 9.1:1).

   TASK-1039[Q]: THE BUREAU IS ITS OWN WINDOW.  It used to be a strip welded
   into the bottom of the sign-on window, so opening it also opened the screen
   name picker and the dialer.  #mbwin is now the site's OWN .w95 floating
   chrome (metaeden-v4.css supplies the shell, the title bar and the close box,
   exactly as the MET list and both instant-message windows get them); only the
   parking spot, the width, the z-order and the body are set here.
   Z-INDEX 75 -- ABOVE the whole dial-up choreography (buddywin 71, aimwin 72,
   imwin 73, pixwin 74) and above the sign-on window itself (70).  This window
   is always SUMMONED, never passive, so unlike TASK-1037[Q]'s retired note (70,
   deliberately UNDER every conversation) it must never open behind the thing
   that summoned it.  The ONE exception is the sysop's word, which BLOCKS a
   dial: for as long as that modal is up the companion puts .mbtop on #aolwin,
   which carries the word with it over the desk.  z-index only -- no state on
   either window changes a box-model property. */
/* TASK-1042[Q]: 880px, up from TASK-1040[Q]'s 660.  The member face is a CARD
   (a 188px cream artifact) beside an ETCHED GROUP BOX, and the group box has
   to hold a heading and its action links on ONE line each -- the designer's
   own hard rule.  880 leaves the box ~618px of content, which fits the longest
   heading (3. COPY THE CODE OR DOWNLOAD THE CODE) and the two selectable value
   boxes side by side; it also lets the three footer buttons share one row with
   ~150px to spare.  The window got WIDER and much SHORTER: the whole point of
   the redesign was halving the height.
   The max-width is unchanged in spirit and now matters more: below ~700px the
   window shrinks with the viewport, which drops the two columns' flex-basis
   floors (210 + 16 + 380) under the available content width and lets #mbMain
   WRAP the card above the group box.  Static -- it never changes on a state
   change, so it costs no jitter -- and mbWinPlace reads the REAL offsetWidth,
   so its own clamp follows automatically.  24px, not 16, so a classic overlay
   scrollbar counted inside 100vw cannot tip it over. */
/* TASK-1323[Q]: 880 -> 600. The desk was a wide box holding one short line, and
   880px was never measured against anything -- at that width the copy sets in a
   single stripe across the top and the eye travels the whole span to read
   twenty-one words.
   600 is the MEASURED floor, not a taste call. I first cut to 560 and the rig
   caught what eyeballing one face could not: #mbReissueConfirm is a confirm
   question plus YES, ISSUE IT and CANCEL on ONE row, and it stacks below 600.
   Sweeping every face of this window from 520 up in 10px steps, 600 is the
   lowest width where that row still holds -- every other multi-button group
   (#mbKeyRow one row, #mbHaveShutRow stacked) reads identically at 600 and at
   880, and nothing overflows at either. So 600 keeps TASK-1042's one-row rule
   intact and still gives back 280px.
   Headroom is unchanged: 600 + the 24px clamp is 624, well inside the 1024
   viewport the prior tickets measured against. The max-width guard is
   untouched, so a narrower window still wins and wraps rather than overflows. */
#mbwin{position:fixed;left:calc(var(--page-inset-left,0px) + 24px);top:calc(var(--page-inset-top,0px) + 76px);width:600px;max-width:calc(100vw - 24px);display:none;z-index:77}
#mbwin.open{display:block}
/* TASK-1327[Q]: THE CARD FACE IS WIDER, WHICH IS WHAT MAKES IT SHORTER.
   #mbMain lays the card and the ways box side by side and WRAPS below 606px
   of content width -- its own comment above says so, and 600 (TASK-1323[Q])
   sits just under that line.  So the create face got narrow and this face
   silently stacked into one very tall column: 792px of window inside a frame
   band only 683px tall, which no placement can fit, so it rode up over the
   browser chrome and clipped.  Widening is the fix for the height AND for
   the clipping, because they are the same problem.  920 clears 606 of
   content with room for the card column to breathe, and stays under the
   ceiling E8.29 measures against.  The class is toggled at the ONE place the
   face itself is switched, so the width can never disagree with the face. */
#mbwin.wide{width:920px}
/* ...and no face may exceed the band again.  max-height is set by mbWinPlace
   (only it knows how tall the frame band is); the title bar stays OUTSIDE
   the scroll, which is the house rule for panels -- header at natural
   height, variable content scrolling under it. */
#membox{overflow-y:auto}
#aolwin.mbtop{z-index:78}
/* The window's height follows WHICH FACE was summoned (create / restore /
   member) -- a user-initiated state change, the documented exception to the
   fixed-panel rule -- and this cap is a viewport FLOOR under the tallest one,
   the same trade #aolwin.open already makes, not a data-driven resize.
   TASK-1042[Q]: #membox has NO side padding of its own any more -- each BAND
   owns its own 16px sides, because the masthead is a full-bleed teal band and
   a shared inset would have left a chrome-coloured gutter down both sides of
   it.  Faces that are not banded (create, guest, restore) get .mbface. */
#membox{background:#c0c0c0;padding:0 0 12px;font:13px Tahoma,Verdana,sans-serif;color:#1c1c1c;max-height:calc(100vh - 150px);overflow-y:auto}
#membox .mbface{padding:12px 16px 2px}
#membox .msmall,#mbOptWin .msmall{font-size:13px;color:#333}
/* ---- TASK-1042[Q] BAND 1: the masthead ------------------------------------
   A teal service band across the top of every face.  Contrast on #00807f:
   #d5f2f2 is 8.1:1, #fff is 9.9:1, #ffe600 is 8.4:1 -- all well past 4.5.
   The bottom edge is a 6px strip of a 6x6 two-square checker tile painted
   OVER the chrome below it, which is how a 16-colour screen made a soft edge.
   It is decoration only and sits in ::after, so it cannot affect layout. */
#membox #mbMast{background:#00807f;color:#fff;padding:5px 16px 4px;position:relative}
#membox #mbMast::after{content:"";position:absolute;left:0;right:0;bottom:-6px;height:6px;background:url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="6" height="6"><rect width="3" height="3" fill="%2300807f"/><rect x="3" y="3" width="3" height="3" fill="%2300807f"/></svg>')}
#membox #mbMast .eyebrow{font:700 12px Verdana,sans-serif;letter-spacing:3px;color:#d5f2f2;margin-bottom:2px}
#membox #mbMast .bigname{display:flex;align-items:baseline;gap:14px;flex-wrap:wrap}
#membox #mbMast h1{margin:0;font:700 21px Verdana,sans-serif;letter-spacing:4px;color:#fff}
#membox #mbMast h1 .tri{color:#ffe600}
#membox #mbMast .deskno{margin-left:auto;font:700 12px "Courier New",monospace;letter-spacing:2px;color:#d5f2f2}
#membox .mrow{margin:7px 0;display:flex;align-items:center;gap:8px;flex-wrap:wrap}
#membox .mrow label{font-weight:700;font-size:13px}
#membox b{font:700 15px "Courier New",monospace;letter-spacing:1px}
#membox input{font:14px Tahoma,Verdana,sans-serif;border:2px inset #fff;background:#fff;color:#000;padding:3px 5px;width:180px}
#membox #mbrNum{width:150px}
#membox #mbrSec{width:280px}
/* TASK-1324[Q]: the name row, which is the one row a first-time visitor has
   to actually use.  Its label moves ABOVE the field and the field doubles.
   Done in CSS with no change to the markup on purpose: the copy layer binds
   this face by CHILD INDEX (mbNone::c1.c0 is the label, c1.c2 the rule), so
   wrapping the label and input in a sub-div would silently repoint both
   strings at the wrong nodes.  The row is already display:flex + wrap, so a
   full-width label is all the break it needs, and the label is reached by
   its for= rather than :has() so nothing depends on parent selection. */
#membox .mrow label[for="mbNewName"]{flex:0 0 100%;margin-bottom:2px}
/* 180 -> 360 and 14px -> 28px: twice as large, and twice as legible inside.
   Padding goes with it or the field is wide and flat.  Two IDs here beat the
   one-ID #membox input shorthand above, which still supplies the family. */
#membox #mbNewName{width:360px;font-size:28px;padding:6px 10px}
/* the sign-on window's own button rule is scoped #aolwin .aolbtn, and the
   bureau no longer lives inside that window -- so restate it verbatim here
   (the same thing TASK-1037[Q]'s note had to do) and keep the tighter padding
   the strip has always used. */
#membox .aolbtn,#mbOptWin .aolbtn{background:#00807f;color:#fff;border:2px outset #7fd4d4;font:700 13px Verdana,sans-serif;letter-spacing:1px;cursor:pointer;padding:5px 12px}
#membox .aolbtn:active,#mbOptWin .aolbtn:active{border-style:inset}
#membox .mbm{cursor:grab;touch-action:none}
/* TASK-1042[Q]: the save-method ACTIONS are classic text links now, not a
   stack of buttons -- the designer's third goal.  #0000bb on the #c0c0c0
   chrome is 9.1:1 and on the #f4efe2 card cream 11.4:1; the hover only
   darkens the colour, so nothing about the box moves on hover. */
#membox .mwlink{color:#0000bb;text-decoration:underline;cursor:pointer}
#membox .mwlink:hover{color:#000080}
/* TASK-1040[Q]: the number and the code are SELECTABLE TEXT the member is
   told to write down, so one click selects a whole value (COPY THE CODE next
   to them is the no-selection path).  user-select is not a box-model property
   and does not change between states. */
#membox .ccodes b{background:#fff;border:2px inset #fff;padding:1px 6px;font-size:12px;letter-spacing:0;-webkit-user-select:all;user-select:all}
/* ---- TASK-1042[Q] BAND 6: the sysop's memo (BAND 5 before TASK-1043[Q]) ---
   A pinned cream slip with an envelope glyph and a FROM line.  #7a6a2a on
   #fffbe6 is 5.2:1 (readable, not decoration); the body keeps #1c1c1c at
   13.4:1.  The glyph is absolutely positioned inside the reserved left pad, so
   it cannot reflow the body. */
#membox .mnote{margin:6px 0 0;background:#fffbe6;border:1px solid #7a6a2a;padding:6px 12px 6px 34px;font:13px/1.4 Tahoma,Verdana,sans-serif;color:#1c1c1c;position:relative}
#membox .mnote::before{content:"\2709";position:absolute;left:10px;top:6px;font-size:16px;color:#7a6a2a}
#membox .mnote .nfrom{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#7a6a2a;display:block;margin-bottom:2px}
/* ---- TASK-1042[Q] BAND 2: the member strip --------------------------------
   The plate is an engraved nameplate; the number keeps this file's own <b>
   monospace face.  The greet is a full-width sunken readout with a teal
   information chip, so the arrival's own words read as something the desk
   PRINTED rather than another paragraph of chrome text. */
#membox #mbMember{display:flex;align-items:center;gap:12px;flex-wrap:wrap;padding:7px 16px 2px}
#membox .plate{display:inline-flex;align-items:center;gap:8px;background:#d7d7d7;border:2px groove #fff;padding:4px 10px}
#membox .plate .plbl{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#555}
/* TASK-1046[Q]: THE SCREEN NAME ON THE PLATE.  The desk knows a name in most
   member states and was printing only the number, so the plate now reads
   MEMBER MET-8228-6859 | wanderer.  A hairline rule (not a glyph) divides the
   two so the pair reads as one engraved object; #12403f on the #d7d7d7 plate
   is 5.7:1.  Shown only while there IS a name -- a nameless thread would
   otherwise print a stray divider with nothing after it. */
#membox .plate .plname{font:700 13px Verdana,sans-serif;letter-spacing:1px;color:#12403f;border-left:1px solid #9a9a9a;padding-left:8px}
#membox #mbGreetBox{flex-basis:100%;margin:3px 0 0;background:#fff;border:2px inset #fff;padding:4px 10px;color:#1c1c1c;display:flex;gap:8px;align-items:flex-start}
#membox #mbGreetBox .gi{flex:0 0 auto;width:16px;height:16px;background:#00807f;color:#fff;font:700 12px "Courier New",monospace;display:grid;place-items:center;margin-top:1px}
#membox #mbStandWhy{white-space:nowrap}
/* TASK-1038[Q]: the STANDING -- one thing, two states, never both.  It used to
   be a sentence and is now a rubber stamp; the gate, the flag it reads and the
   never-both rule are all unchanged, and the sentence each state carried lives
   on (probationary: the stamp's own tooltip plus #mbStandWhy beside it;
   registered: #mbLinked, where it always was).
   Contrast: #a11c1c on the #c0c0c0 chrome is 6.5:1, #12403f is 6.3:1 -- both
   readable text, not decoration.  The rotation is a transform, which does not
   participate in layout, so the strip's box is identical in both states and
   swapping stamps moves nothing. */
#membox #mbStanding{display:inline-flex}
#membox .stamp{font:700 14px Verdana,sans-serif;letter-spacing:3px;border:3px double currentColor;padding:3px 10px;transform:rotate(-3deg);background:rgba(255,255,255,.25);cursor:help;-webkit-user-select:none;user-select:none}
#membox #mbStandProb{color:#a11c1c}
#membox #mbStandReg{color:#12403f}
#membox [role="status"]{min-height:17px;display:inline-block}
/* phase 1b: the phone-vouch pairing panel (knock code + square).
   TASK-1045[Q]: the panel is part of the restore face now rather than something
   a button reveals, so it carries a FLOOR under its own box -- the held states
   (stale / busy / dead wire / stood down) drop the 150px square, and without a
   floor the CLOSE THIS WINDOW button under it would jump on every transition.
   The two mutually exclusive controls are separate rows for the same reason
   only one is ever shown at a time; the floor absorbs the difference. */
#membox #mbPair{margin:7px 0;padding:8px 10px;background:#d7d7d7;border:2px groove #fff;min-height:150px}
/* TASK-1046[Q]: the knock code rides the END of the lead sentence now, so its
   label and its value travel together as ONE flex item on that row and share
   the row's own 8px rhythm.  Both halves hide together with the square when the
   knock is not live -- a held panel shows no stale code and no stale square. */
#membox #mbPairKnock{display:inline-flex;align-items:center;gap:8px}
#membox #mbPairCode{background:#fff;border:2px inset #fff;padding:2px 8px;font-size:16px;letter-spacing:3px}
#membox #mbPairQr{display:block;background:#fff;border:2px inset #fff;padding:6px;width:150px;height:150px}
#membox #mbPairMsg{max-width:420px}
/* TASK-1034[Q]: the identity switcher + sign-off + the first-class square.
   The disabled seed names in the picker: the disabled ATTRIBUTE is the
   functional gate (unselectable in every browser); the grey + italic is the
   readable cue where option styling is honored.  Decoration-only grey is
   deliberate -- these entries are set dressing, not content to read. */
#aolwin select option[disabled]{color:#808080;font-style:italic}
#membox .aolbtn[disabled]{color:#808080;text-shadow:1px 1px 0 #fff;cursor:default}
/* the square, scannable off the glass: true dark-on-light, quiet zone kept by
   the white padding (the SVG carries its own margin too).  TASK-1042[Q] moved
   its surrounding chrome onto the CARD around it and took the square from 176
   to 168 -- still comfortably scannable at arm's length, and it is the number
   the card's own 188px column is built from. */
#membox #mbQrBox{margin:0}
/* TASK-1344[Q]: a SQUARE at the largest size that fits, not a square
   letterboxed inside a wide box. object-fit:contain centred the code
   correctly and left the inset border framing 310x171 of mostly white.
   Sized off the height with aspect-ratio holding it square, and capped by
   max-width so a short wide card shrinks it rather than overflowing. */
#membox #mbQrImg{display:block;box-sizing:border-box;background:#fff;border:2px inset #fff;padding:6px;height:100%;width:auto;aspect-ratio:1;max-width:100%;max-height:100%;margin:0}
#membox #mbSwitchNote .msmall,#mbOptWin #mbSwitchNote .msmall{display:block;max-width:560px}
#membox #mbLeaveWarn,#mbOptWin #mbLeaveWarn{display:block;color:#5a1010;font-weight:700}
#membox #mbGuestView .msmall{display:block;max-width:560px}
/* TASK-1035[Q]: the state-aware bureau.  Three new pieces, no new type sizes:
   the arrival pointer, the SIGN ON emphasis, and the MEMBERSHIP OPTIONS
   disclosure.  Contrast checked on the #c0c0c0 chrome: #12403f on the
   #e8f6f6 pointer panel is ~10.4:1, the .msmall #333 default is 5.3:1. */
#membox #mbNext{margin:7px 0 0;padding:6px 11px;background:#e8f6f6;border:2px solid #00807f}
#membox #mbNext .msmall{display:block;max-width:560px;color:#12403f;font-weight:700}
/* THE CTA.  The emphasis rides box-shadow (and animates only box-shadow), so
   it sits entirely outside the box model: SIGN ON never changes size, border
   width or position when the ring appears, and its neighbours never move.
   prefers-reduced-motion keeps the emphasis but drops the animation to a
   plain static ring. */
@keyframes mbctaPulse{0%,100%{box-shadow:0 0 0 1px rgba(255,230,0,.55)}50%{box-shadow:0 0 0 6px rgba(255,230,0,.95)}}
#aolwin .aolbtn.mbcta{box-shadow:0 0 0 3px rgba(255,230,0,.95);animation:mbctaPulse 1.7s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){#aolwin .aolbtn.mbcta{animation:none;box-shadow:0 0 0 3px #ffe600}}
/* THE DISCLOSURE.  A user-initiated collapse (the documented exception to the
   fixed-height panel rule), so it animates its own height deliberately rather
   than snapping.  visibility keeps the collapsed rows out of the tab order;
   the arrow sits in a reserved 13px cell so swapping the glyph cannot nudge
   the label, and the toggle's padding/border never change between states. */
/* TASK-1042[Q]: the disclosure now hangs off the FOOTER (the retired #mbCounter
   wrapper was a divider row; the toggle lives in a status-bar cell), and its
   body is a full-width sibling of the cells so the panel spans the window
   rather than the cell that opened it.  Mechanism unchanged. */
#membox #mbCounterBtn .mbarrow{display:inline-block;width:13px;text-align:left}
#membox #mbCounterBtn .mbarrow::before{content:"\25b8"}
#membox #mbCounterBtn[aria-expanded="true"] .mbarrow::before{content:"\25be"}
/* The overlay centres the sign-on window with place-items:center, which on
   overflow leaves the tail unreachable -- so keep it centred while it fits and
   let it SCROLL when it does not.  `safe` degrades to plain centring where it
   is unsupported.  TASK-1035[Q] added this because the bureau strip could
   outgrow a short laptop viewport from inside that window; TASK-1039[Q] moved
   the bureau out into its own window, so the sign-on window is short again and
   this is now purely a floor under a short-viewport edge -- kept, not needed
   day to day.  (The bureau's own cap is on #membox, above.) */
#aolwin.open{overflow-y:auto;align-items:safe center}
/* TASK-1036[Q]: the definitive sign-on flow.
   1. THE BUREAU IS SHUT ON A FRESH VISIT.  #membox is hidden by the companion
      (mbRender) rather than by a rule here, because the decision is stateful;
      the strip keeps its own chrome for every state that DOES show it. */
#membox #mbLeadNew,#membox #mbLeadName,#membox #mbLeadSwap{display:block;max-width:560px}
#membox #mbLeadSwap{color:#5a1010;font-weight:700}
#membox #mbRestShutRow{margin-top:8px;border-top:1px solid #9a9a9a;padding-top:8px}
/* TASK-1037[Q]: the member face's own way back out, in the same chrome as the
   restore face's (the counter is summoned now, so every face closes alike).
   TASK-1042[Q]: that way out is a status-bar cell now -- see #mbFoot .cell. */
/* 2. THE SYSOP'S WORD.  A period-correct second window over the sign-on
      window it is blocking -- it inherits #aolwin's .win / .tbar / .aolbtn
      chrome and only overrides the width and its own body.  position:fixed
      (not absolute) so nothing scrolling inside #aolwin can ever carry the
      disclaimer off-screen with it.  Text is #1c1c1c on the #c0c0c0
      chrome (10.9:1) at 14px; the footer link is the file's own #0000bb
      (9.1:1).  No state on this panel changes any box-model property. */
#mbWarn{position:fixed;inset:0;display:none;z-index:8;place-items:center;pointer-events:none}
#mbWarn.open{display:grid}
#aolwin.connecting #mbWarn{display:none}
#mbWarn .win{width:470px;max-height:92vh;overflow-y:auto}
#mbWarn .mwbody{padding:16px 18px 14px;background:#c0c0c0;color:#1c1c1c;font:14px/1.55 Tahoma,Verdana,sans-serif}
#mbWarn .mwbody p{margin:0 0 10px}
#mbWarn .mwbtns{display:flex;flex-wrap:wrap;gap:12px;margin:14px 0 2px}
#mbWarn .aolbtn{padding:8px 16px}
/* the recommendation is a STATIC ring on the register button: softly first
   among equals, never a pulsing nag -- and box-shadow only, so neither button
   moves by a pixel between states (repo no-layout-jitter rule). */
#mbWarn #mbWarnReg{box-shadow:0 0 0 3px rgba(255,230,0,.95)}
#mbWarn .aolbtn.mwplain{background:#c0c0c0;color:#1c1c1c;border:2px outset #fff;text-shadow:1px 1px 0 #fff}
#mbWarn .mwfoot{margin:12px 0 0;border-top:1px solid #9a9a9a;padding-top:9px}
#mbWarn .mwfoot a{color:#0000bb;font-weight:700;text-decoration:underline}
/* ---- TASK-1043[Q] BAND 3: what this desk knows, and the decision ----------
   The band the user asked to be "front and center", between the member strip
   and the ways.  Same etched group box + overlapping legend as #mbWaysBox, so
   the two read as a pair of service panels rather than two unrelated ideas --
   and the legend rule (.mblegend) is shared, not restated.
   Every KNOW line is its own block so the variants swap in place; they are the
   file's own .msmall (#333 on #c0c0c0 = 5.3:1) at its own 13px, so this band
   introduces no new type size and no new colour.
   NO LAYOUT JITTER: the three note variants, the three memory variants and the
   three re-issue leads each occupy the SAME slot, one at a time, and the swap
   is display only -- no box-model property of the band changes with state.  The
   confirm is a full-width row that opens BELOW the decision row, exactly as it
   did in the footer, so arming the rotation never moves the button that armed
   it.
   TASK-1044[Q]: the band is TWO lines now, not four paragraphs, and it stands
   down entirely once a code has been stamped (MB_REISSUE_DONE in the
   companion).  Nothing here had to change for either: #mbStatus carries its own
   padding, so hiding it takes that padding with it, and #mbMain below carries
   its own -- the ways never collide with the member strip.  What DID go is the
   #mbKnowOpened rule that used to sit here: the opened-date span it styled was
   retired with the sysop-side paragraph that carried it. */
#membox #mbStatus{padding:12px 16px 0}
#membox #mbStatusBox{border:2px groove #fff;padding:7px 14px 6px;position:relative}
/* TASK-1046[Q]: THE TWO KNOW LINES BECAME ONE ROW.  The provenance sentence and
   the memory sentence are each short enough now that stacking them cost a whole
   line of band height to say two half-lines; they render INLINE inside one
   .knowline block instead.  The row never wraps: it is nowrap + ellipsis, so a
   long screen name or a future variant degrades to a clipped tail rather than
   silently growing the band by a line (the designer's one-row rule, the same
   one .mwayn already keeps for the way headings). */
#membox .knowline{display:block;margin-bottom:5px;line-height:1.5;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
#membox .know{display:inline}
/* THE DECISION ROW: a sunken cell, the same status-bar idiom the footer uses,
   so the offer reads as an instrument rather than another paragraph. */
#membox .mbdec{margin-top:8px;border:2px inset #fff;padding:6px 10px;display:flex;align-items:center;gap:9px;flex-wrap:wrap}
#membox .mbdec.wide{align-items:flex-start}
#membox .mbdec .aolbtn{padding:4px 11px;font-size:12px;white-space:nowrap}
#membox .mbdec .msmall{flex:1 1 260px}
/* TASK-1046[Q]: ...but NOT the empty status span.  #mbReissueMsg is a .msmall
   with role=status and it is empty in every state except the two seconds a
   stamp is in flight, so the rule above was handing an invisible element a
   260px flex basis and squeezing the reissue LEAD -- the one sentence the
   member has to read -- onto two lines.  An empty status shrinks to nothing;
   the moment it has text it takes the shared basis back. */
#membox .mbdec [role="status"]:empty{flex:0 1 auto;min-height:0}
/* ---- TASK-1042[Q] BAND 4: the card and the ways group box -----------------
   TASK-1039[Q] made the member face a MENU of ways; TASK-1040[Q] put the
   square in its own column beside it.  Both still hold.  What changed is that
   the two columns became period objects: a physical membership CARD and an
   etched Win95 GROUP BOX.
   #mbMain wraps at a window too narrow to hold both (210 + 16 + 380 = 606px of
   content floor), which stacks the card ABOVE the box -- the same reading
   order.  Nothing here changes on a state change: the columns are laid out
   once and only their CONTENTS are shown or hidden. */
#membox #mbMain{display:flex;align-items:stretch;gap:16px;padding:8px 16px 0;flex-wrap:wrap}
/* TASK-1339[Q]: the two columns of the WHOLE member face, not of the
   artifacts alone.  #mbArts is the left one and is gated (hidden outright
   for a registered member); #mbSide is the right one and never is, because
   CLOSE THIS WINDOW lives in it.  #mbSide carries the 420/380 sizing the
   ways box used to carry, so when #mbArts is hidden it is the only flex
   child and takes the full width -- which is the single-column face this
   window has always shown in that state. */
#membox #mbArts{flex:0 0 auto;display:flex}
#membox #mbSide{flex:1 1 420px;min-width:380px;display:flex;flex-direction:column;align-items:stretch}
/* THE CARD.  A fixed 188px content column in EVERY state -- armed (the square)
   and cold (the honest no-code explanation in its place) are exactly the same
   width, so swapping between them cannot move the group box beside it.
   #666 on the #f4efe2 cream is 5.0:1; the teal header is 4.7:1. */
/* TASK-1330[Q]: THE CARD LAYS OUT SIDEWAYS, WHICH IS WHERE THE LAST OF THE
   HEIGHT CAME FROM.  The square used to sit ABOVE the number and the name,
   so the card column ran 315px against the ways box's 250 -- the card was
   the taller of the two and therefore set the whole row's height.  Putting
   the square beside its own text instead makes the column ~190 and hands the
   row back to the ways box, which is ~65px shorter.  That is the difference
   between this face fitting a normal window and needing a scrollbar.
   It is a GRID and not a DOM change on purpose: chead, mbQrBox, mbCardNum
   and mbCardName are already direct children, so the whole thing is placement
   and the copy layer's bindings never move.
   STILL A FIXED COLUMN (E8.2b / F9.7): the width is explicit and flex:0 0
   auto, so the group box beside it cannot shift when the square comes or
   goes -- that no-jitter guarantee is the reason those pins exist, and it is
   the property they now read rather than the number 188. */
#membox #mbCard{flex:0 0 auto;width:310px;background:#f4efe2;border:1px solid #7a7a6a;box-shadow:3px 3px 0 rgba(0,0,0,.25);padding:8px 10px 6px;text-align:left;
  display:flex;flex-direction:row;gap:8px}
/* TASK-1346[Q]: THE LABEL IS A SPINE. Rotated a quarter turn anticlockwise so
   it reads bottom to top down the left border, which is writing-mode
   vertical-rl turned 180deg -- sideways-lr would say it in one declaration
   and is not safe to rely on yet. It keeps its own line height rather than
   the card's, so the rule beside it does not drift with the text. */
#membox #mbCard .chead{flex:0 0 auto;writing-mode:vertical-rl;transform:rotate(180deg);text-align:center;border-right:1px solid #c9c2ad;padding:2px 3px 2px 0;margin:0}
#membox #mbCardBody{flex:1 1 auto;min-width:0;display:flex;flex-direction:column}
/* TASK-1348[Q]: the empty square. Same slot and same floor as the real one,
   so the card keeps its shape whether or not there is a code to draw from,
   and a dashed rule rather than the inset frame because it is a place for a
   thing rather than the thing. #666 on the #f4efe2 cream is 5.7:1. */
#membox #mbQrGap{flex:1 1 0;min-height:168px;display:flex;align-items:center;justify-content:center;border:2px dashed #b3ab93;background:#faf7ee}
#membox .qgapl{display:block;max-width:170px;text-align:center;font:12px/1.5 Tahoma,Verdana,sans-serif;color:#666;padding:8px}
/* TASK-1344[Q]: THE SQUARE TAKES WHATEVER HEIGHT IS LEFT. The user asked
   for the number under the square and for the square to grow into the
   space below it, so the card runs to the bottom of the window rather
   than stopping short. The box flexes and the image fits inside it;
   object-fit keeps a QR square square, so it takes the smaller of the
   width and the height available and centres in the other. min-height:0
   is what lets a flex child shrink below its content in the first place. */
/* THE FLOOR IS 168, NOT 152, AND THE 16 IS THE POINT. box-sizing is
   border-box below so height:100% cannot overflow the box, which means the
   6px padding and 2px border on each side come OUT of the square rather
   than sitting outside it. A 152px box paints 136px of code, 3.3 pixels per
   module on the 41-module grid, under the scannability floor E8.35 holds.
   168 leaves 152 of actual code, which is where it was. */
#membox #mbQrBox{flex:1 1 0;min-height:168px;display:flex;align-items:center;justify-content:center}
#membox #mbCardNum{flex:0 0 auto;white-space:nowrap;text-align:center}
/* TASK-1333[Q]: 340 -> 310.  Widening this card to lay the square sideways
   squeezed #mbWaysBox from 647 to 510, and way 4 (the bookmark link, the one
   row carrying an ellipsis as a SAFETY NET) began actually ellipsing, mid
   word, in normal use.  Swept the card width in the browser: way 4 clears at
   320 and below, and the CARD itself starts overflowing at 290, so 310 sits
   with measured margin on both sides rather than being a taste call. */
/* the number is a fixed-length monospace string and must never wrap: broken
   across three lines it is both ugly and harder to read back to somebody.
   The column width below is set so it does not have to. */
/* The name rides the header now: "MEMBERSHIP CARD - ggggg". The separator
   is drawn rather than written, so a nameless thread -- where this element
   is hidden -- shows no dangling dash. */
/* The name is the title of the card, centred over the square. It was a tail on
   the header line and carried a drawn separator; both are gone with the
   header, so there is nothing left to dangle on a nameless thread. */
#membox #mbCardName{flex:0 0 auto;text-align:center;margin:0 0 4px}

#membox #mbCard .chead{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#00807f;margin-bottom:4px}
#membox #mbCard .cnum{margin-top:6px;font:700 13px "Courier New",monospace;letter-spacing:2px;color:#1c1c1c;text-align:center}
/* TASK-1046[Q]: a real membership card carries the NAME under the number, and
   the ID card this column stands for has printed one all along -- only the
   on-screen card did not.  #12403f on the #f4efe2 cream is 7.9:1.  Hidden on a
   nameless thread; the retired #mbQrHint ("point your phone at this square")
   used to sit here and was deleted -- way 1 in the box beside it already says
   what the square is for, in a sentence the cold face keeps. */
#membox #mbCard .cname{font:700 12px Verdana,sans-serif;letter-spacing:1px;color:#12403f}
#membox #mbCard .chint{display:block;font:12px/1.45 Tahoma,Verdana,sans-serif;color:#666;margin-top:4px;text-align:left}
/* THE GROUP BOX.  The legend overlaps the etched border the way a period
   group box does; it is a positioned span on a chrome-coloured patch, so it
   never participates in the box's own flow.  #12403f on #c0c0c0 is 6.3:1. */
#membox #mbWaysBox{border:2px groove #fff;padding:7px 14px 6px;position:relative;margin-top:6px}
#membox .mblegend{position:absolute;top:-9px;left:10px;background:#c0c0c0;padding:0 7px;font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#12403f;white-space:nowrap}
/* TASK-1384[Q]: THE INSET ITS SIBLINGS ALREADY HAVE. #mbHave carries no
   padding of its own -- each of its direct children pays for its own gutter,
   and #mbMember, #mbStatus and #mbMain all read 0 16px. The door-hold block
   was appended beside them with no rule at all, so its heading and its three
   lines sat flush against the window border while everything above and below
   was inset. 16px is not a number chosen here; it is the one the three
   siblings already use, so the block lines up with them rather than merely
   stopping short of the edge.

   The vertical space is its own: it arrives under a status line and hands off
   to a button, and both were touching it. */
#membox #mbDoorHold{padding:0 16px;margin:10px 0 14px}
#membox #mbDoorHold .rktitle{margin:0 0 4px}
#membox #mbDoorHold .msmall{display:block;max-width:640px;margin:0 0 3px}
#membox #mbDoorHold #mbDoorHoldGo{margin-top:9px}

#membox #mbWays{margin:0;padding:0;list-style:none}
#membox .mway{margin:0;padding:5px 0;border-top:1px dotted #9a9a9a;display:flex;align-items:flex-start;gap:12px}
#membox .mway:first-child{border-top:none;padding-top:2px}
#membox .mway:last-child{padding-bottom:2px}
/* THE ICON WELLS: raised toolbar squares holding a 24x24 icon at 2px stroke,
   square caps and miter joins (repo icon conventions), in the desk's teal. */
#membox .iwell{flex:0 0 auto;width:42px;height:42px;background:#d7d7d7;border:2px outset #fff;display:grid;place-items:center}
#membox .micon{width:28px;height:28px;color:#00807f}
#membox .mwbody{flex:1 1 0;min-width:0;line-height:1.5}
/* HEADINGS ARE EXACTLY ONE LINE (the designer's hard rule); only the
   descriptions wrap. */
#membox .mwayn{font:700 13px Verdana,sans-serif;letter-spacing:1px;color:#12403f;white-space:nowrap}
#membox .mwayd{color:#333;font:13px Tahoma,Verdana,sans-serif}
/* RECOMMENDED is a badge, not a shout: colour + a hairline, no animation, and
   it reserves its own space so nothing moves when a method is not armed.
   #5a1010 on #ffe9c9 is 8.9:1. */
#membox .mrec{font:700 12px Verdana,sans-serif;letter-spacing:1px;color:#5a1010;background:#ffe9c9;border:1px solid #7a6a2a;padding:1px 6px;white-space:nowrap}
/* TASK-1043[Q]: THE DEFACTO DOWNLOAD wears the same badge shape in the desk's
   own teal, so way 2 reads as "the one to take" beside way 1's RECOMMENDED
   without either shouting the other down.  Colour only -- every box-model
   property comes from .mrec, so the two badges are the same object.
   #12403f on #d5f2f2 is 8.0:1. */
#membox .mrec.mdef{color:#12403f;background:#d5f2f2;border-color:#00807f}
#membox .ccodes{display:flex;align-items:center;gap:8px;flex-wrap:wrap;margin-top:4px}
/* THE BOOKMARK is the one way that is a draggable artifact, so it takes the
   full width of the box under the list.  Its heading may ellipsize rather than
   wrap -- one line, always. */
#membox #mbWayLink{display:flex;align-items:center;gap:12px;border-top:1px dotted #9a9a9a;padding-top:9px;min-width:0}
#membox #mbWayLink .mwayn{min-width:0;overflow:hidden;text-overflow:ellipsis}

/* TASK-1334[Q]: WAYS TO SAVE IS ONE DROPDOWN, NOT FOUR.
   TASK-1331[Q] read "make this a dropdown list" as a disclosure per row, so
   every way grew its own caret.  The user meant one control holding all four:
   open it, see the options, pick one, read that one.  So exactly ONE way is on
   screen at a time and it is always fully open -- there is no second thing to
   expand once you have chosen.
   STILL BY CLASS, NEVER BY INDEX.  The copy layer binds into these rows by
   CHILD INDEX (ways.qr.recommended is mbWayQr::c1.c1), and the rows do not
   agree on shape -- way 3 has no tag, way 4 is a div outside the <ul> with no
   body at all.  The picker is BUILT BESIDE them and selects by toggling one
   class, so every row keeps its children and its order. */
/* TASK-1337[Q]: every way is shown at once, so there is no selected state.
   The rows live in the panel and are simply visible; .mwsel is gone with the
   selection it described. */
#membox .mwmenu .mway,#membox .mwmenu #mbWayLink{display:flex}
/* the trigger: what is chosen, and that there is more behind it */
/* TASK-1340[Q]: the trigger and OTHER OPTIONS share one row, and the trigger
   takes what is left after the button.  .mwpick keeps position:relative only so
   the menu has something to be measured against; the menu itself is fixed now
   and is not positioned BY it. */
#membox .mwpickrow{display:flex;align-items:stretch;gap:6px;margin:0 0 8px}
#membox .mwpickrow .mwpick{flex:1 1 auto;min-width:0;margin:0}
#membox .mwpickrow #mbCounterBtn{flex:0 0 auto;white-space:nowrap}
/* Way 1 stands over the row, in the same type as the ways inside the menu. */
#membox #mbWayPerm{list-style:none;margin:0 0 8px;padding:0}
#membox #mbWayPerm .mway{display:flex}
#membox .mwpick{position:relative;margin:0 0 8px}
#membox .mwpickbtn{width:100%;display:flex;align-items:center;gap:8px;padding:5px 8px;
  background:#d7d7d7;border:2px outset #fff;cursor:pointer;text-align:left;
  font:700 13px Verdana,sans-serif;letter-spacing:1px;color:#12403f}
#membox .mwpickbtn:active{border-style:inset}
/* focus is an OUTLINE so it sits outside the box model and shifts nothing */
#membox .mwpickbtn:focus-visible{outline:2px solid #00807f;outline-offset:1px}
#membox .mwpickcar{margin-left:auto;font:700 12px Verdana,sans-serif}
#membox .mwpick.mwopen .mwpickcar::before{content:"\25be"}
#membox .mwpickcar::before{content:"\25b8"}
/* the menu.  ABSOLUTE so opening it cannot push the card column taller and
   resize the window under the pointer -- the whole reason this face was
   shortened in the first place. */
/* TASK-1335[Q]: the menu now holds the whole section -- the options AND the
   chosen way's card, code fields and all -- so it needs the room a card
   takes. Still ABSOLUTE, and that matters more than before: opening a
   panel this tall must not push the card column and resize the window
   under the pointer. It scrolls inside a fixed cap instead. */
#membox .mwmenu{display:none;position:fixed;z-index:80;
  background:#fff;border:2px outset #fff;box-shadow:3px 3px 0 rgba(0,0,0,.35);
  max-height:330px;overflow-y:auto;padding-bottom:4px}
/* inside the panel the rows get their own inset -- they used to sit in a
   padded box and are now flush against the menu's edge */
#membox .mwmenu #mbWays,#membox .mwmenu #mbWayLink{padding:0 8px}
#membox .mwpick.mwopen .mwmenu{display:block}
  background:transparent;border:0;cursor:pointer;text-align:left;
  font:700 13px Verdana,sans-serif;letter-spacing:1px;color:#12403f}
/* ---- TASK-1042[Q] BAND 5: the status-bar footer (BAND 4 before 1043[Q]) ---
   One row of sunken cells.  The three buttons share it at 880px and the row's
   contents never change size enough to wrap: the two leads are one short line
   each (their long sentence is a tooltip), the rotation confirm is its own
   full-width cell below, and the disclosure body is a third.
   TASK-1040[Q]'s PRIMARY-vs-secondary distinction is unchanged: a STATIC ring
   on the button and nothing else -- box-shadow sits outside the box model, so
   the button never changes size, border width or position between the two
   states.  No animation: the pulsing mbcta ring belongs to SIGN ON, and two
   pulsing rings is none. */
#membox #mbFoot{margin:9px 0 0;display:flex;align-items:stretch;gap:4px;flex-wrap:wrap}
#membox #mbFoot .cell{border:2px inset #fff;padding:5px 10px;display:flex;align-items:center;gap:8px;flex-wrap:wrap;min-height:26px}
#membox #mbFoot .cell.grow{flex:1 1 auto}
#membox #mbFoot .cell.wide{flex-basis:100%;align-items:flex-start}
#membox #mbFoot .aolbtn{padding:3px 10px;font-size:12px;white-space:nowrap}
#membox .mbhelp{border-bottom:1px dotted #666;cursor:help;white-space:nowrap}
#membox #mbReissueAsking{color:#5a1010;font-weight:700;white-space:nowrap}
#membox #mbReissueWarn{color:#5a1010;font-weight:700}
#membox .aolbtn.mbring{box-shadow:0 0 0 3px rgba(255,230,0,.95)}
/* THE COUNTER PANEL: a grooved service panel, one grid row per errand, the
   button in a column wide enough for the longest label so the two descriptions
   line up.  #555 on #d7d7d7 is 6.9:1; #5a1010 is 8.4:1. */
#membox #mbCounterPanel,#mbOptWin #mbCounterPanel{margin-top:6px;background:#d7d7d7;border:2px groove #fff;padding:9px 12px 10px}
#membox #mbCounterPanel .cptitle,#mbOptWin #mbCounterPanel .cptitle{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#555;margin-bottom:7px}
/* --- TASK-1070[Q]: AND NOW IT IS A TABLE ------------------------------------
   The user: "make this flow more like a table, uniform widths per column."
   WHAT WAS WRONG.  Every .opt is its OWN grid, so minmax(280px,max-content)
   sized the button column from THAT row's own label.  Measured on the rig
   before this change, with the rotation errand hidden: the three columns came
   out 280 / 280 / 370.375px, the buttons 270.2 / 159.2 / 370.4px wide, and the
   descriptions started at x=306 / 306 / 396.4 relative to the panel.  Three
   button widths and two different left edges for the prose is what read as
   three unrelated rows.  TASK-1046[Q]'s justify-self:end was the previous
   attempt at this and could not finish the job: it aligns a button inside its
   own row's column, and the columns themselves disagreed.
   THE FIX IS A FIXED TRACK, and it is fixed on purpose rather than shared-
   max-content.  A single grid over all four rows would size the column from
   the widest button PRESENT -- and #mbReissueAgainRow comes and goes with the
   status band, so the column (and every description's left edge) would move
   the moment it appeared.  A length cannot: 200px is 200px with the rotation
   errand shown and with it hidden, which is the repo's own fixed-panel rule
   applied one level down.  Measured budget: the widest of the four labels is
   ISSUE A NEW CODE at 172.1px including padding and border, so 200px leaves
   27.9px of headroom.  A future label longer than that SPILLS over its
   description rather than silently re-ragging the table, which is the failure
   mode we want -- the old behaviour hid itself for months.
   HEADROOM, measured, because the disclosure above this panel is a
   max-height:360px transition and a panel taller than that is CLIPPED rather
   than scrolled.  Tallest state is four rows with the removal confirm armed:
   345px, from 357px under the old rule.  Three pixels of margin was the real
   position before this change; there are fifteen now.  Anything added to this
   panel has to be measured in THAT state, not in the resting one. */
#membox .opt,#mbOptWin .opt{display:grid;grid-template-columns:200px 1fr;gap:12px;align-items:center;padding:6px 0;border-top:1px dotted #9a9a9a}
#membox .opt:first-of-type,#mbOptWin .opt:first-of-type{border-top:none;padding-top:0}
#membox .opt .msmall,#mbOptWin .opt .msmall{line-height:1.45;text-align:left}
#membox .optd,#mbOptWin .optd{display:flex;align-items:center;gap:8px;flex-wrap:wrap}
#membox .optd .msmall,#mbOptWin .optd .msmall{flex-basis:100%}
/* the counter's own buttons are plain chrome secondaries -- the teal .aolbtn
   is the desk's PRIMARY voice and these errands are not it.  The selector
   carries #membox .opt so it outranks the file's own #membox .aolbtn. */
/* TASK-1046[Q] right-justified these in their grid column, so the buttons at
   least shared one edge against the descriptions instead of sitting at three
   ragged left edges.  TASK-1070[Q] retires that: with the track fixed above,
   the honest thing is for every button to BE the column, so the four boxes are
   one width (200px, measured) and one left edge and one right edge.  stretch is
   the grid default and touches no box property of its own -- it fills a track
   whose width the row does not get a vote in -- so a label changing length
   cannot move anything, and neither can the rotation row appearing.
   The two-step confirm's own buttons live inside .optd, a flex row, where
   justify-self means nothing; they are reset to auto so the cascade cannot
   pretend otherwise (and stretch, unlike a width, would not have reached them
   anyway). */
#membox .opt .aolbtn.plain,#membox .optd .aolbtn.plain,#mbOptWin .opt .aolbtn.plain,#mbOptWin .optd .aolbtn.plain{background:#c0c0c0;color:#1c1c1c;border:2px outset #fff;text-shadow:1px 1px 0 #fff;padding:4px 10px;font-size:12px;white-space:nowrap;justify-self:stretch}
#membox .optd .aolbtn.plain,#mbOptWin .optd .aolbtn.plain{justify-self:auto}
#membox .opt .aolbtn.plain.caution,#mbOptWin .opt .aolbtn.plain.caution{color:#5a1010}
#membox #mbCopyMsg{max-width:100%}
/* LIVE-VERIFY CATCH: #mbArtMsg is the artifact status line and it is the one
   thing inside #mbArts that is NOT part of the two-column band, so it had no
   inset of its own and printed flush against the window chrome.  Give it the
   band inset every other band has. */
#membox #mbArtMsg{display:block;margin:6px 0 0}
/* TASK-1039[Q]: the rename OFFER (fully registered, or a thread with no name
   at all).  It is a moment, not a permanent field, so it reads as one. */
#membox #mbRenameRow{margin:9px 0 0;border-top:1px solid #9a9a9a;padding-top:8px}
#membox #mbRenameRow .msmall{display:block;max-width:560px}
#membox #mbLeaveWhat,#mbOptWin #mbLeaveWhat{display:block}
/* TASK-1042[Q]: #mbLinked is the registered face's whole explanation and the
   card column is gone there, so it gets the band inset every other band has. */
#membox #mbLinked{display:block;margin:12px 0 0}
/* ---- TASK-1048[Q] PHASE B: THE CARD RACK ----------------------------------
   The face the picker's THE CARD RACK... entry (and the counter's matching
   errand) opens: every card this machine is holding, one row each, each with
   its own take-off and its own two-step confirm.

   A FIXED FRAME WITH INTERNAL SCROLL, not a panel that grows with its data
   (the repo's fixed-panel rule).  The list is sized for the SERVER'S OWN cap
   -- eight cards, eight pre-declared rows -- so a desk holding one card
   occupies exactly the space a desk holding eight does, and nothing around it
   moves as cards come and go.  height, never max-height; overflow-y:auto, so
   a scrollbar appears only once a row is really armed and taller.
   Contrast on the #c0c0c0 chrome, all checked: #1c1c1c 10.9:1, #333 5.3:1,
   #12403f 7.4:1, #5a1010 8.9:1.  Nothing under 12px. */
#membox #mbRack{padding-bottom:10px}
/* the face's own heading, in flow.  NOT .mblegend, which is a group-box legend
   (position:absolute) and escaped to the window corner when it was tried here
   -- caught in the browser, not in the harness.  Same shape as the counter
   panel's .cptitle, at the same checked contrast. */
#membox .rktitle{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#12403f;margin:0 0 4px}
#membox #mbRackList{height:272px;overflow-y:auto;background:#d7d7d7;border:2px groove #fff;padding:4px 6px}
/* Each row PRE-RESERVES its confirm line: the warning and its two buttons sit
   on their own grid row, which is empty (and therefore zero-height) until the
   member arms it.  Arming scrolls INSIDE the fixed list rather than resizing
   the window, which is the whole reason the list carries a height of its own. */
#membox .rkrow{display:grid;grid-template-columns:minmax(190px,1fr) max-content max-content;gap:6px 10px;align-items:center;padding:6px 2px;border-top:1px dotted #9a9a9a}
#membox .rkrow:first-child{border-top:none}
#membox .rkid{display:flex;flex-direction:column;gap:1px;min-width:0}
#membox .rkname{font:700 13px Verdana,sans-serif;letter-spacing:1px;color:#12403f;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#membox .rknum{font:700 12px "Courier New",monospace;letter-spacing:1px;color:#333}
#membox .rkmark{display:flex;align-items:center;gap:8px;white-space:nowrap}
/* the standing stamp at the rack's smaller scale.  Everything else is
   inherited from #membox .stamp, so the two surfaces cannot drift apart. */
#membox .rkstamp{font-size:12px;letter-spacing:2px;border-width:2px;padding:2px 7px}
#membox .rkactive{font:700 12px Verdana,sans-serif;letter-spacing:2px;color:#12403f;background:#ffe600;border:1px solid #7a6a2a;padding:1px 6px}
/* the row's own buttons, matching the counter's plain chrome exactly */
#membox .rkrow .aolbtn.plain{background:#c0c0c0;color:#1c1c1c;border:2px outset #fff;text-shadow:1px 1px 0 #fff;padding:4px 10px;font-size:12px;white-space:nowrap}
#membox .rkrow .aolbtn.plain.caution{color:#5a1010}
/* the confirm sentence spans the whole row and wraps; its two buttons follow
   in their own cells, so nothing above them moves when it appears. */
#membox .rkrow .rkwarn{grid-column:1/-1;display:block;color:#5a1010;line-height:1.45}
/* TASK-1055[Q]: ...and the confirm's THREE buttons sit at their own width in
   the three columns rather than stretching to fill them, which is what the
   grid does to a lone button by default.  justify-self touches no box
   dimension, so nothing moves between the armed and unarmed states.
   The way OUT of losing something catches the eye, exactly as it does in the
   dropdown's own popup -- and a ring costs no layout either. */
#membox .rkrow #mbRackYes0,#membox .rkrow #mbRackYes1,#membox .rkrow #mbRackYes2,
#membox .rkrow #mbRackYes3,#membox .rkrow #mbRackYes4,#membox .rkrow #mbRackYes5,
#membox .rkrow #mbRackYes6,#membox .rkrow #mbRackYes7{justify-self:start;color:#5a1010}
#membox .rkrow .rksave{justify-self:start;box-shadow:0 0 0 3px rgba(255,230,0,.95)}
#membox #mbRackMsg{color:#333}
/* THE STALE LINE.  One sentence, on whichever face is up, in the same inset
   every other band has. */
#membox #mbStaleRow{margin:8px 16px 0;padding:6px 8px;background:#d7d7d7;border-left:4px solid #7a6a2a}
#membox #mbStaleRow .msmall{display:block;color:#1c1c1c}

/* --- TASK-1049[Q]: THE SCREEN NAME PICKER, AS A CUSTOM DROPDOWN -------------
   WHY THIS EXISTS: a native <select> cannot carry a per-option button, and the
   user asked twice for an [x] on each saved card IN the dropdown rather than
   one click away in THE CARD RACK... face.  So the picker is a custom
   combobox now -- and the hard part is not the [x], it is that #aolname sits
   in a form beside two selects that are NOT changing (#aolloc, #aolnum).  If
   the closed control renders even slightly differently the form looks broken.

   THE MATCH IS BY CONSTRUCTION WHEREVER IT CAN BE.  The declarations below
   marked MIRROR are copied verbatim from #aolwin select in metaeden-v4.css
   (that base file is at its size budget and is never edited by this
   companion) -- keep the two in step if either ever moves.  Everything else
   that could drift is simply NOT SET here, so the browser draws it for both:
   in particular there is no outline rule, so the focus ring on the custom
   control is the identical UA ring its two native siblings get.
   Measured on the rig against #aolloc: 404 x 30 CSS px, box-sizing
   border-box, both.  Contrast on the white face, all checked: #000 21:1,
   the disabled seed grey #6b6b6b 5.2:1, the highlight #fff on #000080 15.3:1,
   #5a1010 on #fff 12.4:1, #1c1c1c on #ffe600 12.9:1.  Nothing under 12px. */
#aolwin .pknative{display:none}
#aolwin .pkwrap{position:relative}
#aolwin .pkface{box-sizing:border-box;width:100%;height:30px;display:flex;align-items:center;
  /* MIRROR of #aolwin select */
  font:15px Tahoma,Verdana,sans-serif;border:2px inset #fff;background:#fff;color:#000;padding:3px;
  cursor:default;user-select:none}
#aolwin .pkval{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* the chevron the browser draws inside its own selects, at the size and inset
   it draws it: a 10px box, 1.6px stroke, 6px in from the right edge. */
#aolwin .pkarrow{flex:none;width:10px;height:10px;margin-left:6px;margin-right:6px;
  background:no-repeat center/10px 10px url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 10'%3E%3Cpath d='M1 3.6L5 7.6L9 3.6' fill='none' stroke='%23000' stroke-width='1.6'/%3E%3C/svg%3E")}
/* THE POPUP.  It is an overlay, so nothing in the form ever moves for it.  The
   list carries a HEIGHT rather than a max-height, so taking a card off cannot
   resize the popup or shift a row under the pointer.  The list is the only
   scroller.
   TASK-1054[Q]: the 176px below is now the CAP and the pre-script default, not
   the answer.  mbPkSizeList writes an explicit height over it at the moment the
   menu OPENS -- rows * 24px, clamped here -- so a machine holding no cards draws
   five rows and no blank space beneath them, and the height is then frozen for
   as long as the menu is up.  Keep the two numbers below in step with
   MB_PK_ROW_PX / MB_PK_LIST_PX in metaeden-v4-membership.js; the bureau suite
   pins them against each other. */
#aolwin .pkpop{position:absolute;left:0;right:0;top:100%;z-index:20;background:#fff;
  border:1px solid #000;box-shadow:3px 3px 0 rgba(0,0,0,.35)}
#aolwin .pklist{list-style:none;margin:0;padding:0;height:176px;overflow-y:auto;background:#fff}
#aolwin .pkrow{display:flex;align-items:stretch;gap:6px;margin:0;padding:2px 0 2px 6px;
  font:15px Tahoma,Verdana,sans-serif;line-height:18px;color:#000;cursor:default;
  /* pre-reserved at the largest state so arming a row changes colour only */
  border:1px solid transparent}
#aolwin .pklab{flex:1;min-width:0;padding-right:6px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
#aolwin .pkrow.dis{color:#6b6b6b}
/* TASK-1054[Q]: A ROW SAYS WHAT KIND OF THING IT IS BEFORE IT IS READ.  A saved
   card is a real screen name, so it is BOLD; the three bracketed entries are
   verbs rather than names, so they are ITALIC; guest and the four disabled seeds
   are plain, which is what makes the other two read as marked at all.  Weight
   and slope only -- no size, no colour, no box change -- so nothing here moves a
   pixel of layout between states, and the contrast is the row's own (#000 on
   #fff, 21:1; #fff on #000080 when highlighted, 15.3:1).
   THIS IS THE WHOLE REASON THE CUSTOM DROPDOWN EARNS ITS KEEP: a native
   <option> cannot carry per-row styling, so before TASK-1049[Q] this was not
   available at any price. */
#aolwin .pkrow.card .pklab{font-weight:700}
#aolwin .pkrow.cmd .pklab{font-style:italic}
#aolwin .pkrow.on{background:#000080;color:#fff}
#aolwin .pkrow.armed{background:#ffe600;color:#1c1c1c;border-color:#7a6a2a}
/* the [x] itself: 14px so the glyph reads, and its hover ring is a border that
   was already there in transparent, so hovering it moves nothing. */
/* THE [x] FILLS ITS ROW'S FULL HEIGHT and runs to the right edge of the list.
   Live-verify catch: at 23x18 in a 24px row a click one pixel wide of it fell
   through to the row and SWITCHED PROFILES -- a mis-click on a destructive
   affordance must not be able to do something else entirely. */
#aolwin .pkx{flex:none;align-self:stretch;background:transparent;border:1px solid transparent;
  padding:0 7px;font:700 14px Tahoma,Verdana,sans-serif;line-height:18px;color:#5a1010;cursor:pointer}
#aolwin .pkrow.on .pkx{color:#fff}
#aolwin .pkrow.armed .pkx{color:#5a1010}
#aolwin .pkx:hover{border-color:currentColor}
/* TASK-1050[Q]: THE FOOTER IS GONE.  It reserved 112px under the list for a
   standing explanation of the [x] and, once a row was armed, for the warning
   and its two confirm buttons -- the pair of appendages the user called
   awkward.  Both are in #mbPkOff now, so this popup is a list and nothing
   else: it is exactly its own list tall, with no reserved band and no dead
   space, and .pkpop still carries no height of its own so it can never drift
   from the one scroller inside it. */
/* the keyboard route to the [x], for the reader that cannot see it */
#aolwin .pkhint{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);
  clip-path:inset(50%);white-space:nowrap}

/* --- TASK-1054[Q]: THE DIAL NUMBER PICKER ----------------------------------
   #aolnum is the same widget as #aolname, so it reuses .pkwrap / .pkface /
   .pkval / .pkarrow / .pkpop / .pklist / .pkrow / .pklab unchanged -- there is
   no second copy of that geometry and there must never be one.  These four
   rules are the whole difference: a number sits at its natural width, and its
   NOTE takes the rest of the row, greyed and italic.
   THE GREY IS #6b6b6b, and it is the one this stylesheet already measured for
   the disabled seed names: 5.2:1 on the white face, over the 4.5:1 floor.  A
   note is readable content, not decoration, so it is not allowed to be one of
   the ~3:1 greys CLAUDE.md names (#445 / #557 and their family); it inherits
   .pkrow's 15px, which clears the 12px floor with room to spare.
   ON A HIGHLIGHTED ROW the grey would sit on #000080 at about 2:1, which is
   exactly the trap, so it is repainted #d8dcff there -- 11.9:1 on that navy.
   .nmnum must come AFTER .pklab / .pkval: same specificity, source order is
   what makes flex:none win over their flex:1. */
#aolwin .pknote{flex:1;min-width:0;padding-left:8px;padding-right:6px;overflow:hidden;
  text-overflow:ellipsis;white-space:nowrap;font-style:italic;color:#6b6b6b}
#aolwin .nmnum{flex:none}
#aolwin .pkrow.on .pknote{color:#d8dcff}
#aolwin .pkrow.dis .pknote{color:#6b6b6b}

/* --- TASK-1050[Q]: THE TAKE-OFF POPUP --------------------------------------
   Deliberately A Word From The Sysop's rule set, value for value -- same 92vh
   cap with its own scroll, same body padding, type and chrome.  This is the
   bureau's second in-window dialog and the two must read as the same object; a
   member should not be able to tell which one is asking.
   The ONE value that differs is the width, and only because this window has
   THREE buttons where that one has two: measured on the rig, the row wants
   500px and 470 wrapped CANCEL onto a line of its own.  560 is that plus
   slack, so a different font metric cannot wrap it either.
   Contrast on the #c0c0c0 chrome, checked: #1c1c1c 10.4:1, #5a1010 8.6:1.
   Nothing under 12px, and the emphasis on SAVE PROFILE FIRST is a box-shadow
   ring, so no state change moves anything. */
#mbPkOff{position:fixed;inset:0;display:grid;z-index:9;place-items:center;pointer-events:none}
/* The 44px is the desk's line (34px) plus its margin (10px), held OUT HERE as
   transparent margin instead of grey chrome inside the window -- see .pkoffmsg
   at the foot of this block for why. */
#mbPkOff .win{width:560px;max-height:92vh;overflow-y:auto;margin-bottom:44px}
#mbPkOff .win.hasmsg{margin-bottom:0}
#mbPkOff .pkoffbody{padding:16px 18px 14px;background:#c0c0c0;color:#1c1c1c;font:14px/1.55 Tahoma,Verdana,sans-serif}
#mbPkOff .pkoffbody p{margin:0 0 10px}
#mbPkOff .pkoffwho{font:700 15px Tahoma,Verdana,sans-serif;color:#1c1c1c}
#mbPkOff .pkoffwarn{color:#5a1010}
#mbPkOff .pkoffbtns{display:flex;flex-wrap:wrap;gap:12px;margin:14px 0 2px}
#mbPkOff .aolbtn{background:#c0c0c0;color:#1c1c1c;border:2px outset #fff;text-shadow:1px 1px 0 #fff;
  padding:8px 16px;font:700 13px Verdana,sans-serif;letter-spacing:1px;cursor:pointer}
#mbPkOff .aolbtn:active{border-style:inset}
#mbPkOff .aolbtn.pkoffgo{color:#5a1010}
/* the way OUT of losing something is the one that catches the eye, exactly as
   QUICK REGISTER does in the window above -- and a ring costs no layout. */
#mbPkOff #mbPkOffSave{box-shadow:0 0 0 3px rgba(255,230,0,.95)}
/* The desk's own line.  It is written ONLY when mbCardOff refuses, so on every
   other open it was 34px of empty grey under the buttons -- 62px of dead band
   all told, measured on the rig, which is what the member actually sees nearly
   always.  The slot now collapses when it has nothing to say, and the room it
   needs is reserved OUTSIDE the window as transparent margin-bottom on .win
   instead.  The grid centres the MARGIN box, so window-height plus that margin
   is the same either way: the window's top does not move, and a refusal grows
   the window DOWNWARD into space already being held for it.  Same no-resize
   guarantee the fixed height bought, without the grey -- 62px of dead band
   becomes 28px, which is the body's own padding.
   THE SLOT CARRIES NO MARGIN, deliberately.  The gap above the line is
   padding INSIDE a border-box height, so the expanded slot contributes exactly
   its height and nothing else.  A margin here would collapse against the
   button row's own 2px and the reservation would be over by 12px, which is
   measured, not theorised: the first cut of this used margin:10px 0 0 with a
   44px reservation and the window's top still shifted 6px.  Keep the 44px on
   .win equal to THIS HEIGHT, and keep this margin at 0. */
#mbPkOff .pkoffmsg{height:0;margin:0;padding:0;overflow:hidden;box-sizing:border-box;
  font:12px Verdana,sans-serif;line-height:1.45;color:#1c1c1c}
#mbPkOff .win.hasmsg .pkoffmsg{height:44px;padding-top:10px;overflow-y:auto}

/* --- TASK-1054[Q]: THE SMALL CONFIRMATION AFTER A PHONE VOUCHES ------------
   Same rule set as the take-off popup above, value for value, because it is
   the same kind of object -- the desk saying one short thing and offering one
   way out.  It is NARROWER on purpose (420 against 560): that window carries
   three buttons and a warning, this one carries a sentence and OK, and a small
   confirmation that is as wide as a warning does not read as small.
   z-index 80 clears both #mbwin (75) and #aolwin.mbtop (78): it reports on the
   bureau going down, so it cannot be drawn underneath it.
   Contrast on the #c0c0c0 chrome: #1c1c1c is 10.4:1, the same pairing already
   measured for #mbPkOff.  Body type is 14px, over the 12px floor. */
#mbLinkOk{position:fixed;inset:0;display:grid;z-index:80;place-items:center;pointer-events:none}
/* THE CHROME, RESTATED -- AND LIVE-VERIFY IS WHAT FOUND OUT IT HAD TO BE.
   .win / .tbar and their title-bar parts are declared SCOPED TO #aolwin in the
   base stylesheet, so #mbPkOff inherits the lot for free by living inside that
   window.  This one is a SIBLING of the bureau instead -- it reports that
   window going down, so it cannot be a child of either -- which puts it outside
   that scope and gave it no chrome at all: on the rig the title bar came up
   unstyled with its text bleeding over the body, while every headless check
   stayed green.  These six declarations are the base file's own, value for
   value, so the bureau's two confirmations still read as the same object.
   #fff on the #000080 -> #0e73b5 title gradient is that file's own pairing,
   unchanged; the body's #1c1c1c on #c0c0c0 is 10.4:1.  (TASK-1112[Q] moved the
   light stop down from #1084d0, where white measured 4.013:1 at the right-hand
   end and was under the floor; it is 5.075 unwashed and 4.827 at the shipped
   scan intensity now.  Both files moved together, which is what N4.13 in
   server/metaeden_net_bureau_states.test.js now checks by reading the base
   file's own stops rather than a literal it keeps its own copy of.) */
#mbLinkOk .win{background:#c0c0c0;border:2px outset #fff;box-shadow:6px 6px 0 rgba(0,0,0,.4);
  font:15px Tahoma,Verdana,sans-serif;color:#000}
#mbLinkOk .tbar{display:flex;align-items:center;gap:8px;color:#fff;padding:5px 8px;
  background:linear-gradient(90deg,#000080,#0e73b5);font:700 16px Tahoma,Verdana,sans-serif}
#mbLinkOk .tbar .tri{width:0;height:0;border-left:7px solid transparent;
  border-right:7px solid transparent;border-bottom:12px solid #fff}
#mbLinkOk .tbar .wb{margin-left:auto;display:flex;gap:3px}
#mbLinkOk .tbar .wb b{width:26px;height:22px;background:#c0c0c0;border:2px outset #fff;color:#000;
  font:700 13px Verdana,sans-serif;display:grid;place-items:center;cursor:pointer}
#mbLinkOk .tbar .wb b.x{background:#cc2222;color:#fff}
/* TASK-1395[Q]: see the sibling rule in metaeden-v4.css -- the close box is a
   reachable control now and lands here visibly. */
#mbLinkOk .tbar .wb b.x:focus-visible{outline:2px solid #fff;outline-offset:1px}
/* ...and the size, AFTER the chrome so this width wins over the base one it
   copies (same specificity, source order decides). */
#mbLinkOk .win{width:420px;max-width:calc(100vw - 32px);max-height:92vh;overflow-y:auto}
#mbLinkOk .lokbody{padding:16px 18px 14px;background:#c0c0c0;color:#1c1c1c;
  font:14px/1.55 Tahoma,Verdana,sans-serif}
#mbLinkOk .lokmsg{margin:0 0 14px}
#mbLinkOk .lokbtns{display:flex;gap:12px}
#mbLinkOk .aolbtn{background:#c0c0c0;color:#1c1c1c;border:2px outset #fff;text-shadow:1px 1px 0 #fff;
  padding:8px 16px;font:700 13px Verdana,sans-serif;letter-spacing:1px;cursor:pointer}
#mbLinkOk .aolbtn:active{border-style:inset}

/* --- TASK-1055[Q]: THE IMPORT FACE, AS THREE NUMBERED WAYS ----------------
   Same shape the WAYS TO SAVE menu already uses on the member face -- a
   legend, then one heading per way -- so a member reads the two lists the
   same way round.  .mlead and .mway borrow #mbSaveLead's own values rather
   than inventing a third scale; 12px is the floor and #12403f on the face's
   #e9e9e9 is well past 4.5:1 (measured 8.9:1 for the same pairing on
   .rkname).  Nothing here changes size between states. */
#membox #mbWaysInLead .mlead,#membox #mbrQrHead .mway,#membox #mbrTypeHead .mway,
#membox #mbrFileHead .mway{display:block;font:700 12px Verdana,sans-serif;
  letter-spacing:2px;color:#12403f}
#membox #mbWaysInLead{margin-top:2px;border-bottom:1px solid #9a9a9a;padding-bottom:4px}
#membox #mbrQrHead,#membox #mbrTypeHead,#membox #mbrFileHead{margin-top:8px}
/* the file row: the control and its own explanation, at the readable size the
   rest of this face uses. */
#membox #mbrFileRow{display:flex;flex-wrap:wrap;gap:6px 10px;align-items:center}
#membox #mbrFile{font:12px Verdana,sans-serif;color:#1c1c1c;max-width:100%}
#membox #mbrFileHint{flex:1 1 260px;line-height:1.45}

/* TASK-1066[Q]: the two bureau entries this file injects into the base file's
   Dial Up menu (mbBuildDial).  A Win95 groove separating the modem's own two
   commands from the desk's, and the unavailable state of SAVE YOUR CARD.
   BOTH RULES CARRY !important AND AN ID, deliberately: metaeden-v4.css forces
   .browser-menu-panel button to #1c1c1c !important so the chrome stays
   chrome-coloured under any site theme, and an unavailable item has to be able
   to say so through that.  #454545 on the panel's #c0c0c0 is ~5:1, past the
   4.5:1 floor, and it is the ONLY thing that changes -- the item keeps its box,
   its padding and its size in both states, so nothing in the menu moves.  The
   hover rule is neutralised for the same reason: :hover still fires on a
   disabled button, and a highlight would read as a live row. */
.browser-menu-panel .mbdialsep{height:0;margin:3px 2px;
  border-top:1px solid #808080;border-bottom:1px solid #ffffff}
.browser-menu-panel #mbDialSave[disabled]{color:#454545 !important;cursor:default}
.browser-menu-panel #mbDialSave[disabled]:hover,
.browser-menu-panel #mbDialSave[disabled]:focus{background:#c0c0c0 !important;
  color:#454545 !important}
/* TASK-1306[Q]: NO MODAL BACKING, by design decision -- reported as "all the
   buttons seem like they were cut out of a modal screen and everything else is
   still screened by a modal background; just get rid of the modal backing both
   functional and visually in general."

   These dialogs are 1996 WINDOWS, not modern modals. A window does not dim the
   desktop behind it and does not stop you clicking what it is sitting on top
   of, so the dark rgba backdrop is gone from every one of them and the
   full-window layer they each stretch across no longer swallows pointer events.
   The dialog itself still takes clicks -- that is the `> *` rule -- so only the
   empty space around it becomes transparent to the mouse.

   Checked before landing: none of these seven relies on a backdrop click to
   close (METAMP's ask closes on its own X button, the rest on their own
   controls), so nothing loses a way out. What they DO lose is enforced
   modality: the page behind stays live while one is open. That is the point of
   the request rather than a side effect of it. */
#mbWarn>*,#mbPkOff>*,#mbLinkOk>*{pointer-events:auto}

/* TASK-1340[Q]: THE COUNTER'S OWN WINDOW.  Same .w95 chrome as every other 1996
   window on this site, so it needs only a position, a width and a z-index of its
   own.  79 sits above #mbwin's 77 -- it is summoned FROM that window and has to
   stand over it -- and below the ways menu's 80, which is fixed and would
   otherwise be painted under a window it has nothing to do with.
   NO BACKDROP: TASK-1306[Q] took the modal backing off every window here, and
   this one does not get to bring it back.  The page behind stays live, which is
   what the user asked for then and has not changed. */
#mbOptWin{position:fixed;left:calc(var(--page-inset-left,0px) + 24px);top:calc(var(--page-inset-top,0px) + 76px);width:520px;max-width:calc(100vw - 24px);display:none;z-index:79}
#mbOptWin.open{display:block}
#mbOptWin #mbCounterBody{max-height:calc(100vh - 160px);overflow-y:auto}
/* TASK-1357[Q]: the way out, under the sysop memo and hard right. flex-end
   rather than text-align, because the row holds a button and not text, and
   margin-top matches the gap the memo already keeps from the band above it so
   the column reads as evenly spaced rather than as a button bolted on. */
#membox #mbCloseRow{display:flex;justify-content:flex-end;margin-top:10px}
#membox #mbCloseRow .aolbtn.plain{background:#c0c0c0;color:#1c1c1c;
  border:2px outset #fff;text-shadow:1px 1px 0 #fff;padding:4px 12px;
  font-size:12px;white-space:nowrap}
#membox #mbCloseRow .aolbtn.plain:active{border-style:inset}
/* TASK-1358[Q]: the way out, once a copy has actually been saved. GREEN and
   SLOW where the SIGN ON cta is yellow and quick, because this one is a
   confirmation rather than a summons -- it should be noticed on the way past,
   not obeyed. Like that cta it animates box-shadow ONLY, so the button never
   changes size or moves its neighbours as it breathes, and reduced-motion
   keeps the ring and drops the movement. 4.6s is deliberately longer than a
   glance: a fast pulse on a confirmation reads as another alarm. */
@keyframes mbKeptEbb{0%,100%{box-shadow:0 0 0 1px rgba(0,128,127,.30)}
  50%{box-shadow:0 0 0 5px rgba(0,128,127,.55)}}
#membox #mbCloseRow .aolbtn.plain.mbkept{background:#e8f6f6;color:#12403f;
  border-color:#7fd4d4;box-shadow:0 0 0 3px rgba(0,128,127,.45);
  animation:mbKeptEbb 4.6s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  #membox #mbCloseRow .aolbtn.plain.mbkept{animation:none;
    box-shadow:0 0 0 3px rgba(0,128,127,.55)}}
