/* =====================================================================================
   Milo · Pro Glass v3 — components.css (agent-v3)                  canvas _nccnJIfnL
   The component sheets' CSS consolidated (2.01–2.16), plus the app shell that the pilot frames 01 (DRtLKM84H6) and
   02 (u00U411l8W) draw. Loads after kit/v3-base.css
   (verbatim, never edited). Every value is a kit token or a value drawn on a sheet — no new glass recipes (D35 on hold).
   Order: 0 a11y text size · 1 app shell · 2 controls (2.17 filter bar) · 3 status · 4 content (row2 · show all · filtered empty) · 5 overlays (toast kinds) · 6 phone · 7 adaptivity.
   ===================================================================================== */

/* ---------- 0 · A11y: text follows the user's text size (rem). At the default 16 px root every value below is
   pixel-identical to the kit's px value; only a larger/smaller user setting changes it. ---------- */
:root{
--t-title:600 1.5rem/1.2 var(--font-ui);--t-section:600 .9375rem/1.3 var(--font-ui);--t-strong:600 .8125rem/1.35 var(--font-ui);
--t-body:400 .8125rem/1.45 var(--font-ui);--t-small:400 .75rem/1.4 var(--font-ui);--t-label:600 .6875rem/1.3 var(--font-ui);
--t-value:500 1.0625rem/1.25 var(--font-ui);--t-metric:500 1.375rem/1.15 var(--font-ui);--t-numeral:300 3.5rem/1 var(--font-ui);
--t-reading:400 .9375rem/1.6 var(--font-ui);
--seg-thumb-sh:0 0 0 .5px var(--hair-2),0 1px 2px var(--hair-2)} /* the segmented thumb / selected tab: one recipe (was written out three times) */
.is-phone{--t-title:600 1.625rem/1.15 var(--font-ui);--t-section:600 1.0625rem/1.25 var(--font-ui);--t-strong:600 .9375rem/1.3 var(--font-ui);
--t-body:400 .9375rem/1.4 var(--font-ui);--t-small:400 .8125rem/1.35 var(--font-ui);--t-label:600 .75rem/1.3 var(--font-ui);
--t-value:500 1.125rem/1.25 var(--font-ui);--t-metric:500 1.5rem/1.15 var(--font-ui);--t-numeral:300 3.25rem/1 var(--font-ui)}
.mono{font-size:.6875rem}.credits{font-size:.75rem}.btn{font-size:.8125rem}
.seg>button{font-size:.75rem}.flabel{font-size:.75rem}.tk{font-size:.75rem}.tag{font-size:.6875rem}.badge{font-size:.6875rem}
.av{font-size:.6875rem}.av.l{font-size:.8125rem}.sh .ct{font-size:.8125rem}.ax,.axs,.axv{font-size:.6875rem}
.insp>header h2,.sheet>header h2,.dialog h2{font-size:1.0625rem}.menu [role^=menuitem],.menu [role=option]{font-size:.8125rem}
.menu kbd,.menu .ct{font-size:.75rem}.toast{font-size:.8125rem}.tab{font-size:.6875rem}

[hidden]{display:none!important}
.sr-only{position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
button{font:inherit;color:inherit}
button:not(.btn):not(.tk):not(.tab){cursor:default}

/* ---------- 1 · App shell (01 · 02 · 2.14). The kit draws the shell absolute for static frames; the app pins it. ---------- */
body.app{position:relative;min-height:100vh;min-height:100dvh}
body.app>.scene{position:fixed}
body.app .band{position:fixed}
.band h1{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.band .bg{display:flex;align-items:center;gap:6px}
.band .bg+.bg{margin-left:6px}
/* the Calendar band's tools (D66): search · ‹ Today › on one centre line — as inline boxes Today sat ~4 px low */
.cal-tools,.cal-nav{display:flex;align-items:center}
.band .back{margin-right:4px}
.band .back+h1,.top .back+h1{margin-left:0}
/* record header (3.05): the title and its meta share a baseline in the band */
.band .bt{display:flex;align-items:baseline;gap:12px;margin-right:auto;min-width:0}
.band .bt h1{margin-right:0}
.band .bt>:not(h1){flex:none;white-space:nowrap}
.host .bell .badge,.top .bell .badge{pointer-events:none}
#page{position:relative;z-index:1;min-height:100vh;min-height:100dvh;padding:calc(var(--h-band) + var(--gutter)) 12px 12px calc(var(--w-side) + var(--gutter))}
#page:focus{outline:none}
#page .pane{position:relative}
/* no-shell routes (sign-in, registration) — the class sits on <html>: Doop's canvas renderer keeps <html> attributes, never <body>'s */
html.no-shell .band,html.no-shell .top,html.no-shell .dock{display:none!important}
html.no-shell #page{padding:0}
/* Before admission, there is no sidebar/header to reserve space for. */
html.no-shell:not([data-startup-ready="true"]) body.app #page>.live-state{min-height:100dvh!important}   /* !important: startup has no band, and under html.no-shell #page is not the flex column the full-height rule below fills */
html.no-shell:not([data-startup-ready="true"]) body.app #page>.live-state>.state-view{min-height:inherit}
.credits{color:var(--ink-1);border-radius:var(--r-ctl);transition:background-color var(--dur-hover) ease}
@media (hover:hover){.band .credits:hover{background:color-mix(in srgb,var(--ink-1) 6%,transparent)}}
/* layer for transient surfaces (fixed coordinates) */
.layer{position:relative;z-index:30}

/* ---------- 2 · Controls ---------- */
/* 2.01 Buttons — the static twins on the sheet become real states */
.btn{-webkit-user-select:none;user-select:none;text-decoration:none}
.btn.pl:disabled,.btn.bare:disabled{box-shadow:none}
.btn.crit.is-confirm:hover:not(:disabled,[aria-disabled=true],[aria-busy=true]){filter:brightness(.92)}
.btn.crit.is-confirm:disabled{background:color-mix(in srgb,var(--crt-ink) 34%,transparent);box-shadow:none;color:var(--on-accent)}
.btn[aria-disabled=true]:not(.pri):not(.pl):not(.bare){color:var(--ink-disabled);box-shadow:0 0 0 .5px color-mix(in srgb,var(--ink-1) 10%,transparent)}
.btn.pl[aria-disabled=true],.btn.bare[aria-disabled=true]{color:var(--ink-disabled);box-shadow:none}
.btn[aria-disabled=true]{cursor:default}.btn[aria-disabled=true]:active{transform:none}
.btn:disabled{cursor:default}.btn:disabled:active{transform:none}
.btn .i.s12{color:var(--ink-2)}
.btn[aria-busy=true]{cursor:progress}
.btn[aria-expanded=true]{background:var(--accent-wash);color:var(--accent-ink)}
.btn[aria-expanded=true] .i{color:var(--accent-ink)}
.btn.pu{justify-content:space-between;gap:10px}.btn.pu .i{color:var(--ink-2)}
.btn.pu .val.ph{color:var(--ink-2)}.gate-form .btn.pu .val{flex:1;min-width:0;overflow:hidden;text-align:left;text-overflow:ellipsis}
.hold{display:inline-grid;justify-items:center}.hold>*{grid-area:1/1;display:inline-flex;align-items:center;gap:6px}.hold>.gh{visibility:hidden}
.i.spin{width:14px;height:14px;stroke-width:2;animation:milo-spin .8s linear infinite}
@keyframes milo-spin{to{transform:rotate(1turn)}}
.btn.swell{transform:scale(1.04);background:rgb(255 255 255/.86);box-shadow:var(--sh-ctl)}
.ferr{display:flex;align-items:flex-start;gap:6px;margin-top:6px;font:500 .75rem/1.4 var(--font-ui);color:var(--crt-ink)}
.ferr .i{width:14px;height:14px;margin-top:1px;stroke-width:2.14}

/* 2.02 Fields · select · search */
.fld input,.fld select,.fld textarea{flex:1;min-width:0;height:100%;border:0;padding:0;background:none;font:inherit;color:inherit;outline:none}
.fld input::placeholder,.fld textarea::placeholder{color:var(--ink-2);opacity:1}
.fld .val{flex:1;min-width:0;white-space:nowrap;overflow:hidden}
/* DATE — a native date input inside .fld.l (16 px on phone via the phone rule); the picker glyph is a quiet control */
.fld input[type=date]::-webkit-calendar-picker-indicator{opacity:.6;cursor:default}
.fld input[type=date]::-webkit-datetime-edit{padding:0}
.fld input[type=date]{font-variant-numeric:tabular-nums}
/* autofill keeps the field's own glass and ink (no !important: the transition holds the UA tint back) */
.fld input:-webkit-autofill,.fld input:autofill{-webkit-text-fill-color:var(--ink-1);caret-color:var(--ink-1);transition:background-color 99999s ease-out}
.fld .chev{margin-left:auto}
.fld.l,.fld.f32{height:var(--h-ctl);padding:0 10px}
@media (hover:hover){.fld:hover:not(:focus-within):not(.ro):not(.is-error){box-shadow:inset 0 0 0 1px var(--ink-2)}}
.fld.is-hover{box-shadow:inset 0 0 0 1px var(--ink-2)}
.fld.ro{background:var(--neu-wash);box-shadow:none}.fld.ro .i{margin-left:auto}
.fld:has([aria-invalid=true]){box-shadow:inset 0 0 0 1px var(--crt)}
.fc{display:grid}.fc>.fhint,.fc>.ferr{margin-top:4px}
.fc.dis .flabel,.fc.dis .fld{opacity:.55}
.caret{display:inline-block;width:1.5px;height:15px;margin-left:1px;vertical-align:-3px;background:var(--accent)}
.clr{display:grid;place-items:center;flex:none;width:16px;height:16px;margin-left:auto;border:0;padding:0;border-radius:50%;background:var(--glyph);color:var(--on-accent)}
.clr .i{width:10px;height:10px;stroke-width:3.6}
.fld .i.spin{margin-left:auto;color:var(--ink-2)}
.money{display:flex;align-items:center;gap:2px}.money>span{color:var(--ink-2)}

/* 2.02 Inset field + one-time code (kit/code-input.js) — the pre-login forms' dress (Access, Registration, invitations).
   At rest the field sits in a quiet inset well (a top inner shade) behind its 3:1 edge; focus lifts it to white with a 2 px accent edge (the
   edge is the focus mark, so no outer ring); error = critical, success = positive. Code boxes: the native text is
   transparent and the glyph laid over it enters with a short fade · blur · rise; an empty focused box blinks its own
   caret; an error shakes the row once. Reduced motion: no entry, no shake, a still caret. */
.fld.inset{background:var(--g3);box-shadow:inset 0 0 0 1px var(--edge-field),inset 0 1px 2px var(--hair-2);transition:box-shadow var(--dur-hover) ease,background-color var(--dur-hover) ease}
.fld.inset:focus-within{background:var(--g3-dense);box-shadow:inset 0 0 0 2px var(--accent)}
.fld.inset:has(:focus-visible){outline:none}
.fld.inset.is-error,.fld.inset:has([aria-invalid=true]){box-shadow:inset 0 0 0 1px var(--crt)}
.fld.inset.is-error:focus-within,.fld.inset:has([aria-invalid=true]):focus-within{box-shadow:inset 0 0 0 2px var(--crt)}
.fld.inset.is-ok{box-shadow:inset 0 0 0 1px var(--pos)}
.ci{display:flex;align-items:center;gap:var(--s2)}
.ci-gap{flex:none;width:var(--s1)}
.ci-cell{position:relative;flex:0 1 var(--hit);min-width:0;height:calc(var(--hit) + var(--s2));padding:0;justify-content:center}
.ci-cell.is-filled{background:var(--g3-dense)}
.ci-cell input{position:absolute;inset:0;width:100%;height:100%;text-align:center;font:var(--t-metric);color:transparent;-webkit-text-fill-color:transparent;caret-color:transparent}
.ci-cell input::selection{background:transparent}
.ci-cell input:-webkit-autofill,.ci-cell input:autofill{-webkit-text-fill-color:transparent;caret-color:transparent}
.ci-glyph{position:absolute;inset:0;display:grid;place-items:center;font:var(--t-metric);font-variant-numeric:tabular-nums;color:var(--ink-1);pointer-events:none;transition:color var(--dur-hover) ease}
.ci-cell.is-filled .ci-glyph{animation:ci-in var(--dur-morph-in) var(--ease-out) both}
.ci-cell.is-ok .ci-glyph{color:var(--pos-ink)}
.ci-caret{position:absolute;left:50%;top:50%;width:1.5px;height:var(--s6);border-radius:var(--r-pill);background:var(--accent);transform:translate(-50%,-50%);opacity:0;pointer-events:none}
.ci-cell:focus-within:not(.is-filled) .ci-caret{opacity:1;animation:ci-blink 1.06s steps(1,end) infinite}
.ci-cell.is-error .ci-caret{background:var(--crt)}
.ci.is-shake{animation:ci-shake 320ms var(--ease-out)}
.ci.is-disabled .ci-cell,.ci-cell:has(input:disabled){opacity:.55}
@keyframes ci-in{from{opacity:0;transform:translateY(var(--s2)) scale(.97);filter:blur(var(--s1))}}
@keyframes ci-blink{50%{opacity:0}}
@keyframes ci-shake{25%{transform:translateX(calc(var(--s1) * -1.25))}50%{transform:translateX(var(--s1))}75%{transform:translateX(calc(var(--s1) * -.75))}}
.is-phone .ci .ci-cell input{height:100%;margin-block:0}
@media (prefers-reduced-motion:reduce){.fld.inset{transition:none}.ci.is-shake,.ci-cell.is-filled .ci-glyph,.ci-cell:focus-within:not(.is-filled) .ci-caret{animation:none}.ci-glyph{transition:none}}
@media (forced-colors:active){.ci-cell input{-webkit-text-fill-color:CanvasText;color:CanvasText}.ci-glyph,.ci-caret{display:none}}

/* 2.02 Password strength (kit/password-strength.js) — under a new-password field. One row: a segment per rule (the
   kit's 6 px bar) filling left to right in the score's tone (critical · notice · positive), and beside it the strength
   word, cross-fading ("Commonly guessed" in place of the word for a guessable password; nothing while empty). Below,
   the rules tick off in round checks (a filled positive disc when met). A weak submit (data-insist) turns the unmet
   rules critical and nudges them once. Reduced motion: every change lands at once. */
.pw{--pw-tone:var(--neu);--pw-ink:var(--ink-2)}
.pw[data-tone=crt]{--pw-tone:var(--crt);--pw-ink:var(--crt-ink)}
.pw[data-tone=ntc]{--pw-tone:var(--ntc);--pw-ink:var(--ntc-ink)}
.pw[data-tone=pos]{--pw-tone:var(--pos);--pw-ink:var(--pos-ink)}
.pw-row{display:grid;grid-template-columns:minmax(0,1fr) auto;align-items:center;gap:var(--s3);margin-top:var(--s2)}
.pw-meter{display:grid;grid-auto-columns:minmax(0,1fr);grid-auto-flow:column;gap:var(--s1)}
.pw-seg{position:relative;height:6px;overflow:hidden;border-radius:3px;background:var(--neu-wash)}
.pw-seg i{position:absolute;inset:0;border-radius:inherit;background:var(--pw-tone);transform:scaleX(0);transform-origin:left;
transition:transform var(--dur-toggle) var(--spring) calc(var(--i) * 30ms),background-color var(--dur-hover) ease}
.pw[data-score="1"] .pw-seg:nth-child(-n+1) i,.pw[data-score="2"] .pw-seg:nth-child(-n+2) i,.pw[data-score="3"] .pw-seg:nth-child(-n+3) i,.pw[data-score="4"] .pw-seg:nth-child(-n+4) i,.pw[data-score="5"] .pw-seg:nth-child(-n+5) i,.pw[data-score="6"] .pw-seg:nth-child(-n+6) i{transform:scaleX(1)}
.pw-word{display:inline-grid;justify-items:end;min-width:8.5em;font:var(--t-label);color:var(--pw-ink);transition:color var(--dur-hover) ease}
.pw-word>span{grid-area:1/1;white-space:nowrap;opacity:0;transform:translateY(calc(var(--s1) / 2));transition:opacity var(--dur-toggle) var(--ease-out),transform var(--dur-toggle) var(--ease-out)}
.pw[data-score="1"] [data-w="1"],.pw[data-score="2"] [data-w="2"],.pw[data-score="3"] [data-w="3"],.pw[data-score="4"] [data-w="4"],.pw[data-score="5"] [data-w="5"],.pw[data-score="6"] [data-w="6"]{opacity:1;transform:none}
.pw[data-guess] .pw-word>span{opacity:0}
.pw[data-guess] .pw-word>[data-w=g]{opacity:1;transform:none}
.pw-rules{list-style:none;display:grid;grid-template-columns:1fr 1fr;gap:var(--s1) var(--s3);margin-top:var(--s3)}
.pw-rules li{display:flex;align-items:center;gap:var(--s2);font:var(--t-small);color:var(--ink-2);transition:color var(--dur-hover) ease}
.pw-rules li.on{color:var(--ink-1)}
.pw-tick{position:relative;display:grid;place-items:center;flex:none;width:14px;height:14px;border-radius:50%;box-shadow:inset 0 0 0 1.5px var(--hair-2);color:var(--on-accent);transition:box-shadow var(--dur-hover) ease}
.pw-tick::before{content:"";position:absolute;inset:0;border-radius:inherit;background:var(--pos);opacity:0;transform:scale(.4);transition:opacity var(--dur-toggle) var(--ease-out),transform var(--dur-toggle) var(--spring)}
.pw-tick svg{position:relative;width:64%;height:64%;fill:none;stroke:currentColor;stroke-width:1.9;stroke-linecap:round;stroke-linejoin:round;opacity:0;transform:scale(.6);
transition:opacity var(--dur-toggle) var(--ease-out),transform var(--dur-toggle) var(--spring)}
.pw-rules li.on .pw-tick{box-shadow:none}
.pw-rules li.on .pw-tick::before,.pw-rules li.on .pw-tick svg{opacity:1;transform:none}
.pw[data-insist] .pw-rules{animation:ci-shake 320ms var(--ease-out)}
.pw[data-insist] .pw-rules li:not(.on){color:var(--crt-ink)}
.pw[data-insist] .pw-rules li:not(.on) .pw-tick{box-shadow:inset 0 0 0 1.5px var(--crt)}
.is-phone .pw-rules{grid-template-columns:1fr}
@media (prefers-reduced-motion:reduce){.pw-seg i,.pw-word,.pw-word>span,.pw-rules li,.pw-tick,.pw-tick::before,.pw-tick svg{transition:none}.pw[data-insist] .pw-rules{animation:none}}
@media (forced-colors:active){.pw-seg{border:1px solid CanvasText}.pw-seg i{forced-color-adjust:none;background:CanvasText}.pw-tick{border:1px solid CanvasText}.pw-tick::before{forced-color-adjust:none;background:CanvasText}}

/* 2.03 Segmented control · tabs — the thumb travels (spring 260); at rest it is the drawn pressed style */
.seg{position:relative}
.seg>button{position:relative;z-index:1;transition:background-color var(--dur-hover) ease}
.seg>button[aria-selected=true],.seg>button[aria-checked=true]{background:var(--on-accent);font-weight:600;box-shadow:var(--seg-thumb-sh)}
@media (hover:hover){.seg>button:hover:not([aria-pressed=true],[aria-selected=true],[aria-checked=true],:disabled,[aria-disabled=true]){background:color-mix(in srgb,var(--ink-1) 6%,transparent)}}
/* pressed (feel standard 1): same specificity as the hover rule and later in the sheet, so a press always out-ranks the hover under it */
.seg>button:active:not([aria-pressed=true],[aria-selected=true],[aria-checked=true],:disabled,[aria-disabled=true]){background:color-mix(in srgb,var(--ink-1) 12%,transparent)}
.seg.is-dis{opacity:.55}
.seg .t{display:inline-flex;flex-direction:column;align-items:center}
.seg .t::after{content:attr(data-t);height:0;overflow:hidden;visibility:hidden;font-weight:600}
.seg.full{display:flex;width:100%}.seg.full>button{flex:1}
.seg-thumb{position:absolute;z-index:0;border-radius:var(--r-tag);background:var(--on-accent);box-shadow:var(--seg-thumb-sh);pointer-events:none;transform-origin:left center}
.seg.is-travelling>button[aria-pressed=true],.seg.is-travelling>button[aria-selected=true]{background:none;box-shadow:none}
/* 2.03b Family rail (kit sheet lwRnurA-qH): a page family's views as links in the segmented's track — the current one
   drawn pressed (Carriers · Requests). On phone the family is a pop-up button instead (2.03b phone rule). */
.seg.rail>a{display:inline-flex;align-items:center;justify-content:center;gap:4px;height:24px;padding:0 10px;border-radius:var(--r-tag);font:500 .75rem/1 var(--font-ui);color:var(--ink-1);white-space:nowrap}
.seg.rail>a b{font-weight:500;color:var(--ink-2)}
.seg.rail>a[aria-current=page]{background:var(--on-accent);font-weight:600;box-shadow:var(--seg-thumb-sh)}
.seg.rail>a{transition:background-color var(--dur-hover) ease}
.band .bt:has(>.seg.rail){align-items:center}   /* the annuity admin's rail leads the band's title (frames 50–53) */
@media (hover:hover){.seg.rail>a:hover:not([aria-current=page]){background:color-mix(in srgb,var(--ink-1) 6%,transparent)}}
.seg.rail>a:active:not([aria-current=page]){background:color-mix(in srgb,var(--ink-1) 12%,transparent)}
@media (forced-colors:active){.seg.rail>a[aria-current=page]{background:Highlight;color:HighlightText;forced-color-adjust:none}}

/* 2.17 Filter bar — ONE filter bar (standard 2): 44 min · padding 8 · gap 8 · r12; the glass is the markup's own g2 tier (the
   six page copies agree on G2 — no new recipe). Slots in order: search .fld · .toks (.tk tokens) · .seg · .end (trailing
   .btn.pu / .btn.pl, pushed right). Pages add only what is theirs (a search width, a second token row).
     <div class="pane g2 fbar" role="toolbar" aria-label="Filter clients">
       <label class="fld"><span class="sr-only">Search</span>${icon('search')}<input type="search"></label>
       <span class="toks" role="group" aria-label="Status"><button type="button" class="tk" aria-pressed="false">Active <b>12</b></button></span>
       <span class="seg" role="group">…</span>
       <span class="end"><button type="button" class="btn pu">Carrier${icon('chd','s12')}</button><button type="button" class="btn pl">Clear</button></span>
     </div>
   Phone: the bar wraps, the search takes its own full row, every control keeps its 44 hit area (.fld · .btn · .tk · .seg). */
.fbar{display:flex;align-items:center;gap:8px;min-height:44px;padding:8px;border-radius:var(--r-card)}
.fbar>.fld{flex:0 1 240px;min-width:160px}
.fbar .toks{display:flex;flex-wrap:wrap;align-items:center;gap:4px}
.toks{display:flex;flex-wrap:wrap;align-items:center;gap:4px} /* tokens outside a bar: next to a section head (.rh .end, .sh) */
/* leading summary row (retention): a full-width first row of stats above the controls — .fbar>.sum, text only */
.fbar>.sum{flex:1 0 100%;display:flex;flex-wrap:wrap;align-items:center;gap:4px 12px;font:var(--t-small);color:var(--ink-2)}
.fbar .end{margin-left:auto;display:flex;align-items:center;gap:6px}
.fbar .btn .i{color:var(--ink-2)}

/* 2.04 Switch · checkbox · radio */
.tg{display:inline-flex;align-items:center;gap:8px;min-height:28px;font:var(--t-body);color:var(--ink-1)}
.tg .sub{display:block}.tg.is-dis{opacity:.55}
.chk:indeterminate,.chk.mixed{background:var(--accent);box-shadow:none}
.chk:indeterminate::after,.chk.mixed::after{content:"";width:8px;height:1.8px;border:0;border-radius:1px;background:var(--on-accent);transform:none}
@media (hover:hover){
.sw:hover input:not(:disabled)~i{background:color-mix(in srgb,var(--ink-1) 20%,transparent)}.sw:hover input:checked:not(:disabled)~i{background:var(--accent-hover)}
.chk:hover:not(:disabled):not(:checked):not(:indeterminate),.rad:hover:not(:disabled):not(:checked){box-shadow:inset 0 0 0 1px var(--ink-2)}
.chk:hover:checked:not(:disabled),.chk:hover:indeterminate:not(:disabled),.rad:hover:checked:not(:disabled){background:var(--accent-hover);box-shadow:none}}
.chk:active:not(:disabled):not(:checked),.rad:active:not(:disabled):not(:checked){background:color-mix(in srgb,var(--ink-1) 12%,transparent)}
.chk:active:checked:not(:disabled),.rad:active:checked:not(:disabled){background:var(--accent-hover);filter:brightness(.9)}
.chk[aria-invalid=true],.rad[aria-invalid=true],.chk.is-err,.rad.is-err{box-shadow:inset 0 0 0 1px var(--crt)}
.chk:disabled,.rad:disabled,.sw input:disabled~i,.sw input:disabled~b{opacity:.55}

/* ---------- 3 · Status · tags · tokens · badge · logos (2.05) ---------- */
.tk{transition:background-color var(--dur-hover) ease,transform var(--dur-press) var(--ease-out)}
.tk .i{color:var(--ink-2)}
@media (hover:hover){.tk:hover:not([aria-pressed=true],:disabled,[aria-disabled=true]){background:color-mix(in srgb,var(--ink-1) 10%,transparent)}}
.tk:active:not(:disabled,[aria-disabled=true]){transform:scale(.97)}
.tk.lv{opacity:.4;transform:scale(.96)}
/* 3.02 pipeline: "Your move" — the one tag that points at the viewer (accent tint + accent ink) */
.tag.ac{background:var(--accent-tint);color:var(--accent-ink)}
/* 2.05 avatar, small (24): approval cards (3.09) and phone worklist rows (IA-03) */
.av.s{width:24px;height:24px;font-size:.6875rem}
.logos{display:inline-flex;align-items:center;vertical-align:middle}
.logos .logo+.logo{margin-left:-4px;box-shadow:0 0 0 .5px var(--hair-2),0 0 0 1.5px var(--on-accent)}

/* ---------- 4 · Content ---------- */
/* 2.06 Panels & sections */
.insp footer{display:flex;gap:6px;margin-top:auto;padding:12px 16px;box-shadow:inset 0 1px 0 var(--hair-2)}
.insp .ht{flex:1;min-width:0;display:grid;gap:4px;justify-items:start}
.rh{display:flex;align-items:center;gap:12px;height:64px;padding:0 12px 0 16px}
.rh h2{min-width:0;overflow:hidden;text-overflow:ellipsis;font:600 1.0625rem/1.25 var(--font-ui);letter-spacing:-.01em}   /* a name with no break points ends in "…" instead of widening the page (B6-4); a name with spaces still wraps */
.rh .end{margin-left:auto;display:flex;align-items:center;gap:6px}
.rh .btn .i,.insp .btn .i{color:var(--ink-2)}
.kv3{display:grid;grid-template-columns:repeat(3,1fr);margin-top:6px}
.kv3>div{display:grid;gap:2px;padding:8px 0;border-top:1px solid var(--hair)}
.kv3>div:nth-child(-n+3){border-top:0}
.kv3>div:not(:nth-child(3n+1)){padding-left:20px}
.kv3 dd.no,.kv dd.no{color:var(--ink-2)}
/* 2.06 / 2.07: one continuous hairline between key/value rows — the 16 px between the columns moves from the grid gap
   into the value's padding, so the key's and the value's top borders meet */
.kv{column-gap:0}
.kv dd{padding-left:16px}
.co{margin-top:12px;padding:12px;border-radius:var(--r-ctl);background:var(--ntc-wash);box-shadow:inset 0 0 0 .5px color-mix(in srgb,var(--ntc) 22%,transparent)}
.co-h{display:flex;align-items:center;gap:6px;font:var(--t-strong);color:var(--ntc-ink)}
.co-h .i{width:14px;height:14px;stroke-width:2.14}
.co-f{margin:2px 0 0 20px;font:var(--t-small);color:var(--ink-2)}
/* BANNER — the inline message (kit/blocks.js bannerHTML): .co in flow, tones crt · inf · pos (none = notice), one line + one .co-a action.
     <div class="co crt" role="alert"><div class="co-h">${icon('alert')}<span>Message</span><button type="button" class="btn pl co-a">Retry</button></div></div> */
.co.crt{background:var(--crt-wash);box-shadow:inset 0 0 0 .5px color-mix(in srgb,var(--crt) 22%,transparent)}.co.crt .co-h{color:var(--crt-ink)}
.co.inf{background:var(--inf-wash);box-shadow:inset 0 0 0 .5px color-mix(in srgb,var(--inf) 22%,transparent)}.co.inf .co-h{color:var(--inf-ink)}
.co.pos{background:var(--pos-wash);box-shadow:inset 0 0 0 .5px color-mix(in srgb,var(--pos) 22%,transparent)}.co.pos .co-h{color:var(--pos-ink)}
.co-h>span{min-width:0}.co-h>.co-a{margin-left:auto}
@media (forced-colors:active){.co{border:1px solid CanvasText}}
.pr{display:grid;grid-template-columns:16px 1fr auto;column-gap:10px;row-gap:4px;align-items:center;padding:8px 0;border-top:1px solid var(--hair)}
.pr:first-of-type{border-top:0}
.pr .logo{grid-row:span 2;align-self:start;margin-top:1px}
.pr b{font:var(--t-strong)}
.pr .r{text-align:right;font-variant-numeric:tabular-nums}
.pr .r small{font:var(--t-small);color:var(--ink-2)}
.pr .sub{grid-column:2}
.pr .st{justify-self:end;font:var(--t-small)}
/* 2.07 Table · ledger */
.tbl b{font-weight:600}
.tbl .cn{display:flex;align-items:center;gap:10px;font-weight:600}
.tbl tbody tr[data-href],.tbl tbody tr[data-open]{cursor:default}
.tbl tbody tr:active td,.tbl tr.prs td{background:var(--accent-tint)}
.tbl tr.hv td,.tbl tr.nw td{background:var(--accent-wash)}
.tbl td.act{text-align:right}
/* row actions (td.act) hide only where a pointer can hover, by opacity (a visibility:hidden button can never take focus, so
   :focus-within could not reveal it); on touch / no-hover devices they are always shown — the phone .btn::after gives 44 */
@media (hover:hover){
.tbl td.act .btn{opacity:0;transition:opacity var(--dur-hover) ease}
.tbl tr:hover td.act .btn,.tbl tr:focus-within td.act .btn,.tbl tr.is-sel td.act .btn{opacity:1}}
.tbl td.act .btn .i{color:var(--ink-2)}
.tbl.lt,.lt{table-layout:fixed}
/* row2 — the two-line row (standard: 36 · dense 32 · two-line 48): line 1 = .cn (name, 600), line 2 = .sub (small, ink-2).
     <table class="tbl row2"><tbody><tr><td><span class="cn">${logo}<span class="l2"><b>Maya Ellis</b><span class="sub">Final expense · MetLife</span></span></span></td>… */
.tbl.row2 td{height:48px}
.tbl .l2{display:grid;grid-template-columns:minmax(0,1fr);gap:1px;min-width:0}
.tbl .l2 b{font:var(--t-strong)}
.tbl .l2 .sub{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* show all — the one cap control (kit/capped-list.js showAllHTML / capped): .btn.pl + chevron, the chevron turns over when open */
.tbl tr.more td{height:var(--h-row);text-align:left}.tbl tbody tr.more:hover td{background:none}
.showall .i{transition:transform var(--dur-hover) ease}
.showall[aria-expanded=true] .i{transform:rotate(180deg)}
.lfoot,.tfoot{display:flex;align-items:center;gap:8px;height:44px;padding:0 10px 0 16px;box-shadow:inset 0 1px 0 var(--hair-2);font:var(--t-small);color:var(--ink-2)}
.lfoot b,.tfoot b{font:var(--t-strong);color:var(--ink-1);font-variant-numeric:tabular-nums}
.lfoot .vr{width:1px;height:18px;margin:0 6px;background:var(--hair-2)}
.lfoot .end,.tfoot .end{margin-left:auto;display:flex;align-items:center;gap:8px}
/* PAGER — range left, size pop-up + prev/next right (kit/blocks.js pagerHTML); on phone it may wrap instead of overflowing */
.is-phone .lfoot.pager{height:auto;min-height:44px;padding-block:6px;flex-wrap:wrap}
/* 2.08 Metrics */
.delta{display:inline-flex;align-items:center;gap:4px;font:600 .75rem/1.3 var(--font-ui);color:var(--pos-ink);font-variant-numeric:tabular-nums;white-space:nowrap}
.delta .i{width:13px;height:13px;stroke-width:2.3}
.delta.dn{color:var(--crt-ink)}
.delta span{font-weight:400;color:var(--ink-2)}
.v small{font:var(--t-small);color:var(--ink-2);margin-left:1px}
.mtr{display:block;height:6px;border-radius:3px;background:var(--track);margin:4px 0}
.mtr i{display:block;height:100%;border-radius:3px;background:var(--data-1)}
.bar2{display:block;width:100%;height:6px;border-radius:3px;background:var(--track)}
.bar2 i{display:block;height:100%;border-radius:3px;background:var(--data-1)}.bar2 i.m{background:var(--data-muted)}
.stk{display:flex;gap:2px;height:6px}.stk i{display:block;height:100%;border-radius:3px}
.lg{display:grid;gap:8px}.lg>div{display:flex;align-items:center;gap:8px;font:var(--t-small)}
.lg>div b{margin-left:auto;font:600 .75rem/1 var(--font-ui);font-variant-numeric:tabular-nums}
.key i.m{background:var(--data-muted)}.key i.d.m{background:none;border-top-color:var(--data-muted)}
.tip{position:absolute;z-index:6;padding:10px 12px;border-radius:var(--r-menu);display:grid;gap:6px;pointer-events:none}
.tip p{font:var(--t-label);color:var(--ink-2)}
.tip div{display:flex;align-items:center;gap:8px;font:var(--t-small)}
.tip div b{margin-left:auto;font:600 .75rem/1 var(--font-ui);font-variant-numeric:tabular-nums}
/* 2.09 Empty · loading · error — one line + one action, in place; skeleton after 150 ms; cause + one action */
.empty{flex:1;display:grid;place-items:center;align-content:center;gap:12px;padding:16px;text-align:center}
.pane>.empty{min-height:200px} /* the one sanctioned empty height for a pane (= .pe) — pages stop writing their own */
/* filtered empty (.empty.filtered): the same block; its line names the filter, its one action clears it (fmt.filteredEmpty):
     <div class="empty filtered" role="status"><p>No clients match Lincoln, Pending</p><button type="button" class="btn pl" data-clear-filters>Clear filters</button></div> */
.empty.filtered p{max-width:48ch}
.empty p{display:flex;align-items:center;gap:6px;font:500 .8125rem/1.4 var(--font-ui);color:var(--ink-2)}
.empty p .i,.caught .i{color:var(--pos)}
.caught{display:flex;align-items:center;gap:6px;color:var(--ink-2)}
/* compact inline empty state (one line + one action, no full-pane centering): a smaller card or list row's "no data" */
.empty-row{display:flex;align-items:center;gap:12px}
.empty-row p{font:500 .8125rem/1.4 var(--font-ui);color:var(--ink-2)}
.empty-line{display:flex;align-items:center;margin-top:6px;font:500 .8125rem/1.4 var(--font-ui);color:var(--ink-2)}
.err{display:flex;align-items:center;gap:10px;min-height:40px;margin-top:6px}
.err .i{color:var(--crt)}
.err b{font:var(--t-strong)}
.menu .err{margin-top:0;padding:0 8px}
.err .btn{margin-left:auto}.err .btn .i{color:var(--ink-2)}
.pe{display:grid;place-items:center;align-content:center;gap:12px;min-height:200px;padding:20px;text-align:center}
.pe p{display:flex;align-items:center;gap:6px;font:500 .8125rem/1.4 var(--font-ui)}
.pe p .i{color:var(--crt)}
.pe .acts{display:flex;flex-wrap:wrap;justify-content:center;gap:8px} /* two actions side by side (pageErrorHTML / pageGateHTML actions) */
/* PAGEGATE — a whole page behind a permission or plan: the page error block with a neutral glyph (kit/blocks.js pageGateHTML) */
.pe.gate p .i{color:var(--ink-2)}
/* Read states share a calm hierarchy; unavailable access never resembles an empty queue. */
.state-view{display:grid;justify-items:center;align-content:center;gap:16px;min-height:248px;padding:32px 24px;text-align:center}
.state-view-icon{display:grid;place-items:center;width:44px;height:44px;border:1px solid var(--hair);border-radius:14px;background:var(--accent-wash);color:var(--ink-2)}
.state-view-icon .i{width:20px;height:20px}
.state-view-copy{min-width:0;max-width:48ch;display:grid;gap:8px}
.state-view-copy h2{margin:0;font:var(--t-section);color:var(--ink-1);overflow-wrap:anywhere}
.state-view-copy p{margin:0;font:var(--t-body);color:var(--ink-2);line-height:1.5;overflow-wrap:anywhere}
.state-view-actions{display:flex;justify-content:center;gap:8px;flex-wrap:wrap;max-width:100%}
.state-view-actions .btn{min-height:var(--h-ctl)}
.state-view.compact{min-height:168px;padding:24px 18px;gap:12px}
.err{flex-wrap:wrap}.err .i{flex:none}.err>span,.err>p{min-width:0;overflow-wrap:anywhere}
@media(max-width:600px){.state-view{padding:28px 18px;min-height:224px}.state-view-actions .btn{min-height:44px}.state-view-copy{max-width:100%}}
.sk{display:block;height:10px;border-radius:3px;background:var(--track)}
.sk.rt{margin-left:auto}
.ska{display:block;width:28px;height:28px;flex:none;border-radius:50%;background:var(--track)}
.skq{display:block;width:16px;height:16px;flex:none;border-radius:4px;background:var(--track)}
.skd{display:block;width:6px;height:6px;flex:none;border-radius:50%;background:var(--track)}
.skc{display:flex;align-items:center;gap:10px}
[aria-busy=true] .sk-in,.sk-in,.ld,.ld-cards{animation:milo-sk-in var(--dur-press) ease-out 150ms both}
/* LOADING — the one loading block (kit/blocks.js loadingHTML): 36 px skeleton rows (.row2: 48) that fade in after 150 ms, so a fast read never flashes.
     <div class="ld" role="status" aria-busy="true" aria-label="Loading clients"><div class="skc"><span class="ska"></span><span class="sk w35"></span><span class="sk rt w20"></span></div>…</div>
   .ld-cards = the route shell's four metric skeletons (2-up on phone) above the rows. */
.sk.w20{width:20%}.sk.w35{width:35%}.sk.w60{width:60%}.sk.w80{width:80%}.sk.tall{height:24px}
.ld{display:grid}
.ld .skc{min-height:var(--h-row);padding:0 16px;box-shadow:inset 0 1px 0 var(--hair)}
.ld .skc:first-child{box-shadow:none}
.ld.row2 .skc{min-height:48px}
.ld-cards{display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:var(--gutter);margin-bottom:var(--gutter)}
.ld-cards .pane{display:grid;gap:12px;padding:16px}
.is-phone .ld-cards{grid-template-columns:repeat(2,minmax(0,1fr))}
@keyframes milo-sk-in{from{opacity:0}to{opacity:1}}
.no{color:var(--ink-2)}

/* 3.01 Chart kit — shared chart parts (app/chart.js): hit band tinted --accent-wash on hover · float-glass readout r12,
   value first (tabular), label second with its key · the figure is .plot (positioned) · keys move the readout instantly */
.plot{position:relative}
.hit{fill:var(--accent-wash);opacity:0;transition:opacity var(--dur-hover) ease}
.hit.on{opacity:1}
[data-input-modality=keyboard] .hit{transition:none}
.rdo{position:absolute;z-index:5;display:grid;gap:4px;min-width:176px;padding:10px 12px 12px;border-radius:var(--r-menu);pointer-events:none}
.rdo .t{font:var(--t-label);color:var(--ink-2)}
.rdo .r{display:flex;align-items:baseline;gap:8px;font:var(--t-small);color:var(--ink-2)}
.rdo .r b{font:var(--t-strong);color:var(--ink-1);font-variant-numeric:tabular-nums}
.rdo .r i{align-self:center;width:10px;height:3px;border-radius:2px;background:var(--data-1);flex:none}
.rdo .r i.c2{background:var(--data-2)}.rdo .r i.c3{background:var(--data-3)}.rdo .r i.n{background:none}
.rdo .r i.h{height:10px;background:repeating-linear-gradient(135deg,var(--data-1) 0 2px,transparent 2px 4.2px);box-shadow:inset 0 0 0 .5px var(--data-1)}
svg[tabindex]{cursor:default}

/* 2.15 Stepper — node 20: done = check + a one-line summary (a button: click to return, nothing is lost) · current =
   numeral in an accent ring, label 600 accent ink, never a check · ahead = muted, not reachable until its turn.
   Connector 2 px: accent behind you, track ahead; it fills toward the next step (260 spring; keys and reduced motion:
   instant). Horizontal .stp (4 steps; .s5 five) · vertical .vst (registration rail) · phone: one line .pt + meter. */
.stp{display:grid;grid-template-columns:repeat(4,minmax(0,1fr))}
.stp.s5{grid-template-columns:repeat(5,minmax(0,1fr))}
.stp>*{position:relative;display:grid;justify-items:start;align-content:start;gap:4px}
.stp>button,.vst>button{border:0;padding:0;background:none;text-align:left}
.vst>button{padding-bottom:18px} /* a done step is a button: it keeps 2.15's 18 px between rows (the last row's 0 wins) */
.stp>*:not(:last-child)::after{content:"";position:absolute;left:26px;right:8px;top:9px;height:2px;border-radius:1px;background:linear-gradient(90deg,var(--accent) 50%,var(--track) 50%) 100% 0/200% 100% no-repeat;transition:background-position var(--dur-toggle) var(--spring)}
.stp>.done::after{background-position:0 0}
.nd{display:grid;place-items:center;width:20px;height:20px;border-radius:50%;font:var(--t-label);color:var(--ink-2);box-shadow:inset 0 0 0 1px var(--hair-2);background:var(--g3)}
.done .nd{background:var(--accent);color:var(--on-accent);box-shadow:none}
.done .nd .i{width:12px;height:12px;stroke-width:2.6}
.cur .nd{color:var(--accent-ink);box-shadow:inset 0 0 0 1.5px var(--accent);background:var(--on-accent)}
.stp b,.vst b{font:500 .75rem/1.2 var(--font-ui);color:var(--ink-2)}
.stp .done b,.vst .done b{color:var(--ink-1)}.stp .cur b,.vst .cur b{font-weight:600;color:var(--accent-ink)}
.stp small,.vst small{font:var(--t-small);color:var(--ink-2)}
.sheet .stp{padding:2px 20px 16px;box-shadow:inset 0 -1px 0 var(--hair-2)}
.vst{display:grid}
.vst>*{position:relative;display:grid;grid-template-columns:20px minmax(0,1fr);column-gap:12px;row-gap:2px;padding-bottom:18px}
.vst>*:last-child{padding-bottom:0}
.vst>*:not(:last-child)::after{content:"";position:absolute;left:8px;top:24px;bottom:4px;width:2px;border-radius:1px;background:linear-gradient(180deg,var(--accent) 50%,var(--track) 50%) 0 100%/100% 200% no-repeat;transition:background-position var(--dur-toggle) var(--spring)}
.vst>.done::after{background-position:0 0}
.vst b{align-self:center;font-size:.8125rem}
.vst small{grid-column:2}
.pt{display:flex;align-items:center;gap:10px}
.pt p{flex:1;font:var(--t-strong)}
.pt p span{font-weight:400;color:var(--ink-2)}
.pt .sv{font:var(--t-small);color:var(--ink-2)}
.pt+.mtr{margin:12px 0 16px;overflow:hidden}
.pt+.mtr i{background:var(--accent)}
[data-input-modality=keyboard] :is(.stp,.vst)>*::after{transition:none}

/* ---------- 5 · Overlays ---------- */
/* 2.12 Popover · menu · select (float glass r12, rows 28 r6 inset 6, highlight = accent fill + white) */
.menu,.popover{z-index:30;overflow:auto;overscroll-behavior:contain}
.menu:focus,.popover:focus{outline:none}
.menu [role^=menuitem],.menu [role=option]{cursor:default}
.menu [role^=menuitem]>*,.menu [role=option]>*{pointer-events:none}   /* the whole row is the hit target: a press on its label, glyph or check lands on the row itself, never on a child that could read as "outside" */
.menu [role^=menuitem] .ml,.menu [role=option] .ml{flex:1;min-width:0;display:grid;gap:2px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.menu [role^=menuitem] small{font:var(--t-small);color:var(--ink-2);white-space:normal}
.menu [role^=menuitem]:has(small){height:auto;min-height:28px;padding:4px 8px;align-items:flex-start}
.menu [aria-disabled=true]{color:var(--ink-disabled)}
.menu [aria-disabled=true]:hover{background:none;color:var(--ink-disabled)}
.menu .is-hl small,.menu [role^=menuitem]:hover:not([aria-disabled=true]) small{color:inherit}
.menu .danger{color:var(--crt-ink)}
.menu .ck{display:grid;place-items:center;width:14px;flex:none}
.menu .ck .i{width:14px;height:14px;stroke-width:2.2;color:inherit}
.menu .ck0{width:14px;flex:none}
.menu .is-hl .ct,.menu .is-hl kbd,.menu [role^=menuitem]:hover .ct{color:inherit}
/* 2.16 Avatar menu — 240 · who is signed in (name and email: not a row, nothing to press) · Account · Billing & credits · Sign out last */
.acct .id{display:grid;grid-template-columns:36px minmax(0,1fr);align-items:center;gap:10px;padding:6px 8px 8px}
.acct .id b{display:block;font:var(--t-strong)}
.acct .id div span{display:block;font:var(--t-small);color:var(--ink-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.acct .scope{list-style:none;display:grid;padding:0 0 4px}   /* the contracting seat's carrier scope (IA-02): rows, not items */
.acct .scope li{display:flex;align-items:center;gap:8px;min-height:28px;padding:0 8px;font:var(--t-body);color:var(--ink-1)}
.acct .scope .nolg{width:16px;height:16px;flex:none}
.menu-empty{display:flex;align-items:center;gap:6px;min-height:32px;padding:4px 8px 6px;font:var(--t-body);color:var(--ink-2)}
.menu-empty .i{color:var(--pos)}
.listbox{padding:6px}
.listbox .lbs{position:sticky;top:-6px;z-index:1;margin:-6px -6px 6px;padding:6px;background:var(--float)}   /* searchable select: the field stays pinned while the options scroll */
/* 2.12 select · a two-line option (a value with its reason or its figures): the row grows to hold both lines (36 at
   least, the IA-10 listbox); the second line is quiet, and takes the row's ink when the row is highlighted or hovered */
.menu [role=option] small{font:var(--t-small);color:var(--ink-2);white-space:normal}
.menu [role=option]:has(small){height:auto;min-height:36px;padding:4px 8px}
.menu [role=option]:hover:not([aria-disabled=true]) small{color:inherit}
.opt2{display:grid;gap:1px;min-width:0}.opt2 b{font:var(--t-strong)}.opt2 span{font:var(--t-small);color:var(--ink-2)}
.menu .is-hl .opt2 span{color:var(--on-accent)}
/* 2.11 Dialog · consequence dialog (sheet glass + scrim; 420 · r16; actions trailing, primary last) */
dialog{color:inherit}
dialog.dialog,dialog.sheet{margin:0;border:0;max-width:calc(100% - 24px);max-height:calc(100% - 24px);overflow:visible}
dialog.dialog{inset:auto;left:50%;top:50%}
dialog::backdrop{background:var(--scrim);-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}
.dialog>footer{padding:0;box-shadow:none} /* the sheet-footer rule misaligned dialog buttons (2.01 · 2.14 fix) */
.dialog .effects{display:grid;gap:6px;margin-top:10px;padding-left:18px;font:var(--t-body)}
.is-phone .dialog>footer{flex-wrap:wrap} /* a footer that can't hold both actions wraps instead of overflowing the dialog */
.dialog .fc{margin-top:14px}
.dialog-error{margin-top:12px}
/* 2.13 Sheet · drawer — side sheet inset 12 · r16 · 520; phone bottom sheet inset 8 with a grabber only when it drags */
dialog.side-sheet{inset:12px 12px 12px auto;height:auto;padding:0}
/* popovers and the toast live inside an open modal (the page behind is inert), so the side sheet must not clip them;
   its scrolling body keeps the rounded corners itself when no footer closes the sheet */
dialog.sheet.side-sheet{overflow:visible}
.sheet .sheet-body:has(+footer[hidden]){border-radius:0 0 var(--r-sheet) var(--r-sheet)}
.sheet .sheet-body{flex:1;min-height:0;overflow:auto;padding:4px 20px 20px}
.sheet>header .sheet-close{margin-left:auto}
dialog.bottom-sheet{inset:auto 8px 8px;width:auto;padding:0;display:flex;flex-direction:column;max-width:calc(100% - 16px);max-height:calc(100% - 64px);border-radius:var(--r-sheet)} /* top at 56 at most (2.16) */
.grab{display:grid;place-items:center;padding:6px 0 0;touch-action:none;cursor:grab}
.grab .grabber{margin:0}
/* phone bottom sheet (2.13 .bs): header 8 · 16 · 4, title = section; body inset 16; footer hairline, the commit fills */
dialog.bottom-sheet>header{gap:8px;padding:8px 16px 4px;touch-action:none}
dialog.bottom-sheet>header h2{font:var(--t-section)}
dialog.bottom-sheet .sheet-body{padding:0 16px 14px}
dialog.bottom-sheet .sheet-body .mlabel{padding:12px 0 4px;font:var(--t-label);color:var(--ink-2)}
dialog.bottom-sheet>footer{display:flex;align-items:center;gap:12px;padding:12px 16px 14px;box-shadow:inset 0 1px 0 var(--hair-2)}
dialog.bottom-sheet>footer .pri{flex:1}
dialog.sheet::backdrop{opacity:var(--sheet-progress,1)} /* the scrim follows the drag */
/* 2.13 centre sheet — the Search palette's presentation (app/search.js · .sp-root): a dimmed, blurred scrim and one
   panel in the middle of the screen (r8 · hairline ring · deep drop shadow). The flow sheets that use it (Post a deal)
   keep the kit header / body / footer; popovers and the toast still live inside it, so it must not clip. */
dialog.center-sheet{position:fixed;inset:max(8px,12vh) 0 auto;margin:0 auto;width:calc(100% - 16px);max-width:640px;height:min(640px,calc(100dvh - 2 * max(8px,12vh)));max-height:none;padding:0;display:flex;flex-direction:column;border-radius:8px;background:#fff;color:#171717;font-family:var(--font-ui);box-shadow:0 0 0 1px #e2e2e2,0 25px 50px -12px rgb(0 0 0/.25);-webkit-backdrop-filter:none;backdrop-filter:none;overflow:visible}
dialog.center-sheet::before{display:none}
dialog.center-sheet::backdrop{background:rgb(0 0 0/.5);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px)}
dialog.center-sheet>header{height:52px;padding:0 10px 0 14px;box-shadow:inset 0 -1px 0 #e2e2e2}
dialog.center-sheet .sheet-body{border-radius:0 0 8px 8px}
dialog.center-sheet>footer{box-shadow:inset 0 1px 0 #e2e2e2}
/* 2.16 More sheet — who is signed in, then everything that isn't a tab · drags like 2.13 */
dialog.more>header{padding:6px 12px 6px 20px}
dialog.more .sheet-body{padding:0 12px 12px}
.more .id{display:grid;grid-template-columns:36px minmax(0,1fr);align-items:center;gap:12px;padding:8px 8px 10px}
.more .id b{display:block;font:var(--t-strong)}
.more .id div span{display:block;font:var(--t-small);color:var(--ink-2)}
.mrow{display:flex;align-items:center;gap:12px;width:100%;height:var(--hit);padding:0 8px;border:0;border-radius:var(--r-ctl);background:none;font:500 .9375rem/1 var(--font-ui);color:var(--ink-1);text-align:left;transition:background-color var(--dur-hover) ease}
.mrow .i{width:20px;height:20px;stroke-width:1.5;color:var(--accent)}
.mrow .ct{margin-left:auto;font:var(--t-small);color:var(--ink-2)}
.mrow .tag{margin-left:auto}
.lab-list{display:grid;gap:8px;margin:0;padding:0;list-style:none} /* the lab panel's outbox (app/lab/panel.js) */
.mrow.is-locked{color:var(--ink-2)}.mrow.is-locked .i{color:var(--glyph)}
@media (hover:hover){.mrow:hover{background:color-mix(in srgb,var(--ink-1) 5%,transparent)}}
.mrow[aria-current=page]{background:var(--accent-tint);color:var(--accent-ink);font-weight:600;transition-duration:var(--dur-morph-out)}
.more hr{height:1px;margin:6px 8px;border:0;background:var(--hair-2)}
.more .gl2{padding:12px 8px 4px;font:var(--t-label);color:var(--ink-2)}
/* 2.10 Toast — one region, bottom centre of the content column, 24 up; up to three stack, newest lowest (C8). Kinds: ok
   (check, default) · warn (alert glyph in --ntc) · bad (--crt-ink fill, 6 s). Every toast has a close control; Escape closes too. */
.toast-region{position:fixed;z-index:35;left:var(--w-side);right:0;bottom:24px;display:flex;flex-direction:column;align-items:center;gap:8px;pointer-events:none}
.toast-region .toast{pointer-events:auto}
.toast{white-space:nowrap;max-width:calc(100vw - 24px)}
.toast>span:not(.drain){min-width:0;overflow:hidden;text-overflow:ellipsis} /* one line: a long message ends in an ellipsis instead of clipping at both edges */
.toast b{font-weight:600}
.toast .dim{color:color-mix(in srgb,var(--on-inverse) 72%,transparent);font-variant-numeric:tabular-nums}
.toast .drain{position:absolute;left:12px;right:12px;bottom:4px;height:2px;border-radius:1px;background:color-mix(in srgb,var(--on-inverse) 16%,transparent);overflow:hidden}
.toast .drain i{display:block;height:100%;background:var(--inverse-link)}
@media (hover:hover){.toast .btn:hover{background:color-mix(in srgb,var(--on-inverse) 24%,transparent)}}
.toast .btn.is-hover{background:color-mix(in srgb,var(--on-inverse) 24%,transparent)}
.toast.bad{background:var(--crt-ink);-webkit-backdrop-filter:none;backdrop-filter:none}
.toast.warn>.i{color:var(--ntc)}
/* the close control is deliberately not a .btn: pages and gates find a toast's action (Undo) as `.toast .btn` */
.toast .tclose{position:relative;display:grid;place-items:center;flex:none;width:24px;height:24px;margin-left:-10px;padding:0;border:0;border-radius:var(--r-ctl);background:none;color:var(--on-inverse);cursor:pointer;transition:background-color var(--dur-hover) ease}
@media (hover:hover){.toast .tclose:hover{background:color-mix(in srgb,var(--on-inverse) 24%,transparent)}}
.toast .tclose:active{background:color-mix(in srgb,var(--on-inverse) 32%,transparent);transition-duration:var(--dur-press)}
.toast .tclose .i{width:14px;height:14px}
.is-phone .toast .tclose::after{content:"";position:absolute;inset:-10px}

/* ---------- 6 · Phone ≤ 800 (02 · u00U411l8W): top band, tab bar, 44 px targets, phone metrics ---------- */
.is-phone #page{padding:112px 12px 118px}
.is-phone .top{position:fixed;height:100px;padding:14px 16px 0}
.is-phone .top .r1{display:flex;align-items:center;gap:2px;height:40px}
.is-phone .top h1{margin-right:auto;min-width:0;font:var(--t-title);letter-spacing:-.015em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.is-phone .top .r2{display:flex;align-items:center;gap:12px;margin-top:6px}
.is-phone .top .r2.end{justify-content:flex-end}
.is-phone .top .bg{flex:1;display:flex;min-width:0}
.is-phone .top .bg .seg{flex:1}
.is-phone .top .btn.ic{width:36px;padding:0;background:none;box-shadow:none}
.is-phone .top .bell .i{width:20px;height:20px}
.is-phone .top .back{margin-right:6px}
/* generic phone metrics carry only the component's own specificity (:where) — the kit's own variants
   (.tab .i, .fab .i, .btn.pl, .btn.pri, .seg.icons …) keep winning, exactly as in 02 */
:where(.is-phone) .credits{display:inline;height:auto;padding:0;font:500 .8125rem/1 var(--font-ui);white-space:nowrap}
:where(.is-phone) .i{width:18px;height:18px;stroke-width:1.667}
:where(.is-phone) .btn{padding:0 12px;background:var(--g3);font-size:.9375rem}
:where(.is-phone) .btn .i{width:16px;height:16px;stroke-width:1.875}
:where(.is-phone) .btn.pl{padding:0 6px}
:where(.is-phone) .btn.pl .i{width:14px;height:14px;stroke-width:2.2}
:where(.is-phone) .seg{display:flex}
:where(.is-phone) .seg>button{flex:1;height:28px;font-size:.875rem}
:where(.is-phone) .seg.icons{display:inline-flex;height:28px}
:where(.is-phone) .seg.icons>button{flex:none;width:32px;height:24px}
:where(.is-phone) .st::before{width:7px;height:7px}
:where(.is-phone) .badge{top:0;right:1px}
:where(.is-phone) .av{width:30px;height:30px;font-size:.75rem}
:where(.is-phone) .av.l{width:36px;height:36px;font-size:.8125rem}
:where(.is-phone) .v{letter-spacing:-.012em}
:where(.is-phone) .logo{width:14px;height:14px;border-radius:3px}
:where(.is-phone) .sh{gap:8px;min-height:32px}
:where(.is-phone) .sh h2{letter-spacing:-.01em}
:where(.is-phone) .sh .ct{font-size:.9375rem}
/* equal tabs, except a label wider than its share keeps its own width plus 4 px each side, so "Requests" and "Calendar"
   never run together at 360–390 px (the agent's bar is narrowed by the Post button) */
.tabs{grid-template-columns:repeat(var(--tabs,5),minmax(max-content,1fr))}
.tab,button.tab{padding:0 4px}
button.tab{border:0;background:none}
.tab{transition:background-color var(--dur-hover) ease,color var(--dur-hover) ease}
.tab:active,.fab:active{transform:scale(.97);transition:transform var(--dur-press) var(--ease-out)}
.is-phone .toast-region{left:0;bottom:calc(22px + 62px + 12px)}
.is-phone .fld{position:relative}
.is-phone .fld::after{content:"";position:absolute;inset:-6px -2px;pointer-events:none}
/* FIELD-HIT: the ::after above cannot take a tap (pointer-events:none), so the control itself is the 44 px target — the input grows to --hit and
   is pulled back by half the difference, the field stays 32 */
.is-phone .fld{--fh:var(--h-dense)}.is-phone .fld.l,.is-phone .fld.f32{--fh:var(--h-ctl)}
.is-phone .fld input,.is-phone .fld select{height:var(--hit);margin-block:calc((var(--fh) - var(--hit)) / 2)}
.is-phone .btn.ic::after{inset:-6px}
/* PHONE-INPUT: 16 px on every phone field, so iOS never zooms on focus (the kit's 15 px body would) — pages stop patching it */
.is-phone :is(input,select,textarea){font-size:1rem}
/* TK-HIT: filter tokens (24 tall) get the invisible 44 hit area, as .fld and .btn do; the family rail's links likewise */
.is-phone .fbar{flex-wrap:wrap}
.is-phone .fbar>.fld{flex:1 1 100%}
.is-phone .tg,.is-phone .clr{position:relative}
.is-phone .tg::after{content:"";position:absolute;inset:-8px 0}
.is-phone .clr::after{content:"";position:absolute;inset:-14px}
.is-phone .tk{position:relative}
.is-phone .tk::after{content:"";position:absolute;inset:-10px -2px}
:where(.is-phone) .seg.rail>a{position:relative}
:where(.is-phone) .seg.rail>a::after{content:"";position:absolute;inset:-10px 1px}
/* 44 px phone hit areas drawn on 2.03 / 2.14: segment buttons grow 8 px up and down, icon segments to 44 × 44,
   the band's credits link to a full-height target — all invisible */
:where(.is-phone) .seg>button::after{content:"";position:absolute;inset:-8px 1px}
:where(.is-phone) .seg.icons>button::after{inset:-10px -6px}
/* the shared Me | Team switch (app/scope.js): its short segments reach 44 px wide too */
:where(.is-phone) .seg.scope>button::after{inset:-8px -2px}
/* name links (app/people.js a.lnk, 18 px of text) get the same invisible 44 px hit area as .btn and .tk */
:where(.is-phone) a.lnk{position:relative}
:where(.is-phone) a.lnk::after{content:"";position:absolute;inset:-13px -2px}
/* LEDGER-HIT: the ledger bar's toolbar buttons and links (32–36), filter pills (28–32), segment buttons (28–32) and search
   (36) get the same invisible 44 px hit area; the search input grows to --hit inside its box, which keeps its height */
:where(.is-phone) .ledger :is(.lg-tb:not(select),.lg-pill,.lg-seg>button){position:relative}
:where(.is-phone) .ledger :is(.lg-tb:not(select),.lg-pill)::after{content:"";position:absolute;inset:-8px -2px}
.is-phone .ledger .lg-seg>button::after{content:"";position:absolute;inset:-8px -5px}
.is-phone .ledger .lg-seg>button.ic::after{inset:-8px -7px}
.is-phone .ledger .lg-search input{height:var(--hit)}
/* a native select takes no pseudo-element: on a phone the ledger's select is drawn at the 44 px it needs */
.is-phone .ledger select.lg-tb{height:var(--hit)}
/* text buttons (.btn.pl, 24 tall) and the phone band's icon buttons (28–32 wide) reach 44 in both directions */
.is-phone .btn.pl::after{inset:-10px -2px}
.is-phone .top .btn.ic::after{inset:-6px -8px}
/* page tabs draw their selected underline with ::after, so on a phone the tab itself is the 44 px target */
.is-phone .ptabs>button{height:var(--hit)}
:where(.is-phone) .top .credits{position:relative}
:where(.is-phone) .top .credits::after{content:"";position:absolute;inset:-16px -6px}
.is-phone .menu [role^=menuitem],.is-phone .menu [role=option]{height:var(--hit);font-size:.9375rem}
.is-phone .menu [role=option]:has(small){height:auto;min-height:var(--hit)}

/* SKIP: the shell's first Tab stop (app/shell.js) — out of sight until it has keyboard focus, then a button over the band's
   top-left; pages without the shell (sign-in) have no navigation to skip */
.skip:not(:focus){position:absolute!important;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip:focus{position:fixed;top:12px;left:12px;z-index:80}
.no-shell .skip{display:none}

/* A10: account creation is off in production (live); the sign-in page's "Create your account" line is drawn by the page, so the live
   document hides it here until pages/access reads ctx.signupOpen (app/main.js). Fixture and lab keep it. */
html[data-mode=live] .px-alt p:has(>a[href$="registration"]){display:none}

/* ---------- 7 · Adaptivity (additions for app parts the kit does not draw) ---------- */
@media (prefers-reduced-transparency:reduce){dialog::backdrop{-webkit-backdrop-filter:none;backdrop-filter:none}.toast-region .toast:not(.bad){background:var(--toast)}}
@media (prefers-contrast:more){.fld{box-shadow:inset 0 0 0 1px var(--edge-hc)}.menu hr,.more hr{background:var(--edge-hc)}}
@media (forced-colors:active){dialog{border:1px solid CanvasText}.menu [role^=menuitem]:hover,.menu .is-hl{background:Highlight;color:HighlightText;forced-color-adjust:none}.mrow[aria-current=page]{background:Highlight;color:HighlightText;forced-color-adjust:none}}
/* Forced colours drop box-shadows, and every control edge here is one: fields and search get a CanvasText border;
   every kit button (pop-up selects included), token, the phone Post button and each segmented control a ButtonBorder
   edge — text-style .pl / .bare buttons have no edge in any mode. The selected segment keeps Highlight, also while
   the thumb travels (the thumb itself is hidden). No focus ring (D12). */
@media (forced-colors:active){.fld{border:1px solid CanvasText}
.btn:not(.pl):not(.bare),.tk,.fab,.seg{border:1px solid ButtonBorder}.btn:disabled,.btn[aria-disabled=true]{border-color:GrayText}
.seg{padding:1px}.seg-thumb{display:none}
.seg>button[aria-selected=true],.seg>button[aria-checked=true],.seg.is-travelling>button[aria-pressed=true],.seg.is-travelling>button[aria-selected=true]{background:Highlight;color:HighlightText;forced-color-adjust:none}}
/* 2.04 checkbox · radio · switch in forced colours: the state stays perceivable. Edge ButtonBorder; checked = Highlight
   fill with a HighlightText mark (check, mixed dash, radio dot); switch = ButtonBorder track, ButtonText knob, on =
   Highlight track with a HighlightText knob (also on hover and while pressed); disabled = GrayText at full opacity. */
@media (forced-colors:active){
.chk,.rad{border:1px solid ButtonBorder;background:Canvas}
.chk:checked,.chk:indeterminate,.chk.mixed,.rad:checked,.chk:hover:checked:not(:disabled),.chk:hover:indeterminate:not(:disabled),.rad:hover:checked:not(:disabled),.chk:active:checked:not(:disabled),.rad:active:checked:not(:disabled){background:Highlight;border-color:Highlight;filter:none}
.chk:checked::after{border-color:HighlightText}.chk:indeterminate::after,.chk.mixed::after,.rad:checked::after{background:HighlightText}
.sw i{border:1px solid ButtonBorder;background:Canvas}.sw b{background:ButtonText}
.sw input:checked~i,.sw:hover input:checked:not(:disabled)~i{background:Highlight;border-color:Highlight}.sw input:checked~b{background:HighlightText}
.sw input:active~b,.sw.is-pressing b{background:ButtonText;-webkit-backdrop-filter:none;backdrop-filter:none}
.sw input:checked:active~b,.sw.is-pressing input:checked~b{background:HighlightText}
.chk:disabled,.rad:disabled,.sw input:disabled~i,.sw input:disabled~b{opacity:1}
.chk:disabled,.rad:disabled,.chk:disabled:checked,.chk:disabled:indeterminate,.chk.mixed:disabled,.rad:disabled:checked{background:Canvas;border-color:GrayText}
.chk:disabled:checked::after{border-color:GrayText}.chk:disabled:indeterminate::after,.chk.mixed:disabled::after,.rad:disabled:checked::after{background:GrayText}
.sw input:disabled~i,.sw input:disabled:checked~i,.sw:hover input:disabled:checked~i{background:Canvas;border-color:GrayText}.sw input:disabled~b,.sw input:disabled:checked~b{background:GrayText}}
@media (prefers-reduced-motion:reduce){:is(.stp,.vst)>*::after{transition:none}.showall .i{transition:none}.seg-thumb{display:none}.i.spin{animation:none}.tk:active,.tab:active,.fab:active{transform:none}}

/* Account & access additions — 2.03 tabs: a selected tab (aria-selected) takes Highlight in forced colours, exactly
   as the pressed segment already does (kit adaptivity); the Account section tabs are the first tablist on .seg. */
@media (forced-colors:active){.seg>button[role=tab][aria-selected=true]{background:Highlight;color:HighlightText;forced-color-adjust:none}}

/* ---------- 8 · Production gates (D49, app/gates.js): payment issue · NIPR identity · Discord · low credits · upgrade ·
   override alerts · idle lock — kit dialog, float glass and the inline-message pattern, nothing new in the language ---------- */
dialog.gate-opaque::backdrop{background:var(--sheet);-webkit-backdrop-filter:blur(40px) saturate(1.1);backdrop-filter:blur(40px) saturate(1.1)}   /* the Discord gate hides the page behind it */
dialog.gate-nipr,dialog.gate-upgrade{width:min(560px,calc(100% - 24px))}
dialog.gate-upgrade .gate-signout{order:-1;margin:0 auto 0 -10px;padding:0 10px;color:var(--ink-2)}   /* left of the plan actions in the row; after them in the DOM, so they stay first in the tab order */
.is-phone dialog.gate-upgrade .gate-signout{margin-left:-12px;padding:0 12px}
.gate-form{display:grid;gap:14px;max-height:min(56vh,520px);margin-top:12px;overflow:auto}
.gate-sec h3{margin-bottom:8px;font:var(--t-strong)}
.gate-grid{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px 12px}
.is-phone .gate-grid{grid-template-columns:minmax(0,1fr)}
.gate-kv{margin-top:12px}
.consequence .typed{margin-top:14px}
.gate-plans{display:grid;gap:8px;margin-top:12px}
.gate-plan{padding:10px 12px;border-radius:var(--r-ctl);box-shadow:inset 0 0 0 1px var(--hair-2)}
.gate-plan p{display:flex;align-items:baseline;gap:8px}
.gate-plan p .num{margin-left:auto;font:var(--t-small);color:var(--ink-2)}
.gate-plan ul{display:grid;gap:4px;margin-top:6px;list-style:none;font:var(--t-small)}
.gate-plan li{display:flex;align-items:center;gap:6px}
.gate-plan li .i{width:14px;height:14px;color:var(--accent)}
.gbanner{position:fixed;z-index:4;left:calc(var(--w-side) + 12px);right:12px;top:calc(var(--h-band) + 8px);display:flex;align-items:center;gap:10px;min-height:40px;padding:6px 6px 6px 12px;border-radius:var(--r-ctl)}
.gbanner>.i{flex:none}
.gbanner.ntc>.i{color:var(--ntc)}
.gbanner.crt>.i{color:var(--crt)}
.gbanner.ws>.i{color:var(--accent)}   /* the workspace banner (app/banner.js tone 'ws'): quiet, the accent glyph only */
.gbanner span{flex:1;min-width:0;font:var(--t-body);color:var(--ink-1)}
html.has-gbanner #page{padding-top:112px}
.is-phone .gbanner{left:12px;right:12px;top:108px}
html.is-phone.has-gbanner #page{padding-top:160px}
html.no-shell .gbanner,html.no-shell .oalerts{display:none}
.oalerts{position:fixed;z-index:31;right:12px;top:calc(var(--h-band) + 8px);width:min(420px,calc(100vw - 24px));display:grid;gap:8px}
.oalert{padding:12px 12px 12px 14px;border-radius:var(--r-menu)}
.oalert header{display:flex;align-items:flex-start;gap:10px}
.oalert header>.i{flex:none;margin-top:2px;color:var(--crt)}
.oalert header div{flex:1;display:grid;gap:2px;min-width:0}
.oalert header b{font:var(--t-strong)}
.oalert header small{font:var(--t-small);color:var(--ink-2)}
.oalert p{margin-top:6px;padding-left:24px;font:var(--t-body)}
.idle-left{margin-top:10px;font:var(--t-strong);font-variant-numeric:tabular-nums}
@media (forced-colors:active){.gbanner,.oalert{border:1px solid CanvasText}}

/* Person link — a client's or agent's name that opens their record (app/people.js). */
a.lnk{color:var(--accent-ink);text-decoration:none}
@media (hover:hover){a.lnk:hover{text-decoration:underline;text-underline-offset:2px}}

/* 9 Stage track — contracting-ux §7 (Doop canvas QTXGr9r-_W, frame 10 Track system). One component for every request row:
   .trk = four rounded bars + an outcome dot, beside the stage word (.stgc); .trkl = the same as five labelled bars with a
   date under each (the record); .trkl.v = the vertical list (phone record). One colour per track: accent in progress ·
   amber (.rq) Requirement / Reply sent · green (.ok) Appointed / Approved · red (.no) Declined · grey (.wd) Withdrawn.
   .s2 = the two-stop track of an approval-only request (Admin review · outcome). Markup comes from app/stage.js.
   Bars are 14 px with a 4 px gap (4 × 14 + 6 + 4 × 4 = 78, the design's width) because the spacing scale has no 3 px.
   The current-bar halo is the --sh-cur token (a ring in the track's own tint); the stage word cell is .stgc because
   Carrier Requests' own page CSS already uses .stg for the track itself. */
:root{--rq:#f5a623;--rq-wash:rgb(245 166 35/.24);--rq-ink:#8a5a00}
.trk,.trkl{--c:var(--accent);--h:var(--accent-tint);--sh-cur:0 0 0 2px var(--h)}
.trk.rq,.trkl.rq{--c:var(--rq);--h:var(--rq-wash)}
.trk.ok,.trkl.ok{--c:var(--pos)}.trk.no,.trkl.no{--c:var(--crt)}.trk.wd,.trkl.wd{--c:var(--neu)}
.trk{display:inline-grid;grid-template-columns:repeat(4,14px) 6px;gap:4px;align-items:center;height:14px;vertical-align:middle}
.trk.s2{grid-template-columns:68px 6px}
.trk i{display:block;height:4px;border-radius:2px;background:var(--track)}
.trk i:last-child{width:6px;height:6px;border-radius:50%}
.trk i.on{background:var(--c)}
.trk i.cur{background:var(--c);box-shadow:var(--sh-cur)}
.stgc{display:grid;gap:4px;min-width:0}
.stgc b{font:var(--t-strong)}
.stgc b.rq{color:var(--rq-ink)}.stgc b.ok{color:var(--pos-ink)}.stgc b.no{color:var(--crt-ink)}.stgc b.wd{color:var(--ink-2)}
.trkl{list-style:none;margin:0;padding:0;display:grid;grid-template-columns:repeat(5,1fr);gap:4px}
.trkl.s2{grid-template-columns:repeat(2,1fr)}
.trkl li{display:grid;grid-template-rows:4px 2.6em auto;gap:6px 0;align-content:start;padding-right:4px;font:var(--t-label);color:var(--ink-2)}
.trkl li::before{content:"";display:block;height:4px;border-radius:2px;background:var(--track)}
.trkl li.on::before{background:var(--c)}
.trkl li.cur::before{background:var(--c);box-shadow:var(--sh-cur)}
.trkl li.on,.trkl li.cur{color:var(--ink-1)}
.trkl li.cur{font-weight:600}
.trkl.rq li.cur{color:var(--rq-ink)}
.trkl.ok li:last-child{color:var(--pos-ink);font-weight:600}
.trkl.no li:last-child{color:var(--crt-ink);font-weight:600}
.trkl.wd li:last-child{color:var(--ink-2);font-weight:600}
.trkl li span{font:var(--t-small);color:var(--ink-2);font-variant-numeric:tabular-nums;font-weight:400}
.trkl.v{grid-template-columns:1fr;gap:4px}
.trkl.v li{grid-template-columns:4px minmax(0,1fr) auto;grid-template-rows:auto;gap:0 12px;align-items:center;min-height:36px;padding:0;font:var(--t-body)}
.trkl.v li::before{height:28px;width:4px}
.trkl.v li.cur,.trkl.v li:last-child{font-weight:600}
.trkl.v li span{justify-self:end;text-align:right;white-space:nowrap}
@media (forced-colors:active){.trk i,.trkl li::before{forced-color-adjust:none}}

/* 10 Annuity components — annuity-ux §7 / §8 (Doop canvas Jiyq9KrCJZ, frame 10 Case · strategy · request system), reproduced
   from the exported frames with kit tokens only. Markup comes from app/annuity.js (tracks) and the annuity pages.
   .trk.s3 / .trkl.s3 = the case track (New · In process · Submitted · Outcome: three bars + dot); .trk.s4 / .trkl.s4 = a strategy's
   (Exploring · Illustrated · Applied · Submitted · Outcome: four bars + dot). Colour classes sit on the container only.
   .rs = a request's status word (Open · .w waits on the viewer · .d Done); .rqr = a request row (.w = amber wash).
   .stc = a strategy card (.s1 type · logo · carrier · tags, .s2 product · premium · rate, .s3 track · status · facts) in a .stl list.
   .fg / .fl = files under a category word; .chps / .chp = the list's strategy chips; .tag.sg = a strategy tag; .tag.best = "Top in TX".
   Off-scale design values, moved to the nearest scale value: strategy card radius 10 -> --r-card (12) and its row gap 7 -> 8,
   the card dot separator margin 7 -> 6, the request row gap 3 -> 4. The washes below are token definitions (the frames hard-code them). */
:root{--rq-row:rgb(245 166 35/.09);--rq-row-edge:rgb(245 166 35/.4);--stc-bg:rgb(255 255 255/.5);--chp-bg:rgb(16 30 42/.055)}
.trk.s3{grid-template-columns:repeat(3,21px) 6px}
.trkl.s3{grid-template-columns:repeat(4,1fr)}
.trkl.s3 li,.trkl.s4 li{grid-template-rows:4px auto auto}
.trk.s4{grid-template-columns:repeat(4,15px) 6px}
.trkl.s4{grid-template-columns:repeat(5,1fr)}
.rqr .rs{font:var(--t-strong);color:var(--ink-1);white-space:nowrap}
.rqr .rs.w{color:var(--rq-ink)}
.rqr .rs.d{color:var(--ink-2);font-weight:500}
.tag.sg{background:var(--neu-wash);color:var(--neu-ink);font-weight:500}
.tag.best{background:var(--pos-wash);color:var(--pos-ink)}
.rql{list-style:none;display:grid;gap:2px}
.rqr{display:grid;gap:4px;padding:8px 10px;margin:0 -10px;border-radius:var(--r-ctl);transition:background-color var(--dur-hover) ease}
.rqr .r1{display:flex;align-items:center;gap:8px;min-width:0}
.rqr .r1 b{font:var(--t-strong)}
.rqr .r1 .rs{margin-left:auto}
.rqr .rm{font:var(--t-small);color:var(--ink-2)}
.rqr.w{background:var(--rq-row);box-shadow:inset 0 0 0 .5px var(--rq-row-edge)}
.stl{display:grid;gap:8px}
.stl.two{grid-template-columns:1fr 1fr}
.stc{display:grid;gap:8px;align-content:start;padding:10px 6px 12px 14px;border-radius:var(--r-card);background:var(--stc-bg);box-shadow:inset 0 0 0 .5px var(--hair-2)}
.stc .s1{display:flex;align-items:center;gap:8px;min-height:24px;min-width:0}
.stc .s1 b{font:var(--t-strong)}
.stc .s1 .cr{font:500 13px/1.35 var(--font-ui)}
.stc .s1 .mn{margin-left:auto;width:24px;height:24px}
.stc .s2{display:flex;font:var(--t-body);color:var(--ink-1);white-space:nowrap}
.stc .s2>*+*::before{content:"·";margin:0 6px;color:var(--ink-2)}
.stc .s3{display:flex;align-items:center;gap:8px;padding-right:8px}
.stc .s3 b{font:var(--t-strong)}
.stc .s3 b.ok{color:var(--pos-ink)}.stc .s3 b.no{color:var(--crt-ink)}.stc .s3 b.wd{color:var(--ink-2)}
.stc .s3 .fc{margin-left:auto;font:var(--t-small);color:var(--ink-2)}
.fg+.fg{margin-top:10px}
.fg h4{font:var(--t-small);color:var(--ink-2);margin-bottom:2px}
.fl{list-style:none;display:grid}
.fl li{display:flex;align-items:center;gap:8px;height:36px;border-top:1px solid var(--hair)}
.fl li:first-child{border-top:0}
.fl li .i{color:var(--glyph)}
.fl .fn{flex:1;min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;font:500 13px/1.35 var(--font-ui)}
.fl .fm{font:var(--t-small);color:var(--ink-2);white-space:nowrap}
.fl .btn.ic{width:24px;height:24px}
.chps{display:flex;align-items:center;gap:4px;min-width:0}
.chp{display:inline-flex;align-items:center;height:22px;padding:0 6px;border-radius:var(--r-tag);background:var(--chp-bg);font:500 12px/1 var(--font-ui);color:var(--ink-1);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}
.chp.more{flex:none;color:var(--ink-2)}
.nil{color:var(--ink-2)}
@media (hover:hover) and (pointer:fine){.rqr:not(.w):hover{background:var(--accent-wash)}}
@media (forced-colors:active){.stc,.rqr.w{border:1px solid CanvasText}}

/* Keep existing boot failure presentation while recovered pages adopt shared state blocks. */
.boot-error{display:grid;justify-items:start;gap:12px;max-width:420px;padding:18px 24px 20px;border-radius:var(--r-card)}

/* Desktop shell without a top bar (Oct 2026 · Doop yH80Kb58OY frame 01): the band is a chrome-less page head that scrolls with the page. */
html:not(.is-phone) .band.g1{background:none;-webkit-backdrop-filter:none;backdrop-filter:none;box-shadow:none}
html:not(.is-phone) body.app .band{position:absolute;top:8px;padding:0 calc(var(--gutter) + 12px) 0 calc(var(--gutter) + 4px)}
html:not(.is-phone) .band h1{font:600 26px/1.2 var(--font-ui)}

/* NIPR verification as a notice (Oct 2026 · Doop yH80Kb58OY frames 02–05): the bell's pinned action row, the Contracting
   lock, and the stepped verification sheet (app/gates.js niprSheet). */
.bell-menu .act{min-height:52px;align-items:flex-start;padding-top:8px;padding-bottom:8px;margin:2px 0 4px;border-radius:var(--r-ctl);background:var(--accent-wash);box-shadow:inset 0 0 0 .5px rgb(29 106 208/.25)}
.bell-menu .act>.i{color:var(--accent);margin-top:1px}
.bell-menu .act .ml{display:grid;gap:2px;font-weight:600;white-space:normal}
.bell-menu .act .sub{font:var(--t-small);color:var(--ink-2);font-weight:400}
.bell-menu .act:focus-visible .sub,.bell-menu .act:hover .sub{color:inherit}
dialog.nipr-sheet{width:min(560px,calc(100% - 24px))}
.nipr-sheet .sheet-body{display:grid;gap:16px;align-content:start}
.nipr-sheet .nv-why{display:flex;gap:10px;padding:11px 12px;border-radius:var(--r-card);background:var(--accent-wash);box-shadow:inset 0 0 0 .5px rgb(29 106 208/.18);font:var(--t-small);color:var(--ink-2)}
.nipr-sheet .nv-why .i{color:var(--accent);flex:none;margin-top:1px}
.nipr-sheet .nv-steps{list-style:none;display:flex;gap:4px;padding:0;margin:0}
.nipr-sheet .nv-steps li{flex:1;display:flex;align-items:center;gap:6px;min-width:0;padding-top:8px;border-top:3px solid var(--track);font:500 12px/1.3 var(--font-ui);color:var(--ink-2)}
.nipr-sheet .nv-steps li>span:last-child{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.nipr-sheet .nv-steps li.done,.nipr-sheet .nv-steps li.cur{border-top-color:var(--accent);color:var(--ink-1)}
.nipr-sheet .nv-steps li.cur{font-weight:600}
.nipr-sheet .nv-steps .d{display:grid;place-items:center;flex:none;width:20px;height:20px;border-radius:50%;font:600 11px/1 var(--font-ui);background:#fff;box-shadow:inset 0 0 0 1.25px var(--hair-2);color:var(--glyph)}
.nipr-sheet .nv-steps .done .d{color:var(--accent);box-shadow:inset 0 0 0 1.5px var(--accent)}
.nipr-sheet .nv-steps .done .d .i{width:12px;height:12px}
.nipr-sheet .nv-steps .cur .d{background:var(--accent);color:var(--on-accent);box-shadow:0 0 0 3px var(--accent-tint)}
.nipr-sheet .nv-k{font:var(--t-label);color:var(--accent-ink);margin:0 0 4px}
.nipr-sheet h3{font:600 20px/1.25 var(--font-ui);letter-spacing:-.01em;margin:0}
.nipr-sheet .nv-lead{font:var(--t-body);color:var(--ink-2);margin:4px 0 0}
.nipr-sheet .nv-grid{display:grid;grid-template-columns:1fr 1fr;gap:14px;margin-top:16px}
.nipr-sheet .nv-wide{grid-column:1/-1}
.nipr-sheet .nv-help{font:var(--t-small);color:var(--glyph);margin:6px 0 0}
.nipr-sheet .nv-err{margin:0;padding:9px 12px;border-radius:var(--r-ctl);background:var(--crt-wash);color:var(--crt-ink);font:500 12.5px/1.4 var(--font-ui)}
.nipr-sheet .nv-card{margin-top:12px;padding:10px 14px 12px;border-radius:var(--r-card);background:rgb(255 255 255/.8);box-shadow:var(--sh-3)}
.nipr-sheet .nv-ch{display:flex;align-items:center;justify-content:space-between;font:var(--t-label);color:var(--glyph)}
.nipr-sheet .nv-ch .btn{height:var(--h-mini);color:var(--accent-ink)}
.nipr-sheet .nv-card dl{display:grid;grid-template-columns:repeat(2,1fr);gap:8px 14px;margin:6px 0 0}
.nipr-sheet .nv-card dt{font:var(--t-small);color:var(--glyph)}
.nipr-sheet .nv-card dd{margin:1px 0 0;font:500 13.5px/1.35 var(--font-ui);font-variant-numeric:tabular-nums}
.nipr-sheet .nv-consent{display:flex;gap:10px;align-items:flex-start;margin-top:14px;font:var(--t-body);color:var(--ink-2)}
.nipr-sheet .nv-consent input{width:18px;height:18px;margin:1px 0 0;accent-color:var(--accent);flex:none}
.nipr-sheet .nv-done{display:grid;justify-items:start;gap:4px;padding-top:12px}
.nipr-sheet .nv-hero{display:grid;place-items:center;width:52px;height:52px;margin-bottom:12px;border-radius:14px;background:var(--pos-wash);color:var(--pos-ink);box-shadow:0 0 0 6px rgb(47 138 102/.06)}
.nipr-sheet .nv-hero .i{width:26px;height:26px}
.nipr-sheet footer{display:flex;align-items:center;gap:8px}
.nipr-sheet footer .sp{flex:1}
.nipr-sheet footer .btn .i{width:15px;height:15px}
.is-phone .nipr-sheet .nv-grid{grid-template-columns:1fr}

/* Local development only — the Role switcher capsule (app/local-roles.js, serve.mjs --local). */
.local-role{position:fixed;z-index:70;right:12px;bottom:68px;gap:8px;height:32px;padding:0 12px 0 6px;border-radius:var(--r-pill);background:var(--inverse);color:var(--on-inverse);box-shadow:var(--sh-float);font:600 12px/1 var(--font-ui)}
.local-role .lr-k{padding:4px 7px;border-radius:var(--r-pill);background:rgb(255 255 255/.14);color:var(--inverse-link);font:700 10px/1 var(--font-ui);letter-spacing:.04em;text-transform:uppercase}
@media (hover:hover){.local-role:hover{background:color-mix(in srgb,var(--inverse) 88%,#fff)}}
.local-role[aria-expanded=true]{background:var(--inverse);color:var(--on-inverse)}
.local-role-menu .ml small.sub{display:block;font:var(--t-small);color:var(--ink-2)}

/* ---------- Notifications as LumaDial's NotificationBell (luma-dialer, Oct 2026): the panel and the expanded sheet. ---------- */
/* the bell's panel, as LumaDial's (header · unread pill · 40px rows with a bordered glyph box · caught-up state) */
.bell-menu{padding:0 0 4px;border-radius:8px}
.bell-menu .bm-h{display:flex;align-items:center;gap:8px;height:40px;padding:0 12px;margin-bottom:4px;border-bottom:1px solid #e2e2e2}
.bell-menu .bm-h h3{font:500 12px/1 var(--font-ui);color:#171717}
.bell-menu .bm-pill{display:inline-flex;align-items:center;gap:5px;height:18px;padding:0 6px;border-radius:4px;box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent);font:500 11px/1 var(--font-ui);color:#171717}
.bell-menu .bm-pill i{width:6px;height:6px;border-radius:50%;background:var(--accent)}
.bell-menu .bm-pill b{font:500 11px/1 var(--font-mono);font-variant-numeric:tabular-nums}
.bell-menu .bm-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:200px;padding:0 28px;text-align:center}
.bell-menu .bm-ic{display:flex;align-items:center;justify-content:center;width:36px;height:36px;margin-bottom:12px;border-radius:8px;box-shadow:inset 0 0 0 1px #e2e2e2;color:var(--accent)}
.bell-menu .bm-ic .i{width:17px;height:17px;stroke-width:1.75}
.bell-menu .bm-empty p{font:500 12px/1.4 var(--font-ui);color:#171717}
.bell-menu .bm-empty p.s{margin-top:4px;font-weight:400;line-height:17px;color:#6b6b6b}
.bell-menu [role=menuitem]{gap:10px;min-height:40px;margin:0 4px;padding:0 8px;border-radius:5px;font:500 12px/16px var(--font-ui);color:#171717}
.bell-menu [role=menuitem]>.i{box-sizing:content-box;width:13px;height:13px;padding:5px;border-radius:5px;box-shadow:inset 0 0 0 1px #e2e2e2;stroke-width:2;color:#6b6b6b}
.bell-menu [role=menuitem].act>.i{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent);color:var(--accent)}
.bell-menu [role=menuitem] small.sub{font:400 11px/15px var(--font-ui);color:#6b6b6b}
.bell-menu .msec,.bell-menu .mlabel{padding:8px 12px 4px;font:500 11px/1 var(--font-ui);text-transform:none;letter-spacing:0;color:#6b6b6b}
.bell-menu .bm-h{padding-right:6px}
.bell-menu .bm-sp{flex:1}
.bell-menu .bm-x{display:inline-flex;align-items:center;justify-content:center;width:24px;height:24px;padding:0;border:0;border-radius:5px;background:none;color:#6b6b6b;cursor:pointer}
.bell-menu .bm-x .i{width:13px;height:13px;stroke-width:2}
@media (hover:hover){.bell-menu .bm-x:hover{background:#f4f4f4;color:#171717}}
.bm-empty .bm-all{display:inline-flex;align-items:center;gap:6px;margin-top:12px;padding:0;border:0;background:none;font:500 12px/1 var(--font-ui);color:var(--accent);cursor:pointer}
.bm-empty .bm-all .i{width:12px;height:12px;stroke-width:2.2}
@media (hover:hover){.bm-empty .bm-all:hover{color:color-mix(in srgb,var(--accent) 80%,#fff)}}
/* the expanded Notifications sheet */
.notif-sheet .sheet-body{padding:8px 12px 16px}
.notif-sheet .ns-sec{padding:12px 4px 6px;font:500 11px/1 var(--font-ui);color:#6b6b6b}
.notif-sheet .ns-row{display:flex;align-items:center;gap:10px;width:100%;min-height:48px;padding:6px 8px;border:0;border-radius:6px;background:none;text-align:left;color:#171717;cursor:pointer}
@media (hover:hover){.notif-sheet .ns-row:hover{background:#f4f4f4}}
.notif-sheet .ns-ic{display:flex;flex:none;align-items:center;justify-content:center;width:28px;height:28px;border-radius:6px;box-shadow:inset 0 0 0 1px #e2e2e2;color:#6b6b6b}
.notif-sheet .ns-ic .i{width:14px;height:14px}
.notif-sheet .ns-row.act .ns-ic{box-shadow:inset 0 0 0 1px color-mix(in srgb,var(--accent) 45%,transparent);color:var(--accent)}
.notif-sheet .ns-t{flex:1;min-width:0;display:grid;gap:2px}
.notif-sheet .ns-t b{font:500 13px/18px var(--font-ui)}
.notif-sheet .ns-t span{font:400 12px/16px var(--font-ui);color:#6b6b6b}
.notif-sheet .ns-row>.i{flex:none;width:14px;height:14px;color:#8f8f8f}
.notif-sheet .bm-empty{display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:320px;text-align:center}
.notif-sheet .bm-ic{display:flex;align-items:center;justify-content:center;width:36px;height:36px;margin-bottom:12px;border-radius:8px;box-shadow:inset 0 0 0 1px #e2e2e2;color:var(--accent)}
.notif-sheet .bm-empty p{font:500 12px/1.4 var(--font-ui);color:#171717}
.notif-sheet .bm-empty p.s{margin-top:4px;font-weight:400;color:#6b6b6b}

/* ---------- Desktop top bar as LumaDial's TopBar (luma-dialer TopBar.tsx, Oct 2026): a 56px white bar with a hairline
   bottom rule, the page title at 14/500, the page's groups, then Post a deal (in Prep work's place) and the
   wallet-style credits chip. No search, no playlist line. ---------- */
html:not(.is-phone){--h-band:56px}
html:not(.is-phone) .band.g1{background:var(--g1);box-shadow:inset 0 -1px 0 rgb(16 30 42/.1)}   /* same surface as the side menu */
html:not(.is-phone) body.app .band{position:fixed;top:0;left:var(--w-side);right:0;height:56px;gap:10px;padding:0 20px}
html:not(.is-phone) .band h1{margin-right:auto;font:500 14px/20px var(--font-ui);letter-spacing:0;color:#171717}
html:not(.is-phone) .band .bt h1{margin-right:0}
html:not(.is-phone) .band .bt{align-items:center}
html:not(.is-phone) .band .host{display:flex;flex:none;align-items:center;gap:10px}
html:not(.is-phone) body:has(:is(.band,.side) .tb-post) [data-page="book"] .ldbar .ld-add{display:none}   /* the side menu carries Post a deal */

/* ---------- Top bar Search (LumaDial SearchTrigger + PaletteShell + SearchPalette, Oct 2026) ---------- */
.band .tb-search{display:inline-flex;flex:none;align-items:center;gap:8px;height:32px;padding:0 10px;border:1px solid transparent;border-radius:6px;background:none;color:#6b6b6b;font:500 12px/1 var(--font-ui);cursor:pointer}
.band .tb-search .i{width:15px;height:15px;stroke-width:2}
.band .tb-search kbd{padding:0 5px;border-radius:4px;box-shadow:inset 0 0 0 1px #e2e2e2;font:400 10px/14px var(--font-mono);color:#8f8f8f}
@media (hover:hover){.band .tb-search:hover{border-color:#e2e2e2;background:#f4f4f4;color:#171717}}
.band .tb-search[aria-expanded=true]{border-color:#e2e2e2;background:#f4f4f4;color:#171717}
/* the page title follows Search across a hairline, as LumaDial's page slot */
html:not(.is-phone) .band .tb-search+h1,html:not(.is-phone) .band .tb-search+.bt{padding-left:12px;box-shadow:inset 1px 0 0 #e2e2e2}
.sp-root{position:fixed;inset:0;z-index:80}
/* Search owns its native top layer, preserving ordinary dialogs and their drafts underneath. */
dialog.sp-root{margin:0;border:0;padding:0;width:100vw;height:100dvh;max-width:none;max-height:none;background:transparent;color:inherit;overflow:hidden}
dialog.sp-root::backdrop{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
.sp-scrim{position:absolute;inset:0;background:rgb(0 0 0/.5);-webkit-backdrop-filter:blur(8px);backdrop-filter:blur(8px);animation:sp-in .15s ease-out both}
.sp-wrap{position:absolute;left:0;right:0;top:max(8px,12vh);display:flex;justify-content:center;padding:0 8px;pointer-events:none}
/* the search panel only: plain .sp is also the footer spacer class used across sheets */
.sp-wrap>.sp{pointer-events:auto;display:flex;flex-direction:column;width:100%;max-width:640px;height:min(640px,calc(100dvh - 2 * max(8px,12vh)));overflow:hidden;border-radius:8px;background:#fff;box-shadow:0 0 0 1px #e2e2e2,0 25px 50px -12px rgb(0 0 0/.25);color:#171717;font-family:var(--font-ui);animation:sp-drop .16s cubic-bezier(.22,1,.36,1) both}
@keyframes sp-in{from{opacity:0}}
@keyframes sp-drop{from{opacity:0;transform:translateY(-4px) scale(.98)}}
@media (prefers-reduced-motion:reduce){.sp-wrap>.sp,.sp-scrim{animation:none}}
.sp-q{flex:none;display:flex;align-items:center;gap:10px;height:52px;padding:0 14px;border-bottom:1px solid #e2e2e2}
.sp-q>.i{width:17px;height:17px;color:#6b6b6b}
.sp-q input{flex:1;min-width:0;height:100%;border:0;outline:0;background:none;font:400 14px/1 var(--font-ui);color:#171717}
.sp-q input::placeholder{color:#8f8f8f}
.sp-kbd{flex:none;padding:0 5px;border:0;border-radius:4px;background:none;box-shadow:inset 0 0 0 1px #e2e2e2;font:400 10px/14px var(--font-mono);color:#8f8f8f;cursor:pointer}
.sp-scopes{flex:none;display:flex;gap:6px;overflow-x:auto;padding:10px 14px;border-bottom:1px solid #e2e2e2}
.sp-scope{display:inline-flex;flex:none;align-items:center;gap:6px;height:24px;padding:0 10px;border:1px solid #e2e2e2;border-radius:5px;background:none;font:500 11px/1 var(--font-ui);color:#6b6b6b;cursor:pointer}
.sp-scope span{font:400 10px/1 var(--font-mono);color:var(--accent)}
.sp-scope[aria-selected=true]{border-color:color-mix(in srgb,var(--accent) 45%,transparent);background:color-mix(in srgb,var(--accent) 10%,transparent);color:#171717}
@media (hover:hover){.sp-scope:hover{color:#171717}}
.sp-list{flex:1;min-height:0;overflow-y:auto;padding:4px 6px 8px}
.sp-gh{display:flex;align-items:center;gap:6px;min-height:26px;padding:10px 8px 4px;font:500 11px/1 var(--font-ui);color:#8f8f8f}
.sp-gh span{font:400 11px/1 var(--font-mono)}
.sp-it{display:flex;align-items:center;gap:10px;height:34px;padding:0 8px;border-radius:5px;cursor:pointer}
.sp-it.tall{height:52px}
.sp-it[aria-selected=true]{background:#f4f4f4}
.sp-ic,.sp-av{display:flex;flex:none;align-items:center;justify-content:center;width:22px;height:22px}
.sp-ic .i{width:16px;height:16px;color:#6b6b6b}
.sp-av{border-radius:5px;background:#f4f4f4;font:500 9.5px/1 var(--font-ui);color:#6b6b6b}
.sp-t{flex:1;min-width:0;display:flex;flex-direction:column}
.sp-it:not(.tall) .sp-t{flex-direction:row;align-items:baseline;gap:6px}
.sp-t b{font:500 12px/16px var(--font-ui);color:#171717;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sp-t span{margin-top:2px;font:400 12px/16px var(--font-ui);color:#6b6b6b;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.sp-enter{display:block;visibility:hidden;flex:none;height:16px;padding:0 4px;border-radius:4px;box-shadow:inset 0 0 0 1px #e2e2e2;font:400 10px/16px var(--font-mono);color:#6b6b6b}
.sp-it[aria-selected=true] .sp-enter{visibility:visible} /* the hint always holds its place: hovering a row must not narrow its title */
.sp-empty{padding:32px 12px;text-align:center;font:400 12px/1.4 var(--font-ui);color:#6b6b6b}
.sp-feedback{flex:none;display:grid;gap:4px;padding:8px 14px;border-bottom:1px solid #e2e2e2;font:400 12px/1.4 var(--font-ui);color:#6b6b6b;max-height:96px;overflow:auto}
.sp-feedback[hidden]{display:none}
.sp-feedback button,.sp-more{color:var(--accent);background:none;border:0;font:inherit;cursor:pointer;text-decoration:underline;text-underline-offset:3px}
.sp-more{display:block;width:100%;padding:12px;text-align:center}
.sp-scopes{scrollbar-width:thin}
.sp-feedback button:focus-visible,.sp-more:focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.sp-foot{flex:none;display:flex;align-items:center;gap:14px;height:38px;padding:0 14px;border-top:1px solid #e2e2e2;font:400 11px/1 var(--font-ui);color:#8f8f8f;white-space:nowrap}
.sp-foot span{display:flex;align-items:center;gap:4px}
.sp-foot kbd{padding:0 4px;border-radius:4px;box-shadow:inset 0 0 0 1px #e2e2e2;font:400 10px/16px var(--font-mono)}
@media (max-width:480px){.sp-q input{font-size:16px}.sp-foot{gap:8px;padding:8px 12px;height:auto;min-height:38px;flex-wrap:wrap}}

/* The top bar carries no page title (Oct 2026) — the heading stays for assistive tech only */
html:not(.is-phone) .band h1{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;padding:0;box-shadow:none}
html:not(.is-phone) .band .tb-search{margin-right:auto}
html:not(.is-phone) .band .bt>.tag{display:none}   /* a title's tag (Training · Beta) goes with the title; the nav still carries it */
/* Search: a soft fill on hover / open, no hard outline */
.band .tb-search,.band .tb-search:hover,.band .tb-search[aria-expanded=true]{border-color:transparent}

/* Billing & credits as a centred modal over the page it was opened from (app/main.js openBillingModal) */
dialog.billing-modal{position:fixed;inset:0;margin:auto;width:min(1120px,calc(100vw - 48px));max-width:none;height:min(880px,calc(100dvh - 48px));max-height:none;padding:0;border:0;border-radius:var(--r-sheet);background:#fff;color:var(--ink-1);box-shadow:0 24px 64px rgb(16 30 42/.22),0 0 0 .5px rgb(16 30 42/.14);display:flex;flex-direction:column;overflow:hidden}
dialog.billing-modal:not([open]){display:none}
dialog.billing-modal::backdrop{background:rgb(16 30 42/.26);-webkit-backdrop-filter:blur(10px) saturate(1.1);backdrop-filter:blur(10px) saturate(1.1)}
.billing-modal .bm-h{display:flex;align-items:center;gap:8px;flex:none;height:56px;padding:0 12px 0 24px;border-bottom:1px solid var(--hair-2)}
.billing-modal .bm-h h2{flex:1;font:600 1.0625rem/1.3 var(--font-ui);letter-spacing:-.01em}
.billing-modal .bm-body{flex:1;min-height:0;overflow:auto;overscroll-behavior:contain;padding:20px 24px 24px}
.billing-modal .bm-load{font:var(--t-body);color:var(--ink-2)}
.billing-modal .pane{position:relative}
.billing-modal .bl-main{background:none;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none;border-radius:0;padding:0}
@media (max-width:800px){dialog.billing-modal{width:100vw;height:100dvh;border-radius:0}.billing-modal .bm-h{padding:0 8px 0 16px}.billing-modal .bm-body{padding:12px;overflow-x:hidden}}
@media (prefers-reduced-transparency:reduce){dialog.billing-modal::backdrop{-webkit-backdrop-filter:none;backdrop-filter:none;background:rgb(16 30 42/.5)}}

/* Desktop panes can be narrower than the window (sidebar, split view, zoom).
   Keep every page tool available and let the shell reserve the measured height. */
html:not(.is-phone) body.app .band{height:auto;min-height:56px;flex-wrap:wrap;row-gap:8px;padding-block:10px}
html:not(.is-phone) .band>.bg{min-width:0;max-width:100%;flex-wrap:wrap;row-gap:8px}
html:not(.is-phone) .band:not(:has(>.tb-search)) .host{margin-left:auto}   /* only without the search: its own auto margin already ends the row, and two would strand page controls mid-band (Oct 11) */
html:not(.is-phone) .band .bt{flex-wrap:wrap;row-gap:6px}
html:not(.is-phone) .band .bg :is(.fld,.seg){max-width:100%}
dialog.sheet>header,dialog.sheet>footer{flex-shrink:0}
dialog.sheet>footer{flex-wrap:wrap}

/* Local role switch (app/local-roles.js): one calm cover over the sign-out → sign-in hop */
html.lr-switching body::after{content:var(--lr-label,"Switching…");position:fixed;inset:0;z-index:2147483646;display:grid;place-items:center;background:var(--g1);color:var(--ink-2);font:500 .875rem/1.4 var(--font-ui)}

/* Page tabs (LumaDial's dashboard tabs): icon + label on a hairline; the current tab is filled and underlined in the
   accent. Used by the page-level switches (Book Overview · Analytics, Scoreboard Everyone · My team). Buttons carry
   aria-pressed (wired with motion.wireSeg or a page's own click handler). */
.ptabs{display:flex;align-items:flex-end;gap:20px;min-width:0;padding-left:14px;box-shadow:inset 0 -1px 0 var(--hair-2)}
.ptabs>button{position:relative;display:inline-flex;align-items:center;gap:6px;height:36px;padding:0 10px;border:0;border-radius:4px 4px 0 0;background:none;color:var(--glyph);font:500 .78125rem/1rem var(--font-ui);white-space:nowrap;cursor:pointer;transition:color .12s,background-color .12s}
.ptabs>button .i{width:14px;height:14px;stroke-width:1.7}
.ptabs>button[aria-pressed=true]{background:linear-gradient(to bottom,transparent,rgb(29 106 208/.035) 55%,rgb(29 106 208/.065));color:var(--accent-ink)}
.ptabs>button[aria-pressed=true] .i{stroke-width:2}
.ptabs>button[aria-pressed=true]::after{content:"";position:absolute;left:0;right:0;bottom:0;height:2px;border-radius:var(--r-pill);background:var(--accent)}
@media (hover:hover){.ptabs>button[aria-pressed=false]:hover{color:var(--ink-1)}}
.ptabs>button:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* Shared interaction states: keyboard focus follows the same accent as selection.
   Pointer focus leaves the approved resting appearance unchanged. */
:is(button,a[href],input,select,textarea,[role=button],[role=tab],[role^=menuitem],[role=option],[tabindex="0"]):focus-visible{outline:2px solid var(--accent);outline-offset:2px}
.fld:has(:focus-visible){outline:2px solid var(--accent);outline-offset:2px}
.fld :is(input,select,textarea):focus-visible{outline:none}
.sw input:focus-visible~i{outline:2px solid var(--accent);outline-offset:2px}
/* Click/tap focus, including programmatic focus inside opened menus and editors,
   stays quiet. Use the existing modality tracker rather than :focus-visible alone:
   browsers also match that pseudo-class on pointer-focused text fields. Keyboard
   navigation keeps its rings; never blur controls or remove focus containment. */
html:not([data-input-modality=keyboard]) :is(:focus,.fld:focus-within,.mux-shell:focus-within,.sw input:focus~i){outline:none!important}

/* Disabled and busy controls retain their resting state, even under a pointer.
   Busy is a visual state only; event guards remain owned by the existing controllers. */
.btn:not(.pri):not(.pl):not(.bare):not(.crit.is-confirm):is(:disabled,[aria-disabled=true]){background:rgb(255 255 255/.68)}
.btn.pri:is(:disabled,[aria-disabled=true]){background:color-mix(in srgb,var(--accent) 34%,transparent);box-shadow:none;color:var(--on-accent)}
.btn.crit.is-confirm[aria-disabled=true]{background:color-mix(in srgb,var(--crt-ink) 34%,transparent);box-shadow:none;color:var(--on-accent)}
.btn:is(.pl,.bare):is(:disabled,[aria-disabled=true]){background:none;box-shadow:none}
.btn:is(:disabled,[aria-disabled=true],[aria-busy=true]){transform:none;filter:none}
:is(.tk,.seg>button):is(:disabled,[aria-disabled=true]){opacity:.55;transform:none;filter:none}
.menu :is([role^=menuitem],[role=option]):is(:disabled,[aria-disabled=true]){background:none;color:var(--ink-disabled)}
.menu :is([role^=menuitem],[role=option]):is(:disabled,[aria-disabled=true]) :is(.i,.ct,kbd,small,.opt2 span){color:inherit}
.sw input:disabled~b{width:14px;background:var(--on-accent);box-shadow:0 1px 2px rgb(16 30 42/.3),0 0 0 .5px rgb(16 30 42/.08);-webkit-backdrop-filter:none;backdrop-filter:none}
.sw input:disabled:checked~b{--x:14px}
.is-phone .sw input:disabled~b{width:24px}
.is-phone .sw input:disabled:checked~b{--x:20px}

/* Clear and toast-close targets grow without moving their visible glyphs. */
.clr{position:relative}
.clr::after{content:"";position:absolute;inset:-4px}

@media (forced-colors:active){
:is(button,a[href],input,select,textarea,[role=button],[role=tab],[role^=menuitem],[role=option],[tabindex="0"]):focus-visible,.fld:has(:focus-visible),.sw input:focus-visible~i{outline-color:Highlight}
.sw input:disabled~b,.sw input:disabled:checked~b{background:GrayText}
.btn:is(.pri,.crit.is-confirm):is(:disabled,[aria-disabled=true]){background:Canvas;color:GrayText;box-shadow:none}
}
@media (prefers-reduced-motion:reduce){
.sw b{transition:none}
.sw input:active~b,.sw.is-pressing b{width:14px}
.sw input:checked:active~b,.sw.is-pressing input:checked~b{--x:14px}
.is-phone .sw input:active~b,.is-phone .sw.is-pressing b{width:24px}
.is-phone .sw input:checked:active~b,.is-phone .sw.is-pressing input:checked~b{--x:20px}
}
/* Desktop chrome: the top bar is 80% opaque over a light blur, so the sky scene shows through (Oct 2026); the side menu has its own section below */
html:not(.is-phone) body.app .band.g1{background:var(--chrome);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
/* Desktop: every page sits flush against the side menu and the top bar — no outer gutter, square page cards (Oct 2026) */
html:not(.is-phone):not(.no-shell) body.app #page{padding:var(--h-band) 0 0 var(--w-side)}
html.has-gbanner:not(.is-phone):not(.no-shell) body.app #page{padding-top:calc(var(--h-band) + 56px)}
/* --h-top: the room above the page — the top bar, plus the 56px alert banner while it is up. A fixed-viewport page is 100dvh minus THIS,
   never minus the bare band (under the banner those pages overflowed the window by 56px). */
:root{--h-top:var(--h-band)}
html.has-gbanner:not(.is-phone):not(.no-shell){--h-top:calc(var(--h-band) + 56px)}
html:not(.is-phone) #page .pane{border-radius:0}
/* …and the cards on a page join with a hairline instead of a gap. A page's surface reaches the window bottom through ONE mechanism, the
   FULL HEIGHT block below (the last visible root grows) — no card or wrapper carries a window-tall min-height of its own: a floor on
   "the only <section>" or on every wrapper that holds a pane stretched the KPI strip and the chart rows above the last root into
   screen-tall empty boxes (Oct 14, Analytics and the admin Home), and overflowed the page by the 56px alert banner's height. */
html:not(.is-phone) #page>*:has(>.pane){gap:0}
html:not(.is-phone) #page>*>.pane{margin-top:0;margin-bottom:0;box-shadow:inset 0 0 0 .5px var(--hair-2)}
/* every page's surface is 80% white over a light blur (the sky shows through), as Overview: a page's wrapper of cards carries
   it once and its cards go clear (no doubled tint); a lone card carries it itself */
html:not(.is-phone) #page>*:has(.pane){align-content:start;background:rgb(255 255 255/.8);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
html:not(.is-phone) #page>* .pane{background:transparent;-webkit-backdrop-filter:none;backdrop-filter:none}
html:not(.is-phone) #page>.pane{background:rgb(255 255 255/.8);-webkit-backdrop-filter:blur(18px) saturate(1.4);backdrop-filter:blur(18px) saturate(1.4)}
/* FULL HEIGHT (owner, Oct 14): no desktop page ends above the window's bottom edge. #page is a column at least one window tall under the
   top bar; the page's last visible root takes all the height the others leave, so its surface reaches the bottom at every window size.
   Zero specificity on purpose: a page that sets its own display, flex or height still wins. A hidden element and a screen-reader-only
   note (.sr-only, e.g. Analytics' "Loading analytics" after its card) are no root: they never take the growth from the card before them.
   The rule that names the last visible root uses :has(~ …); it sits in @supports selector(:has(~ *)) so engines without it (jsdom's
   nwsapi throws) skip it. */
:where(html:not(.is-phone):not(.no-shell) body.app #page){display:flex;flex-direction:column}
:where(html:not(.is-phone):not(.no-shell) body.app #page)>:where(*){flex:0 0 auto}
@supports selector(:has(~ *)){:where(html:not(.is-phone):not(.no-shell) body.app #page)>:where(:not([hidden],.sr-only):not(:has(~ :not([hidden],.sr-only)))){flex:1 0 auto}}
/* …and on the phone. #page keeps its dock clearance (padding-bottom 118px + --ai-clear), so the surface reaches the line above the dock — not
   behind it — and a short page (a loading or error pane, Notifications, an empty list) no longer ends mid-window over bare sky. Same
   mechanism and the same guard as desktop: ONLY the last visible root grows, its own children keep their natural height (align-content:start
   stops a grid root from spreading its extra height over its rows), and a page that is taller than the window never grows at all.
   Calendar sets its own fixed-height #page on the phone and is outside this (its rule is below in pages/calendar/phone.css). */
html.is-phone:not(.no-shell) body.app #page{display:flex;flex-direction:column}   /* not zero-specificity: Book, Home, Analytics, Licensing and Resources lay #page out as a one-column grid on the phone, and a grid cannot hand its leftover height to the last root */
:where(html.is-phone:not(.no-shell) body.app #page)>:where(*){flex:0 0 auto}
@supports selector(:has(~ *)){:where(html.is-phone:not(.no-shell) body.app #page)>:where(:not([hidden],.sr-only):not(:has(~ :not([hidden],.sr-only)))){flex:1 0 auto;align-content:start}}

/* =====================================================================================================================
   Side menu — the ONE place the desktop sidebar is styled (direction B · macOS, owner-approved Oct 14 2026).
   A flush, full-height 232px column on the kit's chrome glass (--g1) closed by one --sh-1 hairline; 28px rows (--h-side,
   --r-row); 13px labels set in px (the menu does not follow the browser's root text size); 16px outline glyphs tinted
   --accent; the current row on --accent-tint (label 500), hover a neutral wash; 11px/600 sentence-case section headers;
   plain right-aligned counts, Notifications alone with an accent dot; Post a deal pinned under the list as the kit's primary
   button; one compact account row; the collapse control a bare sidebar.left glyph at the right end of the brand row.
   This block REPLACES the earlier LumaDial-rail / X-style / Apple-type passes: change it here, never layer overrides on top.
   Kit tokens only: --g1 + --g1-filter · --sh-1 · --ink-1/2 · --glyph (ink-3) · --accent* · --hair · --r-row · --r-ctl ·
   --h-side · --h-dense · --dur-hover/press · --ease-out. Glyphs are the sb-* family in app/icons.js (Lucide ISC notice there).
   DOM contract (app/shell.js, read by the first-run tour app/walkthrough/script.js): nav.side[aria-label=Main] ·
   .side .nav a[data-route] · .nbell.bell (data-route=notifications) · .nbell.nmore (its flyout: .menu.xmore, below) · .side-post a.tb-post[data-post-deal] ·
   .sfoot .sacct · button.rail-tg · a `title` on every row. Desktop only: the phone keeps its dock (html.is-phone hides this nav).
   ===================================================================================================================== */

/* ---------- width: one fixed value on every desktop size; collapsed (html.side-off) the column is gone, the page takes its width ---------- */
html:not(.is-phone):not(.side-off){--w-side:232px}
html.side-off:not(.is-phone){--w-side:0px}
html.side-off:not(.is-phone) body.app .band{padding-left:52px}   /* the band reserves the room the collapse control waits in (12 + 28 + 12) */

/* ---------- the surface: ONE flush, full-height chrome-glass column (the page and band sit flush against it) ---------- */
nav.side{position:fixed;z-index:3;left:0;top:0;bottom:0;width:var(--w-side);display:flex;flex-direction:column;
  padding:10px 8px 8px;overflow:hidden;
  background:var(--g1);-webkit-backdrop-filter:var(--g1-filter);backdrop-filter:var(--g1-filter);
  box-shadow:var(--sh-1);                                       /* one hairline (the kit's --sh-1) closes the column; the page and band sit flush against it */
  font:400 13px/1 var(--font-ui);color:var(--ink-1);-webkit-font-smoothing:antialiased}
nav.side>*{flex:none}
html.side-off nav.side,html.no-shell nav.side{display:none}

/* ---------- brand: 20px mark + agency name 13/600; the collapse control lives at the row's right end ---------- */
.side>.brand{display:flex;align-items:center;gap:8px;height:36px;margin:0 0 6px;padding:0 8px}
.side .brand-mk{width:20px;height:20px;border-radius:5px;box-shadow:0 0 0 .5px rgb(9 15 23/.35),0 1px 1.5px rgb(9 15 23/.18)}
.side .brand .nm{flex:1;min-width:0;padding-right:32px;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font:600 13px/1 var(--font-ui);letter-spacing:-.003em;color:var(--ink-1)}

/* ---------- collapse / expand: quiet, a bare 28px glyph (sidebar.left) that gains a wash on hover; no circle, no border ---------- */
.rail-tg{position:fixed;z-index:6;top:14px;left:calc(var(--w-side) - 36px);display:grid;place-items:center;width:28px;height:28px;padding:0;border:0;border-radius:var(--r-row);
  background:none;box-shadow:none;color:var(--glyph);cursor:default;transition:background-color var(--dur-hover) ease,color var(--dur-hover) ease}
.rail-tg .i{width:16px;height:16px;stroke-width:2.25}
@media (hover:hover){.rail-tg:hover{background:rgb(16 30 42/.06);color:var(--ink-1)}}
.rail-tg:active{background:rgb(16 30 42/.1);transition-duration:var(--dur-press)}
html.side-off:not(.is-phone) .rail-tg{left:12px}      /* collapsed: waits at the band's left edge (the band already reserves 52px) */
html.is-phone .rail-tg,html.no-shell .rail-tg,body:not(.app) .rail-tg{display:none}

/* ---------- the list ---------- */
.side .nav{flex:1;min-height:0;display:flex;flex-direction:column;gap:1px;overflow-x:hidden;overflow-y:auto;overscroll-behavior:contain;scrollbar-width:none}
.side .nav::-webkit-scrollbar{display:none}

/* row: 28 tall · 8 inset · 16px accent glyph · 8 gap · 13/400 ink-1 · radius 6 (the kit's row radius) */
.side .nav>:is(a,.nbell){position:relative;flex:none;display:flex;align-items:center;gap:8px;width:100%;height:var(--h-side);padding:0 8px;border:0;border-radius:var(--r-row);background:none;
  font:400 13px/1 var(--font-ui);color:var(--ink-1);text-align:left;white-space:nowrap;cursor:default;-webkit-user-select:none;user-select:none;
  transition:background-color var(--dur-hover) ease}
.side .nav .i{flex:none;width:16px;height:16px;stroke-width:2.25;color:var(--accent)}   /* 2.25 units x 16/24 = 1.5px on screen; macOS tints every sidebar glyph */

/* states: hover = a faint neutral wash · pressed = a step darker, instantly · current = the kit's selection tint (--accent-tint, as table rows
   and chips use), label one weight up. Neutral vs blue keeps "hover" and "you are here" unmistakable. */
@media (hover:hover){.side .nav>:is(a,.nbell):not([aria-current=page],.is-current,[aria-expanded=true]):hover{background:rgb(16 30 42/.055)}}
.side .nav>:is(a,.nbell):active{background:rgb(16 30 42/.09);transition-duration:var(--dur-press)}
.side .nav>a[aria-current=page],.side .nav>.nbell.is-current,.side .nav>.nbell[aria-expanded=true]{background:var(--accent-tint);font-weight:500}
.side .nav>:is(a,.nbell):focus-visible{outline:2px solid var(--accent);outline-offset:-2px}

/* section headers: 11/600 --glyph, sentence case, aligned to the glyph column */
.side .nav .grp{flex:none;display:flex;align-items:center;height:20px;margin:14px 0 2px;padding:0 8px;font:600 11px/1 var(--font-ui);letter-spacing:.01em;color:var(--glyph);cursor:default}

/* counts: plain right-aligned numerals in --glyph. Notifications alone carries an accent dot (6px) before its count. */
.side .nav .n{margin-left:auto;padding:0;border:0;border-radius:0;background:none;font:400 12px/1 var(--font-ui);font-variant-numeric:tabular-nums;color:var(--glyph)}
.side .nav .badge{position:static;margin-left:auto;display:inline-flex;align-items:center;gap:5px;min-width:0;height:auto;padding:0;border:0;border-radius:0;background:none;box-shadow:none;
  font:500 12px/1 var(--font-ui);font-variant-numeric:tabular-nums;text-align:left;color:var(--ink-2);pointer-events:none}
.side .nav .badge::before{content:"";flex:none;width:6px;height:6px;border-radius:50%;background:var(--accent)}
.side .nav a .tag{margin-left:auto}                                   /* the locked Lapse Bot's "Pro" · a row tag, unchanged kit tag */
/* locked Lapse Bot (isFreePlan || !lapseBotEntitled, D40) keeps its row, muted, with a bare "Pro" tag → Billing (production: AgentOsSidebar locked branch) */
.side .nav a.is-locked{color:var(--ink-2)}.side .nav a.is-locked .i{color:var(--glyph)}
.side .nav a .lk{margin-left:auto;display:inline-flex;color:var(--ntc)}.side .nav a .lk .i{width:13px;height:13px;color:inherit}   /* NIPR lock (shell.js updateCounts) */
.side .nav a .n+.lk{margin-left:6px}

/* ---------- Post a deal: the kit's own primary button (28 tall, r8), pinned under the list, full width, plain (no glow) ---------- */
.side .side-post{margin:8px 0 0}
.side .side-post .tb-post{display:flex;align-items:center;justify-content:center;gap:6px;width:100%;height:var(--h-dense);padding:0 12px;border-radius:var(--r-ctl);
  background:var(--accent-sheen) var(--accent);color:var(--on-accent);font:500 13px/1 var(--font-ui);white-space:nowrap;
  box-shadow:0 0 0 .5px rgb(18 74 150/.6),0 1px 2px rgb(18 74 150/.24),inset 0 1px 0 rgb(255 255 255/.2);
  transition:transform var(--dur-press) var(--ease-out),background-color var(--dur-hover) ease}
.side .side-post .tb-post .i{width:14px;height:14px;stroke-width:2.5;color:inherit}
.side .side-post .tb-post::before,.side .side-post .tb-post::after{content:none}
@media (hover:hover){.side .side-post .tb-post:hover{background-color:var(--accent-hover)}}
.side .side-post .tb-post:active{transform:scale(.97)}
.side .side-post .tb-post:focus-visible{outline:2px solid var(--accent);outline-offset:2px}

/* ---------- account: one compact row. Avatar 24 · name 13/500 · org 11 --glyph · a bare sign-out glyph ---------- */
.side .sfoot{margin-top:8px;padding:8px 0 0;border-top:1px solid var(--hair)}
.side .scard{display:flex;align-items:center;gap:2px}
.side .sfoot>.mirror-tag{margin:0 var(--s2) var(--s2)}   /* mirror mode only: the one quiet chip above the account card */
.side .sacct{flex:1;min-width:0;display:flex;align-items:center;gap:8px;height:40px;padding:0 6px 0 8px;border:0;border-radius:var(--r-row);background:none;
  text-align:left;color:var(--ink-1);cursor:default;transition:background-color var(--dur-hover) ease}
@media (hover:hover){.side .sacct:hover{background:rgb(16 30 42/.055)}}
.side .sacct:active{background:rgb(16 30 42/.09);transition-duration:var(--dur-press)}
.side .sacct[aria-expanded=true]{background:rgb(16 30 42/.09)}
.side .sacct .av{position:relative;width:24px;height:24px;font:600 10px/1 var(--font-ui);background:linear-gradient(150deg,var(--sky-2),var(--sky))}   /* the kit's sky avatar, one step deeper so it holds on glass */
.side .sacct .av .on{display:none}                                    /* the always-on presence dot is decoration */
.side .sacct .who{flex:1;min-width:0;display:grid;gap:1px}
.side .sacct .who b{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font:500 13px/16px var(--font-ui);color:var(--ink-1)}
.side .sacct .chev{flex:none;display:grid;place-items:center;color:var(--glyph)}   /* the account card is a switcher (more than one workspace): a quiet chevron, no caption */
.side .sacct .who span{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis;font:400 11px/14px var(--font-ui);color:var(--glyph)}
.side .sout{flex:none;color:var(--glyph)}
.side .sout .i{width:16px;height:16px;stroke-width:2.25;color:inherit}
@media (hover:hover){.side .sout:hover{color:var(--ink-1)}}

/* ---------- More: the flyout beside the column (app/shell.js sideMoreMenu · app/overlays.js align 'right-up': bottom edge level with the
   More row, growing upward, kept inside the window). The same recipe as the rows above on the kit's menu: an OPAQUE float surface (it
   sits over live page content, so no see-through), 6px inset · 12 radius · the kit float shadow; rows 28 · 13/400 in px · 16px sb-* glyphs
   at 1.5px in --ink-2 · counts and group labels in --glyph; hover and keyboard highlight = the selection tint with ink text (the kit's
   other menus keep their accent fill); one --hair rule between groups. Keyboard focus keeps the ring, inset like the rows' ---------- */
.menu.xmore{padding:6px;background:var(--lg-card);-webkit-backdrop-filter:none;backdrop-filter:none;font:400 13px/1 var(--font-ui);color:var(--ink-1)}
.menu.xmore [role^=menuitem]{gap:8px;height:var(--h-side);padding:0 8px;font:400 13px/1 var(--font-ui);color:var(--ink-1);-webkit-user-select:none;user-select:none}
.menu.xmore .i{width:16px;height:16px;stroke-width:2.25;color:var(--ink-2)}
.menu.xmore .is-hl,.menu.xmore [role^=menuitem]:hover:not([aria-disabled=true]){background:var(--accent-tint);color:var(--ink-1)}
.menu.xmore .is-hl .i,.menu.xmore [role^=menuitem]:hover:not([aria-disabled=true]) .i{color:var(--ink-2)}
.menu.xmore [role^=menuitem]:focus-visible{outline-offset:-2px}
.menu.xmore .ct{margin-left:auto;padding-left:12px;font:400 12px/1 var(--font-ui);font-variant-numeric:tabular-nums;color:var(--glyph)}
.menu.xmore hr{margin:5px 8px;background:var(--hair)}
.menu.xmore .mlabel{display:flex;align-items:center;height:20px;margin:6px 0 2px;padding:0 8px;font:600 11px/1 var(--font-ui);letter-spacing:.01em;color:var(--glyph)}
@media (prefers-contrast:more){
  .menu.xmore .ct,.menu.xmore .mlabel{color:var(--ink-2)}
  .menu.xmore hr{background:var(--edge-hc)}
}
@media (forced-colors:active){
  .menu.xmore .is-hl,.menu.xmore [role^=menuitem]:hover:not([aria-disabled=true]){background:Highlight;color:HighlightText;forced-color-adjust:none}
  .menu.xmore .is-hl :is(.i,.ct),.menu.xmore [role^=menuitem]:hover:not([aria-disabled=true]) :is(.i,.ct){color:HighlightText}
}

/* ---------- short windows: tighten the air, never the type; below ~640 the list scrolls inside itself ---------- */
@media (max-height:700px){
  nav.side{padding-top:8px}
  .side .nav .grp{margin-top:10px}
  .side>.brand{margin-bottom:2px}
}

/* Matthew's tactile primary controls (Oct 21), adapted to keep the full hit target fixed.
   The existing hover color remains; a pointer press uses a solid, contrast-safe accent fill.
   Scaling the control itself can move an edge out from under a held pointer and lose the click. */
html :is(.btn.pri,.side .side-post .tb-post),html :is(.btn.pri,.side .side-post .tb-post):active{transform:none;opacity:1;transition:background-color var(--dur-press) var(--ease-out)}
@media (prefers-reduced-motion:no-preference){
  html[data-input-modality=pointer] :is(.btn.pri,.side .side-post .tb-post):active:not(:disabled,[aria-disabled=true],[aria-busy=true]){background-color:var(--accent-hover);background-image:none;color:var(--on-accent)}
}
html[data-input-modality=keyboard] :is(.btn.pri,.side .side-post .tb-post){opacity:1;transition:none}
html :is(.btn.pri,.side .side-post .tb-post):is(:disabled,[aria-disabled=true],[aria-busy=true]){opacity:1;transition:background-color var(--dur-hover) ease}
@media (prefers-reduced-motion:reduce){
  html :is(.btn.pri,.side .side-post .tb-post){opacity:1;transition:background-color var(--dur-hover) ease}
}

/* ---------- adaptivity ---------- */
@media (prefers-reduced-motion:reduce){.side .side-post .tb-post:active{transform:none}}
@media (prefers-contrast:more){
  .side .nav>a[aria-current=page],.side .nav>.nbell.is-current{box-shadow:inset 0 0 0 1px var(--edge-hc)}
  .side .nav .grp,.side .nav .n,.side .sacct .who span{color:var(--ink-2)}
}
@media (forced-colors:active){
  .side .nav>a[aria-current=page],.side .nav>.nbell.is-current{background:Highlight;color:HighlightText;forced-color-adjust:none}
  .side .nav>a[aria-current=page] .i,.side .nav>.nbell.is-current .i{color:HighlightText}
  .side .side-post .tb-post{forced-color-adjust:none}
}

/* Intake preparation/recovery owns only its content, not the Search palette's
   fixed 640px workspace. Keep the same dialog chrome without a second card. */
dialog.center-sheet.deal-read-modal{inset:0;margin:auto;max-width:560px;height:fit-content;max-height:calc(100dvh - 32px)}
.deal-read-modal .sheet-body{flex:initial;padding:0}
.deal-read-modal .live-state{border:0;border-radius:0;background:transparent;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}
.deal-read-modal .live-state::before{display:none}
.deal-read-modal .pane{position:relative}   /* the global .pane is absolute (v3-base); outside #page nothing overrides it, so the loading skeleton and the state pane escaped the frame */
.deal-read-modal .route-loading{padding:16px 20px 20px}
.deal-read-modal .route-loading .pane{padding:0;border:0;border-radius:0;background:transparent;box-shadow:none;-webkit-backdrop-filter:none;backdrop-filter:none}
.deal-read-modal .route-loading .pane::before{display:none}

/* ---------- Atlas AI clear zone (P7) ----------
   The launcher is a 44 px disc fixed in the bottom-right gutter (right 12 / bottom 12; phone right 21 / bottom 94, stacked above the
   Post a deal +). While it renders, app/ai-popup.js sets html[data-ai-launcher]; --ai-clear is 0 without it, so every rule below
   is a no-op for a page that has no launcher. The rule: a page keeps filling the window and its SCROLL CONTAINER reserves --ai-clear at
   the end, so the last row or control scrolls clear of the disc; a bar stuck to the bottom cannot scroll and takes a right or bottom
   inset instead; empty pane padding and decoration may sit under the disc. A new scroll container adds padding-bottom:var(--ai-clear),
   a new bottom-stuck bar adds the inset, one line each (the page's own page.css; the P7 probe, scripts/live-adapters/
   ai-clear-zone.browser.test.mjs, scrolls every scroller to its end and fails on a control under the disc). */
:root{--ai-clear:0px}
html[data-ai-launcher]{--ai-clear:64px}                /* 12 gutter + 44 disc + 8 gap */
html.is-phone[data-ai-launcher]{--ai-clear:28px}       /* beyond #page's 118 dock clearance: 94 + 44 + 8 = 146 */
html{scroll-padding-bottom:var(--ai-clear)}
.is-phone #page{padding-bottom:calc(118px + var(--ai-clear))}
/* Window-scrolled desktop pages: the last visible child extends (its surface still fills). The fixed-viewport workspaces are left out —
   their scroll containers pad themselves in their own page.css, and a second reserve here would pull their surfaces off the window
   bottom: Book, Scoreboard, Calendar, Retention, Rates, Resources, the Home dashboard (agent and agency admin alike), the Annuities desk board (a page with a
   .brd), and the Requests ledger and inbox (.cxd, .org.ibx). The rule names the last visible root with :has(~ …), so it sits in
   @supports (engines without it, jsdom's nwsapi among them, skip it). */
@supports selector(:has(~ *)){html[data-ai-launcher]:not(.is-phone) body.app #page:not([data-page="calendar"],[data-page^="lapse-bot"],[data-page^="retention"],[data-page="book"],[data-page="training"],[data-page="scoreboard"],[data-page="annuity-rates"],[data-page="resources"],[data-page="overview"]:has(>.db),[data-page="annuities"]:has(>.brd),[data-page="carrier-requests"]:has(>.cxd,>.org.ibx))>:where(:not([hidden]):not(:has(~ :not([hidden])))){padding-bottom:var(--ai-clear)}}
/* Calendar — its own files are being edited; these move to pages/calendar/*.css when that work lands. Higher specificity than the
   page's own rules: the html[data-ai-launcher] prefix also keeps them inert without the launcher. */
html[data-ai-launcher] [data-page="calendar"] .tg-scroll{padding-bottom:var(--ai-clear)}
html.is-phone[data-ai-launcher] [data-page="calendar"] .tg-scroll{padding-bottom:calc(118px + var(--ai-clear))}
html[data-ai-launcher] [data-page="calendar"] .ag{padding-bottom:calc(24px + var(--ai-clear))}
html.is-phone[data-ai-launcher] [data-page="calendar"] .ag{padding-bottom:calc(118px + var(--ai-clear))}
