/* ═══════════════════════════════════════════════════════════════════════════════════════
   ops-universal.css — one aesthetic across every page, including the ones that were never
   written against the design system.

   WHY THIS EXISTS AND WHY IT LOOKS LIKE THIS
   The 66 older pages carry no design tokens at all. They hardcode a slate palette
   (#0f172a / #e2e8f0 / #1e293b / #334155), are dark-only with no light mode, use an 8px radius
   everywhere, and use #3b82f6 as the accent — 144 occurrences of it. There is nothing to remap,
   because there are no variables to remap TO.

   So this sheet overrides by SELECTOR, and it must load AFTER each page's own <style> block:
   same specificity, later source order wins. If a page ever stops linking it last, that page
   silently reverts. Check the <link> position before concluding a page "did not pick up" the
   style.

   The class vocabulary below is not invented — it is what those pages already share:
   .btn/.card/.pill/.kpi/.field/.tabs/.modal/.toast/.top/.pg, measured across all of them.

   SCOPE, honestly: this unifies colour, type, radius, density and the common components. It
   cannot reach a colour hardcoded inline on an element, or a bespoke widget only one page has.
   Expect stragglers, and fix them by name as they turn up rather than by widening this file
   into a catch-all.
   ═══════════════════════════════════════════════════════════════════════════════════════ */

/* ── type ─────────────────────────────────────────────────────────────────────────────
   These pages ship Inter. One face for UI, one for anything read as a value. */
body,button,input,select,textarea,.btn,.field{
  font-family:var(--sans);
}
body{
  background:var(--paper);
  color:var(--ink-1);
  font-size:13px;
  line-height:1.5;
  -webkit-font-smoothing:antialiased;
}
h1{font-family:var(--display);font-size:20px;font-weight:600;letter-spacing:-.014em}
h2{font-size:15px;font-weight:600;letter-spacing:-.008em}
h3,h4{font-size:13px;font-weight:600}
/* Nothing above 600. Several pages set 700/800 on headings and table cells. */
b,strong,th,h1,h2,h3,h4,h5,h6,.nm,.money{font-weight:600}

/* Anything read as a value: money, counts, ids, timestamps. Tabular so columns line up. */
.money,.mono,.ref,.reftag,code,pre,kbd{
  font-family:var(--mono);
  font-variant-numeric:tabular-nums;
  letter-spacing:-.01em;
}

/* ── surfaces ─────────────────────────────────────────────────────────────────────── */
.pg,.wrap,.page{max-width:1240px;margin:0 auto;padding:16px 20px 64px}

.top,.top-bar,.header{
  border-bottom:1px solid var(--line);
  background:var(--paper);
}
.top h1,.top-bar h1,.header h1{color:var(--ink-1)}
/* Colour-only rules on generic class names are how a subtitle rule lands on somebody else's
   chip. `.sub` is a subtitle here and a pale-green tag on the product finder — setting only the
   colour made it unreadable. These are now scoped to where they are genuinely text on the page
   surface, and anything carrying its own background sets BOTH below. */
.top .sub,.top-bar .sub,.header .sub,.pg > .sub,.muted,.dim,.hint{color:var(--ink-3)}

.card,.panel,.box,.modal,.login-box{
  background:var(--panel);
  border:1px solid var(--line);
  border-radius:var(--r-control);
  box-shadow:none;                 /* shadow means elevation; a card does not float */
  color:var(--ink-1);
}
.modal,.login-box{border-radius:var(--r-float);box-shadow:var(--lift)}   /* these DO float */
.card-h{
  border-bottom:1px solid var(--line);
  color:var(--ink-2);
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
}

/* ═══ THE BUTTON SYSTEM — no white buttons, no ovals, every one answers hover ═══════════════
   Owner's directive, 2026-08-24, verbatim: "make sure all buttons have a color, no more white
   buttons. No more basic oval shapes. Use hover highlights when you can."

   Measured before this block: 804 .btn across 70 pages, 87 .act, 7 .cbtn, 5 .sortbtn, 2 .pm-btn,
   2 .dispbtn, and the RESTING fill of the default in every one of those classes was
   var(--panel) — pure white in light mode. 59 pages restated that white fill in their own
   <style>. Half the small controls (.fbtn/.bbtn 18px, .modchip 999px, .bar button 16px) were
   pills, so a filter chip and a status badge read as the same object.

   FIVE TIERS, one vocabulary. The class names are the ones the pages already use — nothing
   here asks a page to change its markup:
     primary    accent fill, on-accent text      .btn.pri  .act.a-create  .btn-primary  .modchip.on
     secondary  STRUCTURAL tint, structural-dark .btn (the default)  .btn-sm  .btn-secondary  .act
                text (not white, and not the      .act.a-link  .act.a-none  .act.send  .pm-btn  .cbtn
                accent — that owns one primary
                per view; see --btn-2-* in
                ops.css for why this tier is the
                structural hue)
                                                 .dispbtn  .sortbtn  .modchip  .fbtn  .bbtn  .pager button
     danger     bad fill        .btn.danger .btn.reject .btn.del .btn.red
                bad tint        .act.a-warn  .pm-btn.no  .dispbtn.danger  .u-danger (below)
     success    ok fill         .btn.approve .btn.green .btn.ok .btn.success  .pm-btn.use
     warn tint                  .btn.warn
     ghost      transparent, tinted on hover      .btn.ghost  .act.a-ghost  button.toggle
                — for tertiary actions inside dense tables; never the only button in a row.
   .tab is a tab (underline, in .tabs above) and is not a button. A page's OWN coloured variant
   (.btn.ai, .act.v, .act.eng, .cbtn.call, .fbtn.active …) outranks the default on purpose.

   EVERY TIER: 8px radius (pills are for status chips — see .badge), a 1px border in a darker
   tint of its own hue, a hover that deepens the fill and darkens the border, translateY(1px)
   on press, a focus ring of 1px accent inside 3px --mh-soft, and disabled at .5 with no hover.
   Every rule that sets a background sets a color. The --btn-* tokens are in ops.css :root and
   restated in both dark blocks; the tints are color-mix() of the hue over --paper, so they
   follow the theme and the tenant accent without a second palette.

   SPECIFICITY, deliberately. 19 pages put their own <style> AFTER this sheet, so "later wins"
   is not available here. `:is(button,a).btn` is (0,1,1): it beats a page's `.btn` (0,1,0) in
   either order and still LOSES to a page's own coloured variant `.btn.ai` (0,2,0) — page-level
   meaning outranks the default, the default outranks white. Base-class hovers use
   :where(:hover) so they stay at (0,1,1) and cannot flip those variants; the hue-deepening
   that reaches EVERY button, variants included, is the filter rule, which touches no colour.
   Compound tiers (.btn.pri, .act.a-link …) have no sub-variants, so their hovers can carry
   full specificity and beat a page's own restatement of white on hover. */

/* .btn geometry — unchanged. Every other class keeps the size its page gave it. */
.btn,button.btn{
  display:inline-flex;align-items:center;gap:6px;
  height:var(--ctl-h,28px);padding:0 10px;
  font-size:12px;font-weight:500;
  white-space:nowrap;
}
.btn.sm,.btn-sm{height:24px;font-size:11px;padding:0 8px;min-width:24px}

/* Shape and motion, shared by every tier. */
.btn,:is(button,a,label,summary).btn,
.btn-sm,:is(button,a).btn-sm,
.btn-secondary,:is(button,a).btn-secondary,
.btn-primary,:is(button,a).btn-primary,
.act,:is(button,a).act,
:is(button,a).toggle,
.cbtn,:is(button,a).cbtn,
.dispbtn,:is(button,a).dispbtn,
.sortbtn,:is(button,a).sortbtn,
.pm-btn,:is(button,a).pm-btn,
.modchip,:is(button,a).modchip,
.fbtn,.bbtn,:is(button,a).fbtn,:is(button,a).bbtn,
.pager button{
  border-radius:var(--r-btn,8px);
  border-width:1px;border-style:solid;
  cursor:pointer;
  transition:background-color .12s,border-color .12s,color .12s,filter .12s,transform .06s;
}

/* SECONDARY — the default. A tint of the accent, never white. */
.btn,:is(button,a,label,summary).btn,
.btn-sm,:is(button,a).btn-sm,
.btn-secondary,:is(button,a).btn-secondary,
.act,:is(button,a).act,
.act.a-none,:is(button,a).act.a-none,
.act.a-link,:is(button,a).act.a-link,
.act.send,:is(button,a).act.send,
.cbtn,:is(button,a).cbtn,
.dispbtn,:is(button,a).dispbtn,
.sortbtn,:is(button,a).sortbtn,
.pm-btn,:is(button,a).pm-btn,
.modchip,:is(button,a).modchip,
/* THE LAST TWO FAMILIES THAT OWNED NO COLOUR. `.bar button` is the filter row on twelve boards
   and declared no fill anywhere, so it fell to the user-agent's ButtonFace — a white button by
   omission rather than by choice. `.qtab` took var(--panel), the page ground. Both are controls,
   and a control owns a colour. */
.fbtn,.bbtn,:is(button,a).fbtn,:is(button,a).bbtn,
.pager button,
.bar button,
/* PAGE-LOCAL CONTROL CLASSES THAT OWNED NO COLOUR. Measured across fifteen routes: these four
   were the labelled controls still rendering white after the tiers above, 15 of them, because a
   page invented its own class and this list had never heard of it. `:is(button,a).x` is (0,1,1)
   and beats the page's own `.x` (0,1,0) in either order, so they can be adopted here without
   touching the page. tools/control-colour-check.js measures this and fails the deploy when a new
   one appears, so the list stops drifting. Not adopted on purpose: the phone's [data-view]
   buttons are TABS (a tab is an underline, not a button) and the softphone keypad is a keypad. */
:is(button,a).cl-tog,
:is(button,a).check-btn,
:is(button,a).btn2,
:is(button,a).flt-clear,
.qtab{
  background:var(--btn-2-bg);color:var(--btn-2-ink);border-color:var(--btn-2-line);
}
.btn:where(:hover:not(:disabled)),:is(button,a,label,summary).btn:where(:hover:not(:disabled)),
.btn-sm:where(:hover:not(:disabled)),:is(button,a).btn-sm:where(:hover:not(:disabled)),
.btn-secondary:where(:hover:not(:disabled)),:is(button,a).btn-secondary:where(:hover:not(:disabled)),
.act:where(:hover:not(:disabled)),:is(button,a).act:where(:hover:not(:disabled)),
.cbtn:where(:hover:not(:disabled)),:is(button,a).cbtn:where(:hover:not(:disabled)),
.dispbtn:where(:hover:not(:disabled)),:is(button,a).dispbtn:where(:hover:not(:disabled)),
.sortbtn:where(:hover:not(:disabled)),:is(button,a).sortbtn:where(:hover:not(:disabled)),
.pm-btn:where(:hover:not(:disabled)),:is(button,a).pm-btn:where(:hover:not(:disabled)),
.modchip:where(:hover:not(:disabled)),:is(button,a).modchip:where(:hover:not(:disabled)),
.fbtn:where(:hover:not(:disabled)),.bbtn:where(:hover:not(:disabled)),
:is(button,a).fbtn:where(:hover:not(:disabled)),:is(button,a).bbtn:where(:hover:not(:disabled)),
.pager button:where(:hover:not(:disabled)),
:is(button,a).cl-tog:where(:hover:not(:disabled)),
:is(button,a).check-btn:where(:hover:not(:disabled)),
:is(button,a).btn2:where(:hover:not(:disabled)),
:is(button,a).flt-clear:where(:hover:not(:disabled)),
.act.a-none:hover:not(:disabled),:is(button,a).act.a-none:hover:not(:disabled),
.act.a-link:hover:not(:disabled),:is(button,a).act.a-link:hover:not(:disabled),
.act.send:hover:not(:disabled),:is(button,a).act.send:hover:not(:disabled){
  background:var(--btn-2-bg-hover);color:var(--btn-2-ink);border-color:var(--btn-2-line-hover);
}

/* PRIMARY — the one action that moves the record forward. */
.btn.pri,:is(button,a,label).btn.pri,
.act.a-create,:is(button,a).act.a-create,
.btn-primary,:is(button,a).btn-primary,
.modchip.on,:is(button,a).modchip.on{
  background:var(--accent);color:var(--on-accent);border-color:var(--accent);
}
.btn.pri:hover:not(:disabled),:is(button,a,label).btn.pri:hover:not(:disabled),
.act.a-create:hover:not(:disabled),:is(button,a).act.a-create:hover:not(:disabled),
.btn-primary:hover:not(:disabled),:is(button,a).btn-primary:hover:not(:disabled),
.modchip.on:hover:not(:disabled),:is(button,a).modchip.on:hover:not(:disabled){
  background:color-mix(in oklab, var(--accent) 86%, var(--ink));color:var(--on-accent);
  border-color:color-mix(in oklab, var(--accent) 72%, var(--ink));
}

/* DANGER — filled for the button that destroys; tinted for the one that warns. */
.btn.danger,.btn.reject,.btn.del,.btn.red,
:is(button,a).btn.danger,:is(button,a).btn.reject,:is(button,a).btn.del,:is(button,a).btn.red{
  background:var(--bad);color:var(--on-accent);border-color:var(--bad);
}
.btn.danger:hover:not(:disabled),.btn.reject:hover:not(:disabled),.btn.del:hover:not(:disabled),.btn.red:hover:not(:disabled),
:is(button,a).btn.danger:hover:not(:disabled),:is(button,a).btn.reject:hover:not(:disabled),
:is(button,a).btn.del:hover:not(:disabled),:is(button,a).btn.red:hover:not(:disabled){
  background:color-mix(in oklab, var(--bad) 86%, var(--ink));color:var(--on-accent);
  border-color:color-mix(in oklab, var(--bad) 72%, var(--ink));
}
.act.a-warn,:is(button,a).act.a-warn,
.pm-btn.no,:is(button,a).pm-btn.no,
.dispbtn.danger,:is(button,a).dispbtn.danger{
  background:var(--btn-bad-bg);color:var(--btn-bad-ink);border-color:var(--btn-bad-line);
}
.act.a-warn:hover:not(:disabled),:is(button,a).act.a-warn:hover:not(:disabled),
.pm-btn.no:hover:not(:disabled),:is(button,a).pm-btn.no:hover:not(:disabled),
.dispbtn.danger:hover:not(:disabled),:is(button,a).dispbtn.danger:hover:not(:disabled){
  background:var(--btn-bad-bg-hover);color:var(--btn-bad-ink);border-color:var(--btn-bad-line-hover);
}

/* SUCCESS — approve, use this one. Filled: it is the affirmative answer on the page. */
.btn.approve,.btn.green,.btn.ok,.btn.success,
:is(button,a).btn.approve,:is(button,a).btn.green,:is(button,a).btn.ok,:is(button,a).btn.success,
.pm-btn.use,:is(button,a).pm-btn.use{
  background:var(--ok);color:var(--on-ok,#fff);border-color:var(--ok);
}
.btn.approve:hover:not(:disabled),.btn.green:hover:not(:disabled),.btn.ok:hover:not(:disabled),.btn.success:hover:not(:disabled),
:is(button,a).btn.approve:hover:not(:disabled),:is(button,a).btn.green:hover:not(:disabled),
:is(button,a).btn.ok:hover:not(:disabled),:is(button,a).btn.success:hover:not(:disabled),
.pm-btn.use:hover:not(:disabled),:is(button,a).pm-btn.use:hover:not(:disabled){
  background:color-mix(in oklab, var(--ok) 86%, var(--ink));color:var(--on-ok,#fff);
  border-color:color-mix(in oklab, var(--ok) 72%, var(--ink));
}

/* WARN tint. */
.btn.warn,:is(button,a).btn.warn{background:var(--btn-warn-bg);color:var(--btn-warn-ink);border-color:var(--btn-warn-line)}
.btn.warn:hover:not(:disabled),:is(button,a).btn.warn:hover:not(:disabled){
  background:var(--btn-warn-bg-hover);color:var(--btn-warn-ink);border-color:var(--btn-warn-line-hover);
}

/* GHOST — nothing at rest, the secondary tint on hover. Tertiary actions in dense tables only.
   The theme toggle in a page header is styled by ops.css (header.pagebar .toggle) and is not
   reached by this rule; a bare button.toggle elsewhere is. label.toggle / div.toggle are the
   on-off switches on bflow-admin and bflow-intake and are deliberately not matched. */
.btn.ghost,:is(button,a).btn.ghost,
.act.a-ghost,:is(button,a).act.a-ghost,
:is(button,a).toggle{
  background:transparent;color:var(--ink-1);border-color:transparent;
}
.btn.ghost:hover:not(:disabled),:is(button,a).btn.ghost:hover:not(:disabled),
.act.a-ghost:hover:not(:disabled),:is(button,a).act.a-ghost:hover:not(:disabled),
:is(button,a).toggle:hover:not(:disabled){
  background:var(--btn-2-bg);color:var(--btn-2-ink);border-color:var(--btn-2-line);
}

/* The hover that reaches EVERY button, a page's own colours included: deepen in light,
   brighten in dark (--btn-hover-k), touching no colour a page chose. */
.btn:hover,.btn-sm:hover,.btn-secondary:hover,.btn-primary:hover,.act:hover,
:is(button,a).toggle:hover,.cbtn:hover,.dispbtn:hover,.sortbtn:hover,.pm-btn:hover,
.modchip:hover,.fbtn:hover,.bbtn:hover,.pager button:hover,
.bar button:hover,.qtab:hover{
  filter:brightness(var(--btn-hover-k,.93));
}
/* Press, focus, disabled — same for every tier. */
.btn:active,.btn-sm:active,.btn-secondary:active,.btn-primary:active,.act:active,
:is(button,a).toggle:active,.cbtn:active,.dispbtn:active,.sortbtn:active,.pm-btn:active,
.modchip:active,.fbtn:active,.bbtn:active,.pager button:active{
  transform:translateY(1px);
}
.btn:focus-visible,.btn-sm:focus-visible,.btn-secondary:focus-visible,.btn-primary:focus-visible,
.act:focus-visible,:is(button,a).toggle:focus-visible,.cbtn:focus-visible,.dispbtn:focus-visible,
.sortbtn:focus-visible,.pm-btn:focus-visible,.modchip:focus-visible,.fbtn:focus-visible,
.bbtn:focus-visible,.pager button:focus-visible{
  outline:1px solid var(--accent);outline-offset:0;
  box-shadow:0 0 0 4px var(--btn-ring,var(--accent-40));
}
.btn:disabled,.btn[aria-disabled="true"],.btn-sm:disabled,.btn-secondary:disabled,.btn-primary:disabled,
.act:disabled,:is(button,a).toggle:disabled,.cbtn:disabled,.cbtn[aria-disabled="true"],
.dispbtn:disabled,.sortbtn:disabled,.pm-btn:disabled,.modchip:disabled,
.fbtn:disabled,.bbtn:disabled,.pager button:disabled{
  opacity:.5;cursor:not-allowed;filter:none;transform:none;
}

/* .field is a WRAPPER — <div class="field"><label>..</label><input></div> — not a control.
   It was in this selector list with height:28px, which is smaller than label + gap + input, so
   the label rendered on top of the input. A gap cannot go negative; a fixed height can. */
input,select,textarea{
  height:var(--ctl-h,36px);padding:0 10px;
  border-radius:var(--r-control);
  border:1px solid var(--line-strong);
  background:var(--panel);
  color:var(--ink-1);
  font-size:14px;
}
/* PICK LISTS ARE DATA CONTROLS, NOT DECORATION. Several older pages paint their own white
   select while the app is in dark mode, or inherit a near-white foreground into the browser's
   native white option popup. The closed control can therefore look fine while every opened
   choice is unreadable. Keep the control, its popup rows and its groups on the same explicit
   token pair. `data-keep-native-colors` is the deliberate escape hatch for a future genuinely
   colour-coded selector; no current workflow needs it. */
select:not([data-keep-native-colors]),
select:not([data-keep-native-colors]) option,
select:not([data-keep-native-colors]) optgroup{
  background-color:var(--panel)!important;
  color:var(--ink-1)!important;
}
select:not([data-keep-native-colors]){color-scheme:light dark}
select:not([data-keep-native-colors]) option:disabled,
select:not([data-keep-native-colors]) optgroup{color:var(--ink-3)!important}
select:disabled{
  opacity:.78;
  cursor:not-allowed;
  background-color:var(--paper-2,var(--panel))!important;
  color:var(--ink-2)!important;
}
select[data-mh-picklist-state="error"]{border-color:var(--bad)!important;box-shadow:0 0 0 3px var(--bad-bg)}
select[data-mh-picklist-state="loading"]{border-color:var(--warn)!important}
select[data-mh-picklist-state="blocked"]{border-style:dashed}
.mh-picklist-status{
  display:block;margin:4px 1px 0;font-size:10px;line-height:1.35;
  color:var(--ink-3);text-transform:none;letter-spacing:0;font-weight:500;
}
.mh-picklist-status:before{content:"→ ";color:var(--structural);font-weight:800}
.mh-picklist-status[data-state="error"]{color:var(--bad)}
.mh-picklist-status[data-state="loading"]{color:var(--warn)}
.mh-picklist-status[data-state="blocked"]{color:var(--ink-2)}
/* Plain flow, and an explicit reset. `.field` is a WRAPPER around a label and its control —
   it is not itself a control, so it carries no border, no background and no height. Stated
   rather than assumed, because a control primitive once shared this class name and every field
   rendered as a box inside a box. */
.field{
  display:flex;
  flex-direction:column;
  gap:var(--space-2);
  min-width:0;
  border:0;
  background:none;
  height:auto;
  padding:0;
}
.field label{line-height:1.4;margin:0;font-size:11px}
textarea{height:auto;padding:6px 8px;line-height:1.5}
input:focus,select:focus,textarea:focus{
  border-color:var(--accent);outline:none;box-shadow:0 0 0 3px var(--accent-08);
}
input:user-invalid{border-color:var(--bad);box-shadow:0 0 0 3px var(--bad-bg)}
label{color:var(--ink-3);font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase}

/* ── state chips ──────────────────────────────────────────────────────────────────
   One family: tinted ground, same-hue text, 2px corner. The old pages used saturated pills
   at a 20px radius, which read as a traffic light next to each other. */
.pill,.badge,.chip,.tag{
  display:inline-flex;align-items:center;gap:5px;
  height:19px;padding:0 6px;
  border-radius:var(--r-badge);
  font-size:11px;font-weight:600;letter-spacing:.01em;text-transform:none;
  background:var(--idle-bg);color:var(--ink-2);border:1px solid var(--idle-line);
  white-space:nowrap;
}
.pill.ok,.badge.ok,.pill.green,.badge.green,.pill.paid,.pill.approved,.pill.active
  {background:var(--ok-bg);color:var(--ok);border-color:var(--ok-line)}
.pill.warn,.badge.warn,.pill.amber,.badge.amber,.pill.pending,.pill.hold
  {background:var(--warn-bg);color:var(--warn);border-color:var(--warn-line)}
.pill.bad,.badge.bad,.pill.red,.badge.red,.pill.denied,.pill.error,.pill.rejected
  {background:var(--bad-bg);color:var(--bad);border-color:var(--bad-line)}
.pill.info,.badge.info,.pill.blue,.badge.blue
  {background:var(--info-bg);color:var(--info);border-color:var(--info-line)}

/* ── tables ───────────────────────────────────────────────────────────────────────
   No card wrapper, no gaps, hairline dividers, 44px rows, hover is a tint. */
table{width:100%;border-collapse:collapse;font-size:13px;background:transparent}
thead th{
  text-align:left;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);padding:8px 12px;background:var(--paper);white-space:nowrap;
  box-shadow:inset 0 -1px 0 var(--line-strong);border-bottom:0;
}
tbody td{padding:0 12px;height:var(--row-h,44px);border-bottom:1px solid var(--line);vertical-align:middle;color:var(--ink-1)}
tbody tr{transition:background-color var(--exit) linear}
tbody tr:hover{background:var(--tint);color:var(--ink-1,var(--ink));transition-duration:var(--enter)}
/* Numbers right, text left. Money and counts are already mono via the rule above. */
td.num,th.num,td.money,th.money,td.right,th.right{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums}

/* ── stats ────────────────────────────────────────────────────────────────────────
   Flattened out of boxes. The hierarchy (one figure large, the rest a strip) belongs to the
   page that knows which number matters; this only removes the equal-weight card look. */
.kpis{display:flex;align-items:flex-start;gap:28px;flex-wrap:wrap;padding:4px 0 16px;margin-bottom:16px;border-bottom:1px solid var(--line)}
.kpi{background:none;border:0;border-radius:0;padding:0;box-shadow:none;min-width:64px}
.kpi .v,.kpi .n{font-family:var(--mono);font-variant-numeric:tabular-nums;font-size:15px;font-weight:600;color:var(--ink-1);line-height:1.3}
.kpi .l{font-size:11px;font-weight:600;color:var(--ink-2);text-transform:uppercase;letter-spacing:.06em;margin-top:1px}

/* ── tabs ─────────────────────────────────────────────────────────────────────────
   Underline, not a filled pill. Pills are the template tell. */
.tabs{display:flex;gap:2px;border-bottom:1px solid var(--line);flex-wrap:wrap}
.tabs .tab,.tabs button,.tabs a{
  background:none;border:0;border-radius:0;
  padding:7px 10px;font-size:12px;font-weight:500;color:var(--ink-3);cursor:pointer;
  box-shadow:inset 0 -1px 0 transparent;
}
.tabs .tab:hover,.tabs button:hover,.tabs a:hover{color:var(--ink-1)}
.tabs .tab.on,.tabs .tab.active,.tabs button.on,.tabs button.active,.tabs a.on,.tabs a.active{
  color:var(--ink-1);background:none;box-shadow:inset 0 -2px 0 var(--structural);
}

/* ── feedback ─────────────────────────────────────────────────────────────────────── */
.toast{
  border-radius:var(--r-float);
  background:oklch(18% .025 250);color:oklch(97% .010 250);
  border:1px solid oklch(100% 0 0 / .12);
  box-shadow:var(--lift);font-size:12.5px;padding:9px 12px;
}
.toast.ok{border-color:var(--ok-line)}
.toast.err{border-color:var(--bad-line)}

.empty{
  display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:40px 20px;text-align:center;color:var(--ink-3);font-size:12.5px;
}
.empty h3,.empty .h{font-size:13px;font-weight:600;color:var(--ink-2);text-wrap:balance}

/* Flat tinted blocks. A shimmer sweep is decoration, and it draws the eye to nothing. */
.skeleton{background:var(--tint-2);border-radius:2px;animation:none!important;background-image:none!important}

.login-gate{background:var(--paper);color:var(--ink-1)}

/* ── links ────────────────────────────────────────────────────────────────────────── */
a{color:var(--structural);text-decoration:none}
a:hover{color:var(--structural-hi);text-decoration:underline;text-underline-offset:2px}
:focus-visible{outline:2px solid var(--accent-40);outline-offset:1px}

/* WCAG 2.2 target size — these pages are dense with small icon buttons. */
.btn.sm,.btn-sm,.icon-btn{min-height:24px;min-width:24px}

@media (forced-colors:active){
  .pill,.badge,.chip,.tag{border:1px solid CanvasText;background:Canvas;color:CanvasText;forced-color-adjust:none}
  .btn{border:1px solid ButtonText}
}

/* ── LEGACY TOKEN ALIASES ──────────────────────────────────────────────────────────
   Measured in the browser, not guessed: these pages DO define tokens, they just define a
   LIGHT palette (--card:#ffffff, --bg:#f4f6fa, --grey:#5a6675) while rendering on a dark
   ground. That is why a search input came out white-on-white.

   Aliasing the legacy names is far better than fighting specificity page by page: one
   definition here reaches every rule that already says var(--card), and it inherits the theme
   for free. This sheet loads after each page's <style>, so at equal specificity it wins.

   Anything NOT listed here keeps whatever the page set — deliberately. This is a bridge, not
   a rewrite of 66 files. */
:root{
  --card:var(--panel);
  --bg:var(--paper);
  --panel-bg:var(--panel);
  --text:var(--ink-1);
  --grey:var(--ink-2);
  --light:var(--ink-3);
  --muted:var(--ink-3);
  --border:var(--line);
  --greybg:var(--idle-bg);
  --agentbg:var(--tint);
  --headerbg:var(--paper);

  /* One accent. The legacy sheets carried three different "primary" colours between them. */
  --navy:var(--structural);
  --accent2:var(--structural);   /* the old 'deeper accent' painted headings and header fills: structure */
  --brand:var(--structural);

  /* The state family, under whatever name each page happens to use. */
  --green:var(--ok);      --greenbg:var(--ok-bg);      --success:var(--ok);
  --amber:var(--warn);    --amberbg:var(--warn-bg);
  --red:var(--bad);       --redbg:var(--bad-bg);       --danger:var(--bad);
  --blue:var(--info);     --bluebg:var(--info-bg);
  --purple:var(--info);   --purplebg:var(--info-bg);

  /* Shadow means elevation; the legacy sheets used it as decoration on every card. */
  --shadow:transparent;
  --radius:var(--r-control);
}

/* .inp is the legacy field class — same treatment as a real input. */
.inp{
  height:var(--ctl-h,28px);padding:0 8px;
  border-radius:var(--r-control);
  border:1px solid var(--line-strong);
  background:var(--panel);
  color:var(--ink-1);
  font-family:var(--sans);font-size:12px;
}
.inp:focus{border-color:var(--accent);outline:none;box-shadow:0 0 0 3px var(--accent-08)}

/* Legacy pill modifiers seen in the wild: single letters and short words. Unmapped ones fall
   through to the neutral base above rather than to a saturated legacy colour. */
.pill.n,.pill.neutral{background:var(--idle-bg);color:var(--ink-2);border-color:var(--idle-line)}
.pill.g,.pill.good{background:var(--ok-bg);color:var(--ok);border-color:var(--ok-line)}
.pill.a{background:var(--warn-bg);color:var(--warn);border-color:var(--warn-line)}
.pill.r,.pill.b{background:var(--bad-bg);color:var(--bad);border-color:var(--bad-line)}


/* ═══ FORMS ════════════════════════════════════════════════════════════════════════
   DENSITY INVERTS HERE. The 13px/44px rules are for a queue — a surface people SCAN. A form
   is a surface people TYPE INTO, and someone entering a patient's date of birth or SSN needs
   generous targets and clear grouping, not compression. Applying the table density to a form
   was the wrong half of the brief.

     queue                  form
     44px rows              36px input, ~64px total field
     13px body              14px
     0 gap (dividers)       16px within a group, 32px between groups
     1.35 line-height       1.5
   ═══════════════════════════════════════════════════════════════════════════════════ */

form,.form,.eff{font-size:14px;line-height:1.5}

.form-grid,.grid2,.fields{
  display:grid;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:var(--space-4);
}
@media(max-width:720px){.form-grid,.grid2,.fields{grid-template-columns:minmax(0,1fr)}}
.form-section + .form-section,.sec + .sec{margin-top:var(--space-6)}

/* A shared label column. Laying each row out independently is why the inputs started at
   ragged x positions — max-content sizes the column to the longest label ONCE, and every row
   aligns on one axis for free. Labels and controls are direct children; no per-row wrapper. */
.kv-list{
  display:grid;
  grid-template-columns:max-content minmax(0,1fr);
  gap:var(--space-3) var(--space-4);
  align-items:center;
}
.kv-list > label{
  font-size:11px;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);line-height:1.4;margin:0;
}

/* A label and its value are not the same thing and should not look identical. Two sizes, two
   weights, two brightnesses — otherwise a stack of them reads as one wall of caps. */
.kv .k,.kvrow .k,.milestone .t{font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);font-weight:600}
.kv .v,.kvrow .v,.milestone .d{font-size:13px;text-transform:none;letter-spacing:0;color:var(--ink-1);font-weight:400}

/* Fill-only rectangles are hard to locate on a dark ground. Every control keeps a hairline. */
input,select,textarea,.inp{border:1px solid var(--line-strong)}


/* ═══ HARDCODED-WHITE HOLDOUTS ═════════════════════════════════════════════════════
   A half-applied theme is worse than no theme. These pages' surfaces took the dark tokens
   while these particular components kept `background:#fff` from the light palette — so
   near-white text landed on a white card and the content became invisible. On the
   transmission dashboard that hid two whole panels and the MTD/QTD/YTD chips.

   Every selector below was extracted from the pages themselves, not guessed: each one sets an
   opaque light background in its own stylesheet.

   THE DISCIPLINE THAT MAKES THIS STRUCTURALLY IMPOSSIBLE, applied here and worth keeping:
   NEVER set a background without setting a color in the same rule. A component that owns its
   surface owns its text. Every invisible element in this class of bug is a rule that set one
   and inherited the other.
   ═══════════════════════════════════════════════════════════════════════════════════ */
.ai-panel,
.bubble.partner,
.card,
.chart-card,
.clock-widget,
.col,
.controls input,
.controls select,
.detail-field,
.detail-panel,
.imgwrap,
.kpi-badge,
.modal-footer,
.modal-header,
.pill.clocked-out,
.pill.expired,
.pill.hold,
.pill.inactive,
.pipeline-bar,
.pkgpage img,
.preview-frame,
/* .qtab left this list on 2026-08-25: it is a CONTROL, not a surface. Sitting among table /
   header img / .table-card it took the page ground, so the quick-tabs on bflow-intake-command
   and outbound read as white buttons. It takes the secondary button tier above instead. */
.send,
.send input[type=file],
.send input[type=text],
.setup,
.tab,
.table-card,
.tabs-bar,
.toggle .slider:before,
.toolframe,
.tools input[type=search],
.tools select,
.wizmod,
header img,
table{
  background:var(--panel);
  color:var(--ink-1);
  border-color:var(--line-strong);
}


/* ═══ SOLID-FILL BADGES: text was matching its own background ══════════════════════
   The contrast audit returned ratio 1.00 for .badge.green / .badge.red on the transmission
   dashboard — text exactly the same colour as the fill, i.e. invisible. Those pages paint a
   saturated fill and inherit their text colour, which the theme change flipped underneath them.

   contrast-color() is the durable answer for a background the component chooses at runtime:
   the browser picks black or white against whatever the fill turns out to be, so a data-driven
   colour can never produce unreadable text again. Fallback first for anything that lacks it. */
.badge,.pill,.chip,.tag{color:var(--ink-2)}
@supports (color:contrast-color(red)){
  .badge[style*="background"],.pill[style*="background"],.chip[style*="background"]{
    color:contrast-color(currentColor);
  }
}
/* The named variants keep the tinted-ground treatment, which is legible by construction. */
.badge.green,.pill.green,.badge.ok,.pill.ok{background:var(--ok-bg)!important;color:var(--ok)!important;border:1px solid var(--ok-line)}
.badge.red,.pill.red,.badge.bad,.pill.bad{background:var(--bad-bg)!important;color:var(--bad)!important;border:1px solid var(--bad-line)}
.badge.amber,.pill.amber,.badge.warn,.pill.warn{background:var(--warn-bg)!important;color:var(--warn)!important;border:1px solid var(--warn-line)}
.badge.blue,.pill.blue,.badge.info,.pill.info{background:var(--info-bg)!important;color:var(--info)!important;border:1px solid var(--info-line)}
.badge.grey,.pill.grey,.badge.gray,.pill.gray{background:var(--idle-bg)!important;color:var(--ink-2)!important;border:1px solid var(--idle-line)}

/* Column headers and page titles were reading at 2.1:1 — these pages set their own dim colour
   on th and h1, below the token. */
thead th{color:var(--ink-3)!important}
h1,h2,h3{color:var(--ink-1)}


/* ═══ CHIPS THAT CARRY THEIR OWN BACKGROUND ════════════════════════════════════════
   Every one of these sets a background in page CSS or inline, so each must also set its text —
   the rule this file exists to enforce. The product-finder tags were the visible failure:
   .need and .sub keep pale grounds, and inherited or overridden text vanished on them.

   .brand carries an INLINE background per manufacturer (5 different browns/blues/purples), so
   its text is picked by the browser against whatever that turns out to be. */
.tags .brand{color:#fff;border:0}
@supports (color:contrast-color(red)){
  .tags .brand{color:contrast-color(currentColor)}
}
.tags .need{background:var(--info-bg);color:var(--info);border:1px solid var(--info-line)}
.tags .sub{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok-line)}
.tags .brand,.tags .need,.tags .sub{
  font-size:10px;font-weight:600;padding:1px 6px;border-radius:var(--r-badge);
  letter-spacing:.03em;text-transform:none;
}

/* Aria's shell paints section headers on a fixed dark strip and relied on an inherited white.
   Pair them explicitly so the theme cannot pull the text out from under the bar. */
.aria .hd,.hd,.sec-h,.panel-h,.card-h{color:var(--ink-1)}
.hd[style*="background"],.sec-h[style*="background"]{color:#fff}
h1,h2,h3,h4{color:var(--ink-1)}


/* ═══ CONTROL GEOMETRY, at a specificity that actually wins ════════════════════════
   These pages style controls as `.field input` (0,1,1), which beats a bare `input` (0,0,1).
   So the page kept its own padding while inheriting this sheet's height, and the text box was
   squeezed between the two — fields looked misaligned rather than merely restyled.

   Matching the specificity is the fix. Width is pinned too: nothing here set it, so a control
   fell back to its intrinsic size and columns came out ragged. */
.field input,.field select,.field textarea,
.field-grid input,.field-grid select,.field-grid textarea,
.form-grid input,.form-grid select,.form-grid textarea{
  width:100%;
  height:var(--ctl-h,36px);
  padding:0 10px;
  font-size:14px;
  font-family:var(--sans);
  border:1px solid var(--line-strong);
  border-radius:var(--r-control);
  background:var(--panel);
  color:var(--ink-1);
  box-sizing:border-box;
}
.field textarea,.field-grid textarea,.form-grid textarea{height:auto;min-height:72px;padding:8px 10px;line-height:1.5}
/* Every field in a row occupies the same height whether it holds an input or a select, so the
   grid's rows stay on one baseline. */
.field-grid,.form-grid{align-items:start}
.field{gap:var(--space-2)}
.field label{font-size:11px;line-height:1.4;margin:0;display:block}


/* ═══ FORM RHYTHM ══════════════════════════════════════════════════════════════════
   Measured on bflow-patient-create rather than guessed: the page ships gap:12px inside a group
   and margin-bottom:16px between groups, so a form of 28 fields had no rhythm — everything one
   distance apart and nothing reading as a group. The brief's values are 16 within, 32 between.

   The "uneven" half is structural: 25 two-column fields plus 3 `.field.full` spanning both, so
   sections end on odd counts and a lone field sits beside a hole. align-items:start stops those
   rows stretching to each other's height, and a min-height on the field keeps a row with a
   short label on the same baseline as one with a wrapped label. */
.field-grid,.form-grid,.fields{
  gap:var(--space-4) var(--space-4);
  align-items:start;
}
.form-section{
  padding:var(--space-5);
  margin-bottom:var(--space-6);
}
.form-section h3{
  margin:0 0 var(--space-4);
  font-size:13px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-2);
  border-bottom:0;
  padding:0 0 0 9px;
  border-left:2px solid var(--structural);
}
/* label (~15px) + gap (8px) + control (36px) ≈ 60px; the floor keeps rows aligned when one
   label wraps and its neighbour does not. */
.field{min-height:60px}
.field label{
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);line-height:1.4;
}
.field label .req{color:var(--bad)}
.field.full{grid-column:1/-1}


/* ═══ FORM: the odd-row hole, and giving the page some intent ══════════════════════
   "Off centre" is structural, not a margin. A section with an odd number of fields leaves its
   last field in the left column with a hole beside it, and the eye reads the whole block as
   shifted left. A lone trailing field now spans the row, so every section ends flush. */
.field-grid > .field:last-child:nth-child(odd),
.form-grid > .field:last-child:nth-child(odd){grid-column:1/-1}

/* Sections are numbered by the browser. A long intake form is a sequence, and the number is
   the one structural device here that encodes something true — where you are in it. */
.form-wrap,.form{counter-reset:formsec}
.form-section{counter-increment:formsec;position:relative}
.form-section h3::before{
  content:counter(formsec);
  display:inline-flex;align-items:center;justify-content:center;
  width:18px;height:18px;margin-right:8px;
  border-radius:var(--r-badge);
  background:var(--structural-12);color:var(--structural);
  font-family:var(--mono);font-size:10px;font-weight:600;letter-spacing:0;
}
.form-section h3{display:flex;align-items:center}

/* The form is the page's subject, so it gets the width. 800px forced two columns into ~370px
   each while the shell had room to spare. */
.form-wrap{max-width:1040px;padding:var(--space-5) var(--space-5) var(--space-7)}

/* A required field should be findable before you submit, not after. */
.field:has(input:required, select:required) label{color:var(--ink-2)}
.field label .req{color:var(--bad);margin-left:2px}

/* The submit stays reachable on a long form instead of living at the bottom of a scroll. */
.form-actions,.form-submit{
  position:sticky;bottom:0;z-index:5;
  display:flex;gap:var(--space-3);align-items:center;
  padding:var(--space-4) 0;
  background:linear-gradient(to top,var(--paper) 70%,transparent);
  color:var(--ink-1);
}
/* Colour, hover and radius come from the primary tier above; this is geometry only. */
.btn-primary{
  height:var(--ctl-h,36px);padding:0 20px;min-width:0;
  box-shadow:inset 0 1px 0 oklch(100% 0 0 / .18);
  font-size:13px;font-weight:500;cursor:pointer;
}
.btn-primary:hover{opacity:1}


/* ═══ THE DRAWER'S EDIT FIELDS — same defect as the patient form ═══════════════════
   The leads panel builds its editor as .eff / .efgrid / .efk / .efv, which this sheet's
   .field rules never matched, so those controls kept the old cramped geometry while everything
   around them moved. Same fix, same reasoning: pin width, height and padding together at a
   specificity that wins, and lay the rows out on ONE shared label column rather than each row
   sizing itself. */
.efgrid{
  display:grid;
  grid-template-columns:max-content minmax(0,1fr);
  gap:var(--space-3) var(--space-4);
  align-items:center;
}
.efgrid > .efk,.eff .efk{
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);line-height:1.4;margin:0;
}
.efgrid > .efv,.eff .efv{min-width:0;color:var(--ink-1)}
.eff input,.eff select,.eff textarea,
.efv input,.efv select,.efv textarea{
  width:100%;height:var(--ctl-h,36px);padding:0 10px;
  font-size:14px;font-family:var(--sans);
  border:1px solid var(--line-strong);border-radius:var(--r-control);
  background:var(--panel);color:var(--ink-1);
  box-sizing:border-box;
}
.eff textarea,.efv textarea{height:auto;min-height:72px;padding:8px 10px;line-height:1.5}
.eff label{
  display:block;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-3);line-height:1.4;margin:0 0 var(--space-2);
}
.eff .arow{gap:var(--space-3)}
.eff > * + *{margin-top:var(--space-4)}


/* Column roles, applied by ops-theme.js from the header text rather than by position. */
td.num,th.h-num{text-align:right;font-family:var(--mono);font-variant-numeric:tabular-nums;white-space:nowrap}
td.nowrap,th.h-nowrap{white-space:nowrap}
td.refcol{font-family:var(--mono);font-size:12px;white-space:nowrap}
/* A payer or product name is the one column that SHOULD wrap rather than force a scrollbar. */
tbody td{overflow-wrap:break-word}


/* ── form helpers (ops-forms.js) ─────────────────────────────────────────────────── */
.sameas{
  display:inline-flex;align-items:center;gap:8px;
  margin:0 0 var(--space-4);padding:6px 10px;
  border:1px solid var(--line-strong);border-radius:var(--r-control);
  background:var(--tint);color:var(--ink-1);
  font-size:13px;font-weight:500;cursor:pointer;text-transform:none;letter-spacing:0;
}
.sameas:hover{border-color:var(--structural);color:var(--ink-1)}
.sameas input{width:15px;height:15px;margin:0}
.fnote{font-size:11.5px;line-height:1.4;margin-top:2px}
.fnote.bad{color:var(--bad)}
.fnote.warn{color:var(--warn)}
/* A copied field is visibly not-yours-to-edit rather than silently ignoring keystrokes. */
input[readonly]{background:var(--tint);color:var(--ink-2);cursor:not-allowed}


/* ═══ STATE MODIFIERS, MAPPED SITE-WIDE ═══════════════════════════════════════════
   The faxes page was the symptom: .pill.new / .reviewed / .processed / .junk were not in this
   sheet, so they fell through to each page's own pre-restyle palette and four different states
   rendered as four shades of the same thing.

   Enumerated rather than guessed — 88 distinct state modifiers are defined across the 70 pages
   and 72 of them were unmapped. Each is grouped by WHAT IT MEANS, not by the colour the page
   used to give it:

     ok    a terminal good outcome: delivered, processed, completed, won, eligible
     warn  in flight or waiting on somebody: new, queued, sending, in_review, paused
     bad   a terminal bad outcome: failed, junk, ineligible, voided, lost, blocked
     info  a CATEGORY rather than a state: note type, payment type, EDI file type
     idle  genuinely neutral: archived, unknown, general, off

   Both halves are always set. A modifier not listed here still gets the neutral base, which is
   legible — the failure mode is a state that looks like another state, not an unstyled one. */
.pill.accepted,.badge.accepted,.chip.accepted,.tag.accepted,
.pill.clear,.badge.clear,.chip.clear,.tag.clear,
.pill.clocked-in,.badge.clocked-in,.chip.clocked-in,.tag.clocked-in,
.pill.completed,.badge.completed,.chip.completed,.tag.completed,
.pill.converted,.badge.converted,.chip.converted,.tag.converted,
.pill.delivered,.badge.delivered,.chip.delivered,.tag.delivered,
.pill.dispensed,.badge.dispensed,.chip.dispensed,.tag.dispensed,
.pill.done,.badge.done,.chip.done,.tag.done,
.pill.eligible,.badge.eligible,.chip.eligible,.tag.eligible,
.pill.live,.badge.live,.chip.live,.tag.live,
.pill.on,.badge.on,.chip.on,.tag.on,
.pill.processed,.badge.processed,.chip.processed,.tag.processed,
.pill.qualified,.badge.qualified,.chip.qualified,.tag.qualified,
.pill.ready,.badge.ready,.chip.ready,.tag.ready,
.pill.sent,.badge.sent,.chip.sent,.tag.sent,
.pill.signed,.badge.signed,.chip.signed,.tag.signed,
.pill.transmitted,.badge.transmitted,.chip.transmitted,.tag.transmitted,
.pill.won,.badge.won,.chip.won,.tag.won,
.pill.sftp,.badge.sftp,.chip.sftp,.tag.sftp{background:var(--ok-bg);color:var(--ok);border:1px solid var(--ok-line)}
.pill.accepted b,.badge.accepted b,.pill.clear b,.badge.clear b,.pill.clocked-in b,.badge.clocked-in b,.pill.completed b,.badge.completed b,.pill.converted b,.badge.converted b,.pill.delivered b,.badge.delivered b,.pill.dispensed b,.badge.dispensed b,.pill.done b,.badge.done b,.pill.eligible b,.badge.eligible b,.pill.live b,.badge.live b,.pill.on b,.badge.on b,.pill.processed b,.badge.processed b,.pill.qualified b,.badge.qualified b,.pill.ready b,.badge.ready b,.pill.sent b,.badge.sent b,.pill.signed b,.badge.signed b,.pill.transmitted b,.badge.transmitted b,.pill.won b,.badge.won b,.pill.sftp b,.badge.sftp b{color:inherit}

.pill.checking,.badge.checking,.chip.checking,.tag.checking,
.pill.contacted,.badge.contacted,.chip.contacted,.tag.contacted,
.pill.draft,.badge.draft,.chip.draft,.tag.draft,
.pill.in_review,.badge.in_review,.chip.in_review,.tag.in_review,
.pill.intake,.badge.intake,.chip.intake,.tag.intake,
.pill.new,.badge.new,.chip.new,.tag.new,
.pill.on-break,.badge.on-break,.chip.on-break,.tag.on-break,
.pill.onhold,.badge.onhold,.chip.onhold,.tag.onhold,
.pill.paused,.badge.paused,.chip.paused,.tag.paused,
.pill.processing,.badge.processing,.chip.processing,.tag.processing,
.pill.queued,.badge.queued,.chip.queued,.tag.queued,
.pill.sending,.badge.sending,.chip.sending,.tag.sending,
.pill.submitted,.badge.submitted,.chip.submitted,.tag.submitted,
.pill.yellow,.badge.yellow,.chip.yellow,.tag.yellow,
.pill.orange,.badge.orange,.chip.orange,.tag.orange,
.pill.refill,.badge.refill,.chip.refill,.tag.refill{background:var(--warn-bg);color:var(--warn);border:1px solid var(--warn-line)}
.pill.checking b,.badge.checking b,.pill.contacted b,.badge.contacted b,.pill.draft b,.badge.draft b,.pill.in_review b,.badge.in_review b,.pill.intake b,.badge.intake b,.pill.new b,.badge.new b,.pill.on-break b,.badge.on-break b,.pill.onhold b,.badge.onhold b,.pill.paused b,.badge.paused b,.pill.processing b,.badge.processing b,.pill.queued b,.badge.queued b,.pill.sending b,.badge.sending b,.pill.submitted b,.badge.submitted b,.pill.yellow b,.badge.yellow b,.pill.orange b,.badge.orange b,.pill.refill b,.badge.refill b{color:inherit}

.pill.absent,.badge.absent,.chip.absent,.tag.absent,
.pill.blocked,.badge.blocked,.chip.blocked,.tag.blocked,
.pill.damaged,.badge.damaged,.chip.damaged,.tag.damaged,
.pill.failed,.badge.failed,.chip.failed,.tag.failed,
.pill.ineligible,.badge.ineligible,.chip.ineligible,.tag.ineligible,
.pill.junk,.badge.junk,.chip.junk,.tag.junk,
.pill.lost,.badge.lost,.chip.lost,.tag.lost,
.pill.missing,.badge.missing,.chip.missing,.tag.missing,
.pill.no-sftp,.badge.no-sftp,.chip.no-sftp,.tag.no-sftp,
.pill.returned,.badge.returned,.chip.returned,.tag.returned,
.pill.voided,.badge.voided,.chip.voided,.tag.voided,
.pill.callneed,.badge.callneed,.chip.callneed,.tag.callneed{background:var(--bad-bg);color:var(--bad);border:1px solid var(--bad-line)}
.pill.absent b,.badge.absent b,.pill.blocked b,.badge.blocked b,.pill.damaged b,.badge.damaged b,.pill.failed b,.badge.failed b,.pill.ineligible b,.badge.ineligible b,.pill.junk b,.badge.junk b,.pill.lost b,.badge.lost b,.pill.missing b,.badge.missing b,.pill.no-sftp b,.badge.no-sftp b,.pill.returned b,.badge.returned b,.pill.voided b,.badge.voided b,.pill.callneed b,.badge.callneed b{color:inherit}

.pill.appointment,.badge.appointment,.chip.appointment,.tag.appointment,
.pill.billing,.badge.billing,.chip.billing,.tag.billing,
.pill.call,.badge.call,.chip.call,.tag.call,
.pill.delivery,.badge.delivery,.chip.delivery,.tag.delivery,
.pill.insurance,.badge.insurance,.chip.insurance,.tag.insurance,
.pill.kit,.badge.kit,.chip.kit,.tag.kit,
.pill.medical,.badge.medical,.chip.medical,.tag.medical,
.pill.patient,.badge.patient,.chip.patient,.tag.patient,
.pill.purple,.badge.purple,.chip.purple,.tag.purple,
.pill.rental,.badge.rental,.chip.rental,.tag.rental,
.pill.route,.badge.route,.chip.route,.tag.route,
.pill.type-835,.badge.type-835,.chip.type-835,.tag.type-835,
.pill.type-837,.badge.type-837,.chip.type-837,.tag.type-837{background:var(--info-bg);color:var(--info);border:1px solid var(--info-line)}
.pill.appointment b,.badge.appointment b,.pill.billing b,.badge.billing b,.pill.call b,.badge.call b,.pill.delivery b,.badge.delivery b,.pill.insurance b,.badge.insurance b,.pill.kit b,.badge.kit b,.pill.medical b,.badge.medical b,.pill.patient b,.badge.patient b,.pill.purple b,.badge.purple b,.pill.rental b,.badge.rental b,.pill.route b,.badge.route b,.pill.type-835 b,.badge.type-835 b,.pill.type-837 b,.badge.type-837 b{color:inherit}

.pill.archived,.badge.archived,.chip.archived,.tag.archived,
.pill.general,.badge.general,.chip.general,.tag.general,
.pill.off,.badge.off,.chip.off,.tag.off,
.pill.own,.badge.own,.chip.own,.tag.own,
.pill.own-other,.badge.own-other,.chip.own-other,.tag.own-other,
.pill.stage,.badge.stage,.chip.stage,.tag.stage,
.pill.tag,.badge.tag,.chip.tag,.tag.tag,
.pill.type,.badge.type,.chip.type,.tag.type,
.pill.unknown,.badge.unknown,.chip.unknown,.tag.unknown,
.pill.writeoff,.badge.writeoff,.chip.writeoff,.tag.writeoff{background:var(--idle-bg);color:var(--ink-2);border:1px solid var(--idle-line)}
.pill.archived b,.badge.archived b,.pill.general b,.badge.general b,.pill.off b,.badge.off b,.pill.own b,.badge.own b,.pill.own-other b,.badge.own-other b,.pill.stage b,.badge.stage b,.pill.tag b,.badge.tag b,.pill.type b,.badge.type b,.pill.unknown b,.badge.unknown b,.pill.writeoff b,.badge.writeoff b{color:inherit}


/* Two that belong nowhere tidy: a fax that has been LOOKED at but not yet actioned is in
   flight, not finished; and an alert note is the one thing on a patient record that should
   interrupt you. */
.pill.reviewed,.badge.reviewed{background:var(--info-bg);color:var(--info);border:1px solid var(--info-line)}
.pill.alert,.badge.alert{background:var(--bad-bg);color:var(--bad);border:1px solid var(--bad);font-weight:600}

/* ── Phone: a wide table scrolls INSIDE itself, never the page ─────────────────────────
   Measured 2026-08-15 at 390px: 9 of 74 pages forced horizontal page-scroll, and every
   culprit was a bare <table> (transmission-dashboard 394px over, meta-ads 268, ads 248,
   subscribers 187…). The faxes board's .tscroll wrapper is the hand-made version of this;
   the media-gated display:block form gives every unwrapped table the same behavior without
   touching 70 pages. Desktop rendering is unchanged — the rule exists only under 640px. */
@media (max-width: 640px) {
  table { display: block; overflow-x: auto; -webkit-overflow-scrolling: touch; max-width: 100%; }
}

/* ── PAGE CONTENT WRAPPER ─────────────────────────────────────────────────────────────
   One component, three widths. Before this, 33 pages each defined their own `.pg` / `.page` /
   `.wrap` / `.container` and between them used FOURTEEN different max-widths — 900, 920, 960,
   1000, 1100, 1180, 1200, 1240, 1280, 1340, 1360, 1400, 1560 and none — so the content column
   jumped every time you moved between tools.

   Three rather than one, because some of that variation was real: a dense board genuinely needs
   more room than a read-only settings page, and forcing a single number would cramp one and
   stretch the other. Three named intents can be argued about; fourteen accidents cannot.

   The page header is NOT here. The shell renders the tool's title in its own bar
   (native-app.html:772 sets #pageTitle on every route), so a title inside the page is the same words
   twice, stacked. */
.pagewrap{max-width:1200px;margin:0 auto;padding:20px 34px 60px}  /* 34px, not 24: inside the shell the tool sits directly against the nav rail, and 24 read
     as the content touching it. Mickell, 2026-08-16. */
.pagewrap.wide{max-width:none}
/* WAS 1560px. Mickell, 2026-09-04, on #patients: "all of the columns dont fit". On his 2,305px
   monitor the cap held the content column to 1,560px, so the tool threw away 745px of screen and
   THEN could not fit its own table: the 9-column patient list needs 1,571px against a 1,477px
   wrapper, so the last columns — Referral source, Updated, and the row actions — sat behind a
   sideways scrollbar inside the page.
   A max-width exists to stop a LINE OF PROSE running too long to track back to. A dense board is
   not prose; its readability comes from the columns lining up, and capping it only means the
   operator scrolls sideways to read a row they have the screen for. So `.wide` now means what it
   says. `.pagewrap` (1200) and `.narrow` (960) keep their caps, because those hold sentences. */      /* dense boards: live calls, queues, wide tables */
.pagewrap.narrow{max-width:960px}     /* reading and settings pages */

/* THE TEMPLATE PAGES HAD NO WRAPPER. Twenty-odd historical system pages share one shape — a full-width
   .top bar, then #loginGate and #mainUI with every block padded 28px on its own — and none of
   them used .pg or .pagewrap, so on a wide monitor the board ran edge to edge and read as
   crammed against the rail while every page with a wrapper sat centred beside it. Centre the
   content block itself, at the same width as .pg; the .top bar stays full-bleed, which is
   what a header is for. Pages already inside a .pagewrap are unaffected (the tighter of the
   two wins). Boards that mean to be full-bleed — faxes.html, directory.html — do not use
   #mainUI and are untouched. */
#mainUI{max-width:1240px;margin:0 auto;width:100%}

@media (max-width:640px){
  .pagewrap,.pagewrap.wide,.pagewrap.narrow{padding:14px 14px 48px}
}

/* ── PAGE BAR ─────────────────────────────────────────────────────────────────────────
   The strip at the top of a tool page. It does NOT carry the page title: the shell already
   renders that in its own header (native-app.html:772 sets #pageTitle per route), so a title here is
   the same words twice, stacked. What belongs here is what the shell cannot know — a subtitle
   that explains the tool, a live status, the page's own actions.

   Before this, twelve pages styled `header` twelve different ways: three background tokens
   (--navy, --headerbg, --b), one hardcoded rgba, two with no background at all, and subtitles
   coloured #cfe0f1 on some and var(--ink-3) on others — so the same element was light text on
   dark here and dark text on light there.

   The subtitle takes the SAME colour as the bar's own text rather than a dimmer one. A tinted
   variant has to be re-checked against every theme, and a subtitle that passes contrast on navy
   in light mode can fail on a lighter accent in dark mode. Size and weight carry the hierarchy;
   colour does not have to. */
.pagebar{
  background:var(--accent); color:var(--on-accent);
  padding:14px 22px;
  display:flex; align-items:center; justify-content:space-between;
  flex-wrap:wrap; gap:10px;
}
.pagebar .sub{font-size:12.5px;font-weight:400;color:var(--on-accent)}
.pagebar a{color:var(--on-accent)}
.pagebar .note{font-size:12px;color:var(--on-accent)}


/* ═══ ACTION BUTTONS SAY WHAT KIND OF THING THEY DO ══════════════════════════════════════════
   Measured across the console: 15 Delete buttons, 7 Save, 3 Approve, Send fax / Send SMS /
   Submit — all rendered in the identical grey chrome, so the button that texts a patient looked
   exactly like the one that closes a panel. Colour here carries MEANING and nothing else:

     .u-primary   moves the record forward (save, submit, push, approve)   — accent, filled
     .u-send      leaves the building (fax, SMS, email to a real person)   — ok green, filled:
                  outbound deserves the strongest visual commitment because it is the least
                  undoable thing on any page
     .u-danger    destroys or discards (delete, junk)                      — bad red, OUTLINED:
                  visible without shouting; a page of solid red Delete buttons trains people
                  to ignore red
     everything else stays the quiet grey it already was — a page of coloured buttons has no
     hierarchy at all, which is the disease this treats.

   Classes are applied by ops-theme.js from EXACT label matches only (the fixer-in-the-shared-
   script pattern the Escape-closes-modal fix established). Background and colour together in
   every rule; tokens carry the dark values. */
/* SPECIFICITY, measured on the running console rather than assumed.
   Written first as `.u-send,button.u-send` (0,1,1) these rules LOST to ordinary page styling:
   the faxes composer's `.send .go` is (0,2,0), so the transmit button stayed navy while carrying
   the class that was supposed to make it green, and `.u-primary` lost the same way. A class that
   is applied and then silently overridden is worse than no class at all — it reads as working in
   the DOM and does nothing on screen.

   These are a deliberate override layer: the semantic meaning outranks a page's local button
   styling by design. The class is therefore repeated to (0,3,1), which clears normal page rules
   without `!important` — leaving `!important` available to any page that genuinely needs to win
   back, which a blanket `!important` here would have taken away. */
button.u-primary.u-primary.u-primary,.u-primary.u-primary.u-primary{
  background:var(--accent);color:var(--on-accent);border:1px solid var(--accent);font-weight:600}
button.u-primary.u-primary.u-primary:hover,.u-primary.u-primary.u-primary:hover{
  background:var(--accent);color:var(--on-accent);filter:brightness(1.12)}
button.u-send.u-send.u-send,.u-send.u-send.u-send{
  background:var(--ok);color:var(--on-ok,#fff);border:1px solid var(--ok);font-weight:600}
button.u-send.u-send.u-send:hover,.u-send.u-send.u-send:hover{
  background:var(--ok);color:var(--on-ok,#fff);filter:brightness(1.12)}
/* Was outlined on var(--panel) — the last white button in the system. Now the danger TINT:
   still quieter than a solid red, still not white. */
button.u-danger.u-danger.u-danger,.u-danger.u-danger.u-danger{
  background:var(--btn-bad-bg);color:var(--btn-bad-ink);border:1px solid var(--btn-bad-line);font-weight:600}
button.u-danger.u-danger.u-danger:hover,.u-danger.u-danger.u-danger:hover{
  background:var(--btn-bad-bg-hover);color:var(--btn-bad-ink);border-color:var(--btn-bad-line-hover)}

/* ── A CELL THAT SPANS THE TABLE IS A PANEL, NOT A COLUMN ─────────────────────────────────────
 *
 * Every expandable table in this console puts its detail view in <td colspan="N">, and that one
 * cell is simultaneously :first-child and :last-child. Any rule written for "the first column"
 * or "the last column" therefore lands on it, and white-space:nowrap is the one that hurts:
 * inherited into a panel it stops policy quotes wrapping, prints grid values on top of each
 * other, and lets an auto-layout table size itself to the max-content width of a whole
 * paragraph. Measured on the fax board at 1920x911: a 5470px table inside a 1657px frame, which
 * is weeks of "I keep having to press the right key just to read things".
 *
 * Fixed per-page it comes back on the next page that grows a detail row. Both declarations are
 * defaults a spanning cell should always have had:
 *   white-space:normal  prose in a panel wraps
 *   max-width:0         removes the cell's max-content contribution, so the TABLE stops growing
 *                       to fit its longest paragraph. width:100% is a floor, not a ceiling, and
 *                       table-layout:fixed would have re-sized the real data columns as well.
 *
 * tools/console-sweep.js measures this on every page and stress-tests a spanning cell with a
 * 900-character paragraph, so a regression fails the gate rather than reaching an operator. */
td[colspan]{white-space:normal;max-width:0}

/* ...AND `.empty` MUST NOT TURN A CELL INTO A FLEX BOX.
 *
 * `.empty` above is a flex COLUMN — right for a standalone empty-state block, wrong on a table
 * cell: display:flex takes the cell out of table layout, so it stops spanning its columns, and
 * the max-width:0 directly above (which is safe and deliberate on a real table-cell, where it
 * only removes the max-content contribution) then collapses it to nothing. The message inside
 * overflows and prints down the page over whatever follows.
 *
 * Measured 2026-08-22 on alert-settings: an 892px table whose colspan=4 cell computed 40px wide,
 * with its text running over the form labels and the next heading. Reported as "still overlaps".
 * 40 cells across 8 pages carry `class="empty"` on a <td>, so this is fixed here rather than in
 * each of them — the same reasoning the rule above gives for not fixing nowrap per page.
 *
 * Specificity is equal to td[colspan] (one type + one class vs one type + one attribute), so
 * this must stay AFTER it. */
td.empty,th.empty{display:table-cell;max-width:none;text-align:center;padding:40px 20px}

/* ═══ CALM FORMS (4th pillar) — folded in from ops-forms.css so it loads with the proven sheet ═══ */
.formcalm{max-width:860px}

/* ── Sections: drop the box (works for .form-section AND .card sections). Whitespace + one
      hairline divider between sections; no border around a border. ── */
.formcalm section{
  border:0;background:none;box-shadow:none;padding:0;margin:0 0 44px;border-radius:0}
.formcalm section + section{border-top:1px solid var(--line);padding-top:36px}
/* Calm section title (was an uppercase accent-bar heading). */
.formcalm section > h3,
.formcalm section > h2{
  border-left:0;padding:0;margin:0 0 5px;
  font-size:15px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink)}
/* The contextual intro/helper sentence under a title — a muted intro line, not cramped body. */
.formcalm section > p.sub,
.formcalm section > .sec-help,
.formcalm section > .intro,
.formcalm section > p.hint{
  margin:0 0 22px;font-size:13px;line-height:1.55;color:var(--ink-3);max-width:64ch}

/* ── Even grid (kills the auto-fit wobble). Related short fields share equal-width columns. ── */
.formcalm .field-grid,
.formcalm .form-grid{
  display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:22px 24px;align-items:start}
@media (min-width:980px){
  .formcalm .field-grid,.formcalm .form-grid{grid-template-columns:repeat(3,minmax(0,1fr))}
}
@media (max-width:560px){
  .formcalm .field-grid,.formcalm .form-grid{grid-template-columns:1fr}
}
.formcalm .field.full{grid-column:1/-1}

/* ── Labels: consistent small medium caps everywhere. ── */
.formcalm .field{gap:7px;min-height:0}
.formcalm .field label{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2)}
.formcalm .field label .req{color:var(--bad)}

/* ── Inputs: soft filled (no hard resting border), radius, comfortable padding, brand focus ring. ── */
.formcalm .field input,
.formcalm .field select,
.formcalm .field textarea,
.formcalm .field-grid input,
.formcalm .field-grid select,
.formcalm .field-grid textarea{
  height:42px;padding:0 13px;font-size:14px;border-radius:10px;
  border:1px solid transparent;background:var(--tint);color:var(--ink);
  transition:border-color .12s, box-shadow .12s, background .12s}
.formcalm .field textarea,
.formcalm .field-grid textarea{height:auto;min-height:88px;padding:11px 13px;line-height:1.5}
.formcalm .field input:hover,
.formcalm .field select:hover,
.formcalm .field textarea:hover{background:var(--tint-2,var(--tint));color:var(--ink)}
.formcalm .field input:focus,
.formcalm .field select:focus,
.formcalm .field textarea:focus{
  outline:none;background:var(--panel,var(--paper));color:var(--ink);
  border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-40,var(--accent-08))}
.formcalm .field input::placeholder,
.formcalm .field textarea::placeholder{color:var(--ink-4,var(--ink-3))}

/* ── Sensitive field (SSN): masked input + a show toggle + a small muted encryption note. ── */
.formcalm .field-sens{position:relative}
.formcalm .field-sens input{padding-right:52px;letter-spacing:.08em}
.formcalm .field-sens .sens-toggle{
  position:absolute;right:6px;top:29px;height:34px;padding:0 10px;border:0;border-radius:8px;cursor:pointer;
  font:600 11px/1 var(--sans);letter-spacing:.04em;text-transform:uppercase;
  background:none;color:var(--ink-3)}
.formcalm .field-sens .sens-toggle:hover{background:var(--tint);color:var(--ink-2)}
.formcalm .enc-note{font-size:11px;line-height:1.4;color:var(--ink-3);margin-top:5px}

/* ── Sticky footer actions: primary right, Clear demoted to ghost. ── */
.formcalm .pn-foot,
.formcalm .form-actions{
  position:sticky;bottom:0;z-index:5;display:flex;justify-content:flex-end;align-items:center;gap:12px;
  margin:8px 0 0;padding:14px 4px;
  background:var(--paper);color:var(--ink);border-top:1px solid var(--line)}

/* ═══ DATATABLE (shared) — folded in from ops-datatable.css to load with the proven sheet ═══ */
/* Controls: search box + count + slots (bulk bar, view menu injected by the page). */
.dt-controls{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 0 12px}
.dt-controls input[type=search]{
  border:1px solid var(--line-strong,var(--line));border-radius:16px;padding:6px 14px;font-size:13px;width:280px;max-width:100%;
  background:var(--panel,var(--paper));color:var(--ink)}
.dt-controls input[type=search]:focus{outline:none;border-color:var(--accent);box-shadow:0 0 0 3px var(--accent-40,var(--accent-08))}
.dt-count{font-size:12px;color:var(--ink-3);margin-left:auto}

/* Scroll wrapper: overflow-x:auto enables x-scroll AND makes position:sticky;left work.
   Transparent (no background) so it needs no paired color. NEVER overflow:hidden here. */
.dt-scroll{overflow-x:auto;-webkit-overflow-scrolling:touch;border-top:1px solid var(--line)}
/* Pane mode: bounded height → wrapper owns vertical scroll → sticky header co-exists with x-scroll. */
.dt-scroll.is-pane{overflow-y:auto;max-height:var(--dt-maxh,70vh)}

.dt{width:100%;border-collapse:collapse;font-size:13px;min-width:var(--dt-min,640px);table-layout:auto}
.dt caption{text-align:left;font-size:11px;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-3);padding:0 12px 6px}

/* Header — sticky to the wrapper top (window when short, pane when maxHeight set). */
.dt thead th{
  font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;text-align:left;
  padding:8px 12px;white-space:nowrap;border-bottom:1px solid var(--line-strong,var(--line));
  position:sticky;top:0;z-index:3;
  background:var(--paper);color:var(--ink-2)}
.dt thead th.dt-sortable{cursor:pointer;user-select:none}
.dt thead th.dt-sortable:hover{background:var(--tint);color:var(--ink)}
.dt thead th .dt-arrow{margin-left:5px;font-size:10px;opacity:.9;font-variant-numeric:tabular-nums}
.dt thead th:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.dt th.dt-right,.dt td.dt-right{text-align:right}
.dt th.dt-center,.dt td.dt-center{text-align:center}

/* Body rows. Colour inherits (mirrors .tbl); rules that ADD a surface add color too. */
.dt tbody td{padding:0 12px;height:44px;vertical-align:middle;border-bottom:1px solid var(--line);color:var(--ink)}
/* Row banding + column rules — the same treatment .tbl gets in ops.css, for the same reason, so
   the two table implementations do not read as two products. See the long note there for why the
   band is painted on the ROW rather than the cell (cell-level colour rules must keep winning).
   `:not(.dt-cards)` is load-bearing: in card mode each row IS a bordered card on --card, and a
   band plus a column rule inside it draws a box in a box. It has to be on the band's own selector
   because `.dt tbody tr:nth-child(even)` would otherwise outrank `.dt.dt-cards tbody tr`. */
.dt:not(.dt-cards) tbody tr:nth-child(even){background:var(--row-alt);color:var(--ink)}
/* Element-level, so `.dt.dt-cards tbody td{border:0}` below still clears these in card mode. */
.dt tbody td,.dt thead th{border-right:1px solid var(--line-soft)}
.dt tbody td:last-child,.dt thead th:last-child{border-right:0}
.dt tbody tr:hover td{background:var(--tint-2);color:var(--ink)}
.dt tbody tr.is-selected td{background:var(--structural-08,var(--tint));color:var(--ink)}
.dt tbody tr.dt-clickable{cursor:pointer}
.dt tbody tr.dt-clickable:focus-visible{outline:2px solid var(--accent);outline-offset:-2px}
.dt-empty td{height:auto;padding:24px 12px;color:var(--ink-3);text-align:center}

/* Column shape. compact = shrink-to-content + never wrap (scrolls, never clips).
   flex = absorbs slack; its text truncates on the .dt-cell span (never the row). */
.dt th.dt-compact,.dt td.dt-compact{width:1%;white-space:nowrap}
.dt th.dt-flex{min-width:var(--dt-mw,120px)}
.dt td.dt-flex{min-width:var(--dt-mw,120px);max-width:0}
.dt td.dt-flex .dt-cell{display:block;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.dt td.dt-flex.dt-wrap .dt-cell{white-space:normal;overflow:visible}
.dt td.dt-mono,.dt th.dt-mono{font-family:var(--mono,'IBM Plex Mono',ui-monospace,monospace)}
.dt td.dt-num,.dt td.dt-dur{font-variant-numeric:tabular-nums}
.dt td.dt-dim{color:var(--ink-2)}

/* Sticky first column (freeze on x-scroll). The cell paints its own surface so the scrolled body
   does not show through — background is paired with color in each rule. */
.dt.dt-sticky1 th:first-child,.dt.dt-sticky1 td:first-child{position:sticky;left:0;z-index:2}
.dt.dt-sticky1 thead th:first-child{z-index:4;background:var(--paper);color:var(--ink-2)}
.dt.dt-sticky1 tbody td:first-child{background:var(--paper);color:var(--ink)}
/* THE FROZEN COLUMN HAS TO REPAINT EVERY ROW STATE, OPAQUELY. It is the one cell the scrolled
   body passes underneath, so its surface has to be solid — and it has to be the SAME solid the
   rest of the row is showing, or the band, the hover and the selection each stop at the freeze
   line and leave a notch. `--row-alt` / `--tint-2` / `--accent-08` are all washes, so each is
   composited over --paper here with a flat gradient layer: one paint, fully opaque, exactly the
   colour the translucent version resolves to over the same ground.
   (The hover and selected rules previously assigned the wash DIRECTLY, which made the frozen
   cell translucent for as long as it was hovered — the scrolled row showed through it.)
   Written above :hover / .is-selected at equal specificity so those still win. */
.dt.dt-sticky1 tbody tr:nth-child(even) td:first-child{
  background:linear-gradient(var(--row-alt),var(--row-alt)),var(--paper);color:var(--ink)}
.dt.dt-sticky1 tbody tr:hover td:first-child{
  background:linear-gradient(var(--tint-2),var(--tint-2)),var(--paper);color:var(--ink)}
.dt.dt-sticky1 tbody tr.is-selected td:first-child{
  background:linear-gradient(var(--structural-08,var(--tint)),var(--structural-08,var(--tint))),var(--paper);color:var(--ink)}

/* Status cell reuses the ops .badge family (.ok/.warn/.bad/.idle) — no new colors. */
.dt .dt-badge{display:inline-block;font-size:11px;font-weight:600;padding:1px 8px;border-radius:10px;line-height:1.5;white-space:nowrap;border:1px solid}
.dt .dt-badge.ok{color:var(--ok);background:var(--ok-bg);border-color:var(--ok-line,var(--ok))}
.dt .dt-badge.warn{color:var(--warn);background:var(--warn-bg);border-color:var(--warn-line,var(--warn))}
.dt .dt-badge.bad{color:var(--bad);background:var(--bad-bg);border-color:var(--bad-line,var(--bad))}
.dt .dt-badge.idle{color:var(--ink-2);background:var(--tint);border-color:var(--line)}

/* Pagination. */
.dt-pager{display:flex;align-items:center;gap:12px;justify-content:flex-end;padding:10px 12px;font-size:12px;color:var(--ink-2)}
.dt-pager button{font:inherit;border:1px solid var(--line-strong,var(--line));border-radius:6px;padding:4px 10px;cursor:pointer;
  background:var(--panel,var(--paper));color:var(--ink)}
.dt-pager button:disabled{opacity:.45;cursor:default}
.dt-pager button:not(:disabled):hover{background:var(--tint);color:var(--ink)}

/* Density — driven by the shell's data-density on <body> (Compact/Comfortable/Spacious). */
:root[data-density="sm"] .dt tbody td,body[data-density="sm"] .dt tbody td{height:34px}
:root[data-density="lg"] .dt tbody td,body[data-density="lg"] .dt tbody td{height:56px}

/* Responsive collapse — below the breakpoint each row becomes a labelled card (no data lost). */
.dt.dt-cards thead{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
.dt.dt-cards,.dt.dt-cards tbody,.dt.dt-cards tr,.dt.dt-cards td{display:block;width:auto}
.dt.dt-cards{min-width:0}
.dt.dt-cards tbody tr{border:1px solid var(--line);border-radius:10px;margin:0 0 10px;padding:6px 12px 10px;background:var(--card,var(--paper));color:var(--ink)}
.dt.dt-cards tbody td{height:auto;border:0;padding:5px 0;display:flex;gap:12px;align-items:baseline}
.dt.dt-cards tbody td::before{content:attr(data-label);flex:0 0 42%;font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-3)}
.dt.dt-cards td.dt-flex{max-width:none}
.dt.dt-cards td.dt-flex .dt-cell{white-space:normal;overflow:visible}
.dt.dt-cards td.dt-primary{font-weight:600;font-size:14px}
.dt.dt-cards td.dt-primary::before{display:none}

/* ═══ CALM FORMS — card-based sections (.card/.card-h/.card-b), so forms built on cards
   (rx builder, chart edit) get the same calm treatment as .form-section forms. ═══ */
.formcalm .card{
  border:0;background:none;box-shadow:none;padding:0;margin:0 0 40px;border-radius:0}
.formcalm .card + .card{border-top:1px solid var(--line);padding-top:32px}
.formcalm .card-h{
  border:0;background:none;padding:0;margin:0 0 14px;min-height:0;
  font-size:15px;font-weight:600;letter-spacing:0;text-transform:none;color:var(--ink)}
.formcalm .card-h span:first-child{font-weight:600}
.formcalm .card-b{padding:0;background:none;border:0}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   PAGE BANNER, FIT-TO-SCREEN AND THE STEP WIZARD
   Added 2026-09-03 to Mickell's brief: "every page should automatically fit to screen",
   "a nice banner custom artwork relative to the page", "no grainy colors or pixels — smooth
   and clean, colored buttons, arrows in place for the operator", and "ready so a new employee
   can start and use content clues with the proper verbiage of navigation."

   Three components, all here rather than in a new stylesheet because a new .css file does not
   reliably enter the build (learned 2026-08-30, the .formcalm and DataTable pillars above).
   ═════════════════════════════════════════════════════════════════════════════════════════ */

/* ── 1. THE BANNER ─────────────────────────────────────────────────────────────────────────
   Artwork is INLINE SVG, never a raster: it is drawn at whatever size the viewport is, so it
   cannot go grainy on a 4K panel or a scaled laptop, and it costs no request. The gradient is
   a soft two-stop wash of the page's own accent so each page reads as a place, not a document.
   Every rule that sets a background sets a colour in the same rule — the contrast gate refuses
   otherwise, and every invisible element in the 2026-08-13 theme bug was a rule that did not. */
.pgbanner{
  position:relative;display:flex;align-items:center;gap:18px;
  padding:16px 20px;margin:0 0 14px;border-radius:14px;overflow:hidden;
  border:1px solid var(--line);
  background:linear-gradient(107deg,var(--structural-12) 0%,var(--structural-08) 46%,var(--panel) 100%);
  color:var(--ink);
}
.pgbanner > .pgbanner-art{
  flex:0 0 auto;width:64px;height:64px;display:block;color:var(--structural);
}
.pgbanner-art svg{width:100%;height:100%;display:block}
.pgbanner-copy{min-width:0;display:flex;flex-direction:column;gap:3px}
.pgbanner-copy .eyebrow{
  font-size:11px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2);
}
.pgbanner-copy h1{margin:0;font-size:20px;line-height:1.2;font-weight:650;color:var(--ink)}
/* One sentence. If it needs two, the page is explaining itself instead of being obvious. */
.pgbanner-copy p{margin:0;font-size:13px;color:var(--ink-2);max-width:64ch}
.pgbanner-acts{margin-left:auto;display:flex;gap:8px;flex-wrap:wrap;align-items:center}
@media (max-width:720px){
  .pgbanner{gap:12px;padding:13px 14px}
  .pgbanner > .pgbanner-art{width:44px;height:44px}
  .pgbanner-copy h1{font-size:17px}
  .pgbanner-acts{margin-left:0;width:100%}
}

/* ── 2. FIT TO SCREEN ──────────────────────────────────────────────────────────────────────
   "I dont want any long pages." A page marked .fitpage is exactly the height of its frame:
   the banner and any footer stay put and only the content region scrolls. The scroll moves
   from the browser window into the part of the page that actually has more to show, so the
   operator never loses the heading they were working under.
   dvh, not vh: on mobile Safari vh includes the address bar that is about to disappear. */
html.fit, html.fit body{height:100%;overflow:hidden}
body.fitpage{
  display:grid;grid-template-rows:auto 1fr;grid-template-columns:minmax(0,1fr);
  min-height:100dvh;max-height:100dvh;
  overflow:hidden;background:var(--bg);color:var(--ink);
}
/* THE COLUMN IS DECLARED, and it has to be. Mickell, 2026-09-04: "do this next bar is glitched".
   With rows declared and no columns, the single implicit column is sized to its CONTENT, so the
   whole page column widened and narrowed as the operator moved through the estimate wizard —
   815px on step 1, where the pane holds a patient search, and 1380px on step 3, where it holds
   the line-item table. Everything inside jumped with it, the guide bar most visibly because it
   spans the full width. minmax(0,1fr) makes the column the viewport and lets each page's own
   max-width do the centring, which is what every .pagewrap already expects. */
body.fitpage > .fit-scroll{min-height:0;overflow:auto;overscroll-behavior:contain;padding-bottom:18px}
/* AND THE CHILD HAS TO FILL IT. Declaring the column was not enough: a grid item with
   `margin:0 auto` — which every .wrap and .pagewrap has, to centre itself — does NOT stretch,
   because auto margins turn stretch off. So the item sized to its own CONTENT and the page column
   still moved as the operator changed step: estimates.html was 815px on step 1 and 1380px on
   step 3. width:100% makes it fill the column; its own max-width still caps it and the auto
   margins still centre it. */
body.fitpage > main, body.fitpage > .wrap, body.fitpage > .pagewrap, body.fitpage > .shell{
  width:100%
}
/* A page that opts in but has nothing to scroll must not trap a stray scrollbar. */
body.fitpage > .fit-scroll:only-child{grid-row:1 / -1}
@media print{
  html.fit,html.fit body,body.fitpage{height:auto;max-height:none;overflow:visible;display:block}
  body.fitpage > .fit-scroll{overflow:visible}
  /* A banner is screen furniture: artwork, an eyebrow and the buttons the page header used to
     hold. On paper it wastes the top of the sheet and prints controls nobody can press.
     capability-statement.html hid its old `.pagebar` here for exactly that reason, and the
     fold replaced that bar with a banner on 100 pages without updating the rule — so the one
     document that goes to hospitals, payers and government buyers started printing its
     toolbar. One line here covers every folded page rather than one line per page. */
  .pgbanner{display:none!important}
}

/* ── 3. THE STEP WIZARD ────────────────────────────────────────────────────────────────────
   One question on screen at a time, a rail that says where you are, and arrows that say which
   way is forward. A new operator should not have to know the order of the work — the page
   should tell them, and the words on the controls should be the words they would use. */
.wizrail{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px;padding:0;list-style:none}
.wizrail .qe-stepbtn,.qe-workflow .qe-stepbtn{
  display:inline-flex;align-items:center;gap:8px;
  padding:8px 14px;border-radius:999px;cursor:pointer;
  font-size:13px;font-weight:600;line-height:1;
  border:1px solid var(--btn-2-line);background:var(--btn-2-bg);color:var(--btn-2-ink);
  transition:background .16s var(--ease-out,ease),color .16s var(--ease-out,ease),
             border-color .16s var(--ease-out,ease);
}
.qe-workflow .qe-stepbtn span{
  display:inline-grid;place-items:center;width:20px;height:20px;border-radius:999px;
  font-size:11px;font-weight:700;
  background:var(--structural-12);color:var(--ink);
}
.qe-workflow .qe-stepbtn:hover{background:var(--structural-08);color:var(--ink);border-color:var(--structural-40)}
.qe-workflow .qe-stepbtn[aria-current="step"]{
  background:var(--structural);color:var(--on-structural,#fff);border-color:var(--structural);
}
.qe-workflow .qe-stepbtn[aria-current="step"] span{background:rgba(255,255,255,.24);color:var(--on-structural,#fff)}
/* A step already completed reads as done, not as available-but-ignored. */
.qe-workflow .qe-stepbtn[data-done="1"] span::before{content:"\2713";font-size:12px}
.qe-workflow .qe-stepbtn[data-done="1"] span{font-size:0;background:var(--structural-12);color:var(--ink)}

/* One pane at a time. [hidden] is toggled in script; this makes it stick even against a
   display rule inherited from .qe-card (the hidden-attr gate checks exactly this pairing). */
.qe-pane[hidden]{display:none!important}
/* A hidden button stays hidden (2026-09-10). .btn sets display:inline-flex, which beats the
   user-agent's [hidden]{display:none}, so every status button on Estimates showed at once and
   "Mark presented" on a presented estimate answered invalid_transition. Page-local patches (the
   wizard's Back button) are subsumed by this. */
.btn[hidden],button[hidden]{display:none!important}

.qe-tabs{display:flex;gap:6px;flex-wrap:wrap;margin:10px 0 0}
.qe-tab{
  padding:7px 13px;border-radius:9px;cursor:pointer;font-size:13px;font-weight:600;
  border:1px solid var(--line);background:var(--panel);color:var(--ink-2);
}
.qe-tab[aria-selected="true"]{background:var(--structural-12);color:var(--ink);border-color:var(--structural-40)}
.qe-tab:hover{background:var(--structural-08);color:var(--ink)}

/* Arrows. The operator should never have to guess which control moves them on. */
.wiznav{
  display:flex;gap:10px;align-items:center;margin:16px 0 0;padding-top:14px;
  border-top:1px solid var(--line);color:var(--ink-2);
}
.wiznav .spacer{margin-left:auto}
.wiznav .btn .arrow{font-size:15px;line-height:1}
.wiznav .hint{font-size:12.5px;color:var(--ink-3)}

/* ops.confirm — the shared confirmation dialog (ops-theme.js). Smooth, vector, no raster. */
.opsconfirm-ov{
  position:fixed;inset:0;z-index:80;display:flex;align-items:center;justify-content:center;
  padding:18px;background:rgba(12,22,30,.55);color:var(--ink);
  backdrop-filter:blur(2px);
}
.opsconfirm-ov[hidden]{display:none!important}
.opsconfirm{
  width:100%;max-width:440px;padding:22px;border-radius:14px;
  background:var(--panel);color:var(--ink);border:1px solid var(--line);
  box-shadow:0 24px 60px rgba(0,0,0,.28);
}
.opsconfirm h2{margin:0 0 8px;font-size:17px;font-weight:650;color:var(--ink)}
.opsconfirm p{margin:0 0 18px;font-size:13.5px;line-height:1.55;color:var(--ink-2)}
.opsconfirm-acts{display:flex;gap:9px;justify-content:flex-end;flex-wrap:wrap}

/* ── THE RENTAL CHECK-IN DIALOG (rentals-checkin.js; the Rentals page and the patient chart) ──
   One dialog on two pages, so its styles live here with the other shared components rather than
   twice in two page <style> blocks. A FORM, not a queue: 13-14px, 34px controls, generous gaps.
   Every rule that sets a background sets a colour in the same rule. */
dialog.rci{
  width:min(560px,calc(100% - 32px));max-height:calc(100% - 48px);overflow:auto;
  padding:18px 20px;border:1px solid var(--line);border-radius:12px;
  background:var(--panel);color:var(--ink-1);
}
.rci h2{margin:0 0 4px;font-size:16px;font-weight:600;line-height:1.35}
.rci-sub{margin:0 0 14px;font-size:13px;line-height:1.5;color:var(--ink-2)}
.rci-box{margin:0 0 14px;padding:10px 12px 8px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1)}
.rci-box legend{padding:0 4px;font-size:12.5px;font-weight:600;color:var(--ink-2)}
/* An option is a sentence, not a field name: the global label rule (11px uppercase, tracked) is for
   field labels, so every one of its properties is set back here. */
.rci-opt{display:flex;gap:9px;align-items:flex-start;padding:5px 0;font-size:13.5px;font-weight:400;line-height:1.4;
  letter-spacing:normal;text-transform:none;color:var(--ink-1);cursor:pointer}
.rci-opt input{flex:0 0 auto;width:16px;height:16px;min-height:0;margin:2px 0 0;accent-color:var(--structural,var(--accent))}
.rci-opt small{display:block;font-size:12px;color:var(--ink-2)}
.rci-row{display:flex;gap:14px;flex-wrap:wrap;margin:0 0 14px}
.rci-l{display:flex;flex-direction:column;gap:5px;flex:1 1 200px;font-size:12.5px;font-weight:600;color:var(--ink-2)}
.rci-wide{margin:0 0 14px}
.rci-l input,.rci-l select,.rci-l textarea{
  padding:7px 9px;min-height:34px;border:1px solid var(--line-strong,var(--line));border-radius:6px;
  background:var(--card);color:var(--ink-1);font:inherit;font-size:13.5px;font-weight:400;
}
.rci-l textarea{min-height:64px;resize:vertical}
.rci-msg{margin:0 0 12px;padding:8px 10px;border:1px solid var(--bad);border-radius:8px;background:var(--bad-bg);color:var(--ink-1);font-size:13px}
.rci-msg[hidden]{display:none}
/* Pinned, not at the end of the scroll: dialog.rci is its own scroller, and with a long check-in
   the Save button sat 2000px down a 336px dialog with nothing on screen saying so (2026-09-17).
   bottom:-18px under the dialog's 18px padding is the .fos-actions convention (Chromium insets the
   sticky rectangle by the scroller's padding); the matching padding-bottom paints the strip beneath
   the buttons so scrolled content never shows through it, and margin-bottom:-18px gives that
   padding back so the row's strip sits IN the dialog's own 18px band instead of on top of it —
   without it every check-in opened 18px taller with a doubled empty band under Save (measured
   36px Save-to-edge instead of 18px, 2026-09-17; .ldlg-actions in faxes.html is the same recipe).
   Background and ink together. */
.rci-acts{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin-top:4px;
  position:sticky;bottom:-18px;padding-bottom:18px;margin-bottom:-18px;background:var(--panel);color:var(--ink-1)}
.rci-sp{flex:1 1 auto}
.rci-next{margin:6px 0 14px;padding:0;list-style:none}
.rci-next li{padding:7px 0;border-bottom:1px dashed var(--line);font-size:13.5px}

/* ── THE RESOLUTION WIZARDS AND MODALS (resolve-modal.js; Rentals, Claims, Users & access) ──────
   Hub migration 337: the lapsed-rental review, the rental billing records, the attestation review,
   who handles what. One dialog shell on three pages, so its styles live here with the other shared
   components. A FORM, not a queue: 13.5-14px, 34px controls, a step rail only where the steps are
   really sequential. Every rule that sets a background sets a colour in the same rule; state colours
   are the semantic family, never the accent (the accent is the one primary button per view).
   PERCENT, NOT vh/dvh, ON EVERY MODAL BOX (2026-09-17). The shell's "Lg" density is zoom:1.12 on
   the tool body (ops.css), and Chromium multiplies a viewport unit inside a zoomed element by the
   zoom: calc(100dvh - 24px) came out 12% taller than the frame, so this dialog's footer sat below
   the visible edge with nothing to scroll (measured: Next button 751..778 in a 760px frame). A
   percentage on a top-layer <dialog> or a position:fixed box resolves against the real viewport,
   which zoom leaves alone. Same for dialog.rci, .odx-modal, the chart's .pd-modal and every
   fixed modal in faxes.html; the page shells keep their 100dvh (body.fitpage above) because a
   document, unlike a modal, is meant to scroll. */
dialog.rw{
  width:min(820px,calc(100% - 16px));max-height:calc(100% - 24px);padding:0;overflow:hidden;
  border:1px solid var(--line);border-radius:12px;background:var(--panel);color:var(--ink-1);
}
dialog.rw::backdrop{background:rgba(12,22,30,.45);color:var(--ink-1)}
dialog.rw[open]{display:flex;flex-direction:column}
.rw-h{display:flex;gap:12px;align-items:flex-start;padding:16px 20px 10px;border-bottom:1px solid var(--line);background:var(--panel);color:var(--ink-1)}
.rw-h h2{margin:0;font-size:16px;font-weight:600;line-height:1.35}
.rw-h .rw-sub{margin:2px 0 0;font-size:12.5px;color:var(--ink-2)}
.rw-h .rw-x{margin-left:auto;flex:0 0 auto}
.rw-steps{display:flex;flex-wrap:wrap;gap:6px;margin:8px 0 0;padding:0;list-style:none;font-size:12px}
.rw-steps li{padding:3px 10px;border-radius:999px;border:1px solid var(--line);background:var(--panel);color:var(--ink-2)}
.rw-steps li[aria-current="step"]{border-color:var(--structural,var(--accent));background:var(--structural-12,var(--panel));color:var(--ink-1);font-weight:600}
.rw-steps li[data-done="1"]{color:var(--ink-1)}
.rw-b{flex:1 1 auto;overflow:auto;padding:14px 20px;font-size:13.5px;line-height:1.5}
.rw-f{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:12px 20px;border-top:1px solid var(--line);background:var(--panel);color:var(--ink-1)}
.rw-f .rw-sp{flex:1 1 auto}
.rw-f .rw-note{font-size:12.5px;color:var(--ink-2)}
.rw-msg{margin:0 0 12px;padding:8px 10px;border:1px solid var(--bad);border-radius:8px;background:var(--bad-bg);color:var(--ink-1);font-size:13px}
.rw-msg.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ink-1)}
.rw-msg[hidden]{display:none}

/* SCROLL CUES ON EVERY MODAL SCROLLER (2026-09-17). "Didn't see the scroll option": with macOS
   "show scrollbars when scrolling" — or any overlay-scrollbar setting — a modal that scrolls looks
   exactly like one that does not, and a button past the fold might as well not exist. None of the
   modal scrollers styled their scrollbar (the only scrollbar rules in the tree HID one, on the tab
   strips). A custom -webkit scrollbar is the one thing Chromium and Safari always PAINT, never
   overlay, so these scrollers get a permanent 12px track and a thumb in --ink-3 — never the accent.
   TWO RULE SETS, KEPT APART ON PURPOSE: Chromium 121+ discards ::-webkit-scrollbar* on any element
   that also sets scrollbar-width or scrollbar-color (pixel-measured here on Chromium 151: 0 custom
   thumb pixels once the standard pair was present), so the standard pair lives under @supports not
   selector(::-webkit-scrollbar) and reaches only engines with no -webkit pseudo-element, i.e.
   Firefox. scrollbar-gutter:stable keeps the width from jumping when content grows past the fold.
   Every rule that sets a background sets its ink beside it — the thumb is painted in --ink-3, so
   the ink that belongs on it is the panel colour, and that is the pair the gate measures. */
.rw-b,.rci,.ai-panel.show,.post-push-sheet,.fos-backdrop,.pd-modal-body,.cap-body,.odx-modal-b,.fax-action-fields,.flowdlg-fields,.ldlg-side{scrollbar-gutter:stable}
.rw-b::-webkit-scrollbar,.rci::-webkit-scrollbar,.ai-panel.show::-webkit-scrollbar,.post-push-sheet::-webkit-scrollbar,.fos-backdrop::-webkit-scrollbar,.pd-modal-body::-webkit-scrollbar,.cap-body::-webkit-scrollbar,.odx-modal-b::-webkit-scrollbar,.fax-action-fields::-webkit-scrollbar,.flowdlg-fields::-webkit-scrollbar,.ldlg-side::-webkit-scrollbar{width:12px;background:var(--panel);color:var(--ink-1)}
.rw-b::-webkit-scrollbar-thumb,.rci::-webkit-scrollbar-thumb,.ai-panel.show::-webkit-scrollbar-thumb,.post-push-sheet::-webkit-scrollbar-thumb,.fos-backdrop::-webkit-scrollbar-thumb,.pd-modal-body::-webkit-scrollbar-thumb,.cap-body::-webkit-scrollbar-thumb,.odx-modal-b::-webkit-scrollbar-thumb,.fax-action-fields::-webkit-scrollbar-thumb,.flowdlg-fields::-webkit-scrollbar-thumb,.ldlg-side::-webkit-scrollbar-thumb{background:var(--ink-3,#8a94a6);border:3px solid var(--panel);border-radius:8px;color:var(--panel)}
@supports not selector(::-webkit-scrollbar){
  .rw-b,.rci,.ai-panel.show,.post-push-sheet,.fos-backdrop,.pd-modal-body,.cap-body,.odx-modal-b,.fax-action-fields,.flowdlg-fields,.ldlg-side{scrollbar-width:thin;scrollbar-color:var(--ink-3,#8a94a6) var(--panel)}
}
.rw-box{margin:0 0 14px;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1)}
.rw-box > h3{margin:0 0 6px;font-size:13.5px;font-weight:600}
.rw-box.warn{border-color:var(--warn);background:var(--warn-bg);color:var(--ink-1)}
.rw-box.bad{border-color:var(--bad);background:var(--bad-bg);color:var(--ink-1)}
.rw-box.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ink-1)}
.rw-small{font-size:12.5px;color:var(--ink-2)}
.rw-row{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin:0 0 10px}
.rw-l{display:flex;flex-direction:column;gap:5px;flex:1 1 180px;font-size:12.5px;font-weight:600;letter-spacing:normal;text-transform:none;color:var(--ink-2)}
.rw-l input,.rw-l select,.rw-l textarea{padding:7px 9px;min-height:34px;border:1px solid var(--line-strong,var(--line));border-radius:6px;
  background:var(--card);color:var(--ink-1);font:inherit;font-size:13.5px;font-weight:400}
.rw-l textarea{min-height:60px;resize:vertical}
.rw-opt{display:flex;gap:9px;align-items:flex-start;padding:5px 0;font-size:13.5px;font-weight:400;line-height:1.4;
  letter-spacing:normal;text-transform:none;color:var(--ink-1);cursor:pointer}
.rw-opt input{flex:0 0 auto;width:16px;height:16px;min-height:0;margin:2px 0 0;accent-color:var(--structural,var(--accent))}
.rw-opt small{display:block;font-size:12px;color:var(--ink-2)}
/* PATIENT CATEGORIES (Hub migration 371, public/patient-categories.js): the chart header row -- category
   chips, then label chips -- and its editor. A category is information-toned, a label is neutral; an
   automatic category says so in words ("auto"), not only in colour. */
.pcat-row{display:flex;flex-wrap:wrap;align-items:center;gap:6px 8px;margin-top:12px;font-size:13px;color:var(--ink-1)}
.pcat-row[hidden]{display:none}
.pcat-h{margin-right:2px;font-size:11px;font-weight:600;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}
.pcat-list{display:flex;flex-wrap:wrap;gap:6px}
.pcat-chip{display:inline-flex;align-items:center;gap:6px;max-width:280px;padding:3px 10px;border:1px solid var(--info-line);
  border-radius:999px;background:var(--info-bg);color:var(--ink-1);font-size:12px;font-weight:600;line-height:1.35;overflow-wrap:anywhere}
.pcat-chip.lab{border-color:var(--line-strong,var(--line));background:var(--panel);color:var(--ink-1);font-weight:500}
.pcat-chip.lab.gone{text-decoration:line-through;background:var(--panel);color:var(--ink-2)}
.pcat-chip.lab.new{border-style:dashed;background:var(--panel);color:var(--ink-1)}
.pcat-chip .btn{min-height:24px;padding:0 8px;font-size:12px}
.pcat-auto{font-size:10.5px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2)}
.pcat-none{font-size:12.5px;color:var(--ink-2)}
.pcat-edit{margin-left:2px}
.pcat-grid{display:grid;grid-template-columns:repeat(auto-fill,minmax(230px,1fr));gap:2px 16px}
.pcat-optnote{display:block;font-size:12px;font-weight:400;color:var(--ink-2)}
.pcat-labels{display:flex;flex-wrap:wrap;gap:6px;margin:0 0 10px}
.pcat-addrow{margin:0}
.rw-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1);margin:0 0 12px}
.rw-t{width:100%;border-collapse:collapse;font-size:12.5px}
.rw-t th{text-align:left;font-size:11px;letter-spacing:.03em;text-transform:uppercase;padding:6px 8px;background:var(--panel);color:var(--ink-2);box-shadow:inset 0 -1px 0 var(--line);white-space:nowrap}
.rw-t td{padding:6px 8px;border-bottom:1px solid var(--line);vertical-align:top}
.rw-t tr:last-child td{border-bottom:0}
.rw-t td small{display:block;font-size:11.5px;color:var(--ink-2)}
.rw-t .rw-chip{white-space:normal}
.rw-t td.num,.rw-t th.num{text-align:right;font-variant-numeric:tabular-nums;white-space:nowrap}
.rw-chip{display:inline-block;padding:1px 8px;border-radius:999px;font-size:11.5px;font-weight:600;border:1px solid var(--line);background:var(--panel);color:var(--ink-1);white-space:nowrap}
.rw-chip.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ink-1)}
.rw-chip.warn{border-color:var(--warn);background:var(--warn-bg);color:var(--ink-1)}
.rw-chip.bad{border-color:var(--bad);background:var(--bad-bg);color:var(--ink-1)}
.rw-chip.info{border-color:var(--structural,var(--accent));background:var(--structural-12,var(--panel));color:var(--ink-1)}
.rw-quote{margin:0 0 12px;padding:10px 12px;border-left:3px solid var(--structural,var(--accent));background:var(--structural-08,var(--card));color:var(--ink-1);font-size:13px}
.rw-ev{margin:4px 0 0;padding:0;list-style:none}
.rw-ev li{display:flex;gap:8px;align-items:flex-start;padding:3px 0;font-size:12.5px}
.rw-ev .have{color:var(--ok);font-weight:700}
.rw-ev .miss{color:var(--bad);font-weight:700}
.rw-sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0}
.rw-queue{width:100%;border-collapse:collapse;font-size:13px}
.rw-queue th{text-align:left;font-size:11px;letter-spacing:.03em;text-transform:uppercase;padding:8px 10px;background:var(--panel);color:var(--ink-2);box-shadow:inset 0 -1px 0 var(--line)}
.rw-queue td{padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:top}
.rw-queue td small{display:block;font-size:12px;color:var(--ink-2)}
.rw-kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:10px;margin:0 0 12px}
.rw-kpi{padding:10px 12px;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink-1)}
.rw-kpi b{display:block;font-size:19px;font-weight:650;font-variant-numeric:tabular-nums}
.rw-kpi small{display:block;margin-top:2px;font-size:12px;color:var(--ink-2)}
/* CHANGE HOW THIS IS BILLED and the account's paperwork (billing-switch.js, billing.html; Hub
   migration 360). Built on dialog.rw; the only accent in the wizard is the step rail's current step. */
.bs-list{margin:4px 0 0;padding:0 0 0 18px;font-size:13px;color:var(--ink-1);background:transparent}
.bs-list li{margin:3px 0}
.bs-list small{display:block;font-size:12px;color:var(--ink-2);background:transparent}
.bs-legend{padding:0 4px;font-size:13.5px;font-weight:600;color:var(--ink-1);background:transparent}
fieldset.rw-box{min-width:0}
.bs-price{width:96px;padding:6px 8px;min-height:34px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--card);color:var(--ink-1);font-size:13px;text-align:right;font-variant-numeric:tabular-nums}
.bs-signed{margin:0 0 6px;font-size:13.5px;color:var(--ink-1);background:transparent}
.bs-timeline{margin:0;padding:0;list-style:none}
.bs-timeline li{padding:6px 0 6px 12px;border-left:2px solid var(--line-strong,var(--line));font-size:13px;color:var(--ink-1);background:transparent}
.bs-timeline li small{display:block;font-size:12px;color:var(--ink-2);background:transparent}
.bs-paper{display:grid;gap:10px}
.bs-paper .rw-row{margin:6px 0 0}
.bs-doc{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1)}
.bs-doc b{font-weight:600}
.bs-doc .rw-sp{flex:1 1 auto}
.bs-lines .bs-k{display:none}
@media (max-width:640px){
  .bs-price{width:100%;max-width:140px}
  /* On a phone each line is a small card: the tick, then the item, where it was found, the change
     and the price stacked, so the price box is never scrolled off to the side. */
  .bs-lines thead{display:none}
  .bs-lines tr{display:grid;grid-template-columns:28px minmax(0,1fr);gap:4px 8px;padding:8px 10px;border-bottom:1px solid var(--line)}
  .bs-lines tr:last-child{border-bottom:0}
  .bs-lines td{display:block;padding:0;border:0;text-align:left;white-space:normal}
  .bs-lines td:first-child{grid-row:1 / span 4}
  .bs-lines td.num{text-align:left}
  .bs-lines .bs-k{display:inline;color:var(--ink-2);background:transparent;font-size:12px}
  dialog.rw.bs{overflow-x:hidden}
}
@media (max-width:640px){
  dialog.rw{width:100%;max-width:100%;max-height:100%;height:100%;border-radius:0}
  .rw-h,.rw-b,.rw-f{padding-left:12px;padding-right:12px}
}
/* A SHORT FRAME GETS THE FULL HEIGHT TOO (2026-09-17). The full-bleed rule above is width-only,
   tuned for a phone: at 200% on a 1280 laptop the frame is 640px wide and catches it by one pixel;
   at 175% (731px) or on a 1366 laptop at 200% (683px) it does not, and the wizard floats in a
   ~360px-tall frame giving 24px of it back to the gutter. Height is what a zoomed laptop trips —
   .ai-panel in faxes.html has had (max-height:880px) since 2026-08-26 — so this is the height
   half, and ONLY the height half: no width, no padding change, because a wide-but-short desktop
   must not get an 820px wizard stretched across 1300px. The threshold is the tool iframe, which
   is 40px shorter than the window: a 1366x768 laptop at 100% lands around 560-605px and must
   never trip this; 125% zoom on the same laptop lands at ~474px and should. */
@media (max-height:500px){
  dialog.rw{max-height:100%;height:100%;border-radius:0}
}

/* ── ORDERS GET A HOME (order-home.js; the chart's Orders tab, orders.html, the order modal) ────
   2026-09-13. A QUEUE where it lists (13px, scanning rows) and the rw- dialog where it acts. The
   group chip is the semantic family (rw-chip); the accent is only the one primary button per view
   (the next step in the modal, nothing on a row). Every rule that sets a background sets a colour. */
.oh-bar{display:flex;gap:10px;align-items:center;flex-wrap:wrap;margin:0 0 6px}
.oh-sp{flex:1 1 auto}
.oh-lede{margin:0 0 10px}
.oh-toggle{display:inline-flex;gap:6px;align-items:center;font-size:12.5px;font-weight:500;letter-spacing:normal;text-transform:none;color:var(--ink-2)}
.oh-nextact{margin-top:6px}
.oh-toggle input{accent-color:var(--structural,var(--accent))}
.oh-wrap{overflow-x:auto;border:1px solid var(--line);border-radius:8px;background:var(--card,var(--panel));color:var(--ink-1)}
.oh-table{width:100%;border-collapse:collapse;font-size:13px}
.oh-table th{text-align:left;font-size:11px;letter-spacing:.03em;text-transform:uppercase;padding:8px 10px;background:var(--panel);color:var(--ink-2);box-shadow:inset 0 -1px 0 var(--line);white-space:nowrap}
.oh-table td{padding:8px 10px;border-bottom:1px solid var(--line);vertical-align:top}
.oh-table tr:last-child td{border-bottom:0}
.oh-table td small{display:block;font-size:12px;color:var(--ink-2)}
.oh-table td.oh-ref{white-space:nowrap}
.oh-table td.oh-next{min-width:180px;max-width:280px}
.oh-table td.oh-acts{text-align:right;white-space:nowrap}
.oh-table td.oh-items{min-width:165px}
.oh-table td.oh-docs-cell{min-width:120px}
.oh-table td.oh-linked-cell{min-width:120px}
.oh-table td.oh-held{min-width:90px}
.oh-table td.oh-wait,.oh-table th.oh-wait{white-space:nowrap}
.oh-table td.oh-wait b{font-variant-numeric:tabular-nums;font-weight:600}
.oh-table .oh-who{margin:2px 0 0;font-size:12.5px;color:var(--ink-1)}
.oh-table small.oh-pays{margin-top:4px;font-weight:600;color:var(--ink-1)}
.oh-table td.num,.oh-table th.num{text-align:right;font-variant-numeric:tabular-nums}
.oh-table tr.oh-focus td{background:var(--structural-08,var(--panel));color:var(--ink-1)}
.oh-muted{font-size:12px;color:var(--ink-2)}
.oh-link{padding:0;border:0;background:none;color:var(--structural,var(--accent));font:inherit;font-weight:600;cursor:pointer;text-decoration:underline;text-underline-offset:2px}
.oh-link:focus-visible{outline:2px solid var(--structural,var(--accent));outline-offset:2px}
.oh-nextbox{margin:0 0 12px;padding:12px 14px;border:1px solid var(--line);border-radius:10px;background:var(--card,var(--panel));color:var(--ink-1)}
.oh-nextbox.warn{border-color:var(--warn);background:var(--warn-bg);color:var(--ink-1)}
.oh-nextbox.bad{border-color:var(--bad);background:var(--bad-bg);color:var(--ink-1)}
.oh-nextbox.ok{border-color:var(--ok);background:var(--ok-bg);color:var(--ink-1)}
.oh-nextbox.info{border-color:var(--structural,var(--accent));background:var(--structural-08,var(--panel));color:var(--ink-1)}
.oh-nexth{display:flex;gap:8px;align-items:center;flex-wrap:wrap;margin:0 0 6px;font-size:14px}
.oh-nextbox .btn{margin-top:4px}
.oh-others{display:flex;gap:8px;flex-wrap:wrap;margin:0 0 14px}
.oh-kv{display:grid;grid-template-columns:repeat(auto-fit,minmax(150px,1fr));gap:8px 14px;margin:8px 0 0}
.oh-kv span{display:block;font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--ink-2)}
.oh-kv b{display:block;font-size:13px;font-weight:600;color:var(--ink-1)}
.oh-docs{display:grid;gap:6px}
.oh-doc{display:flex;gap:8px;align-items:baseline;flex-wrap:wrap;font-size:13px}
.oh-doc > span:first-child{min-width:170px;font-weight:600}
.oh-doc small{flex:1 1 100%;font-size:12px;color:var(--ink-2)}
.oh-linked{display:grid;grid-template-columns:repeat(auto-fit,minmax(200px,1fr));gap:10px 16px}
.oh-linked > div > span{display:block;font-size:11px;letter-spacing:.03em;text-transform:uppercase;color:var(--ink-2);margin:0 0 3px}
.oh-linked small{font-size:12px;color:var(--ink-2)}
.oh-timeline{margin:0;padding:0;list-style:none}
.oh-timeline li{padding:5px 0;border-bottom:1px dashed var(--line);font-size:13px}
.oh-timeline li small{display:block;font-size:11.5px;color:var(--ink-2)}
.oh-groups{display:flex;flex-wrap:wrap;gap:8px;margin:0 0 12px}
.oh-group{display:inline-flex;gap:8px;align-items:center;padding:7px 12px;border:1px solid var(--line-strong,var(--line));border-radius:999px;background:var(--card,var(--panel));color:var(--ink-1);font-size:13px;cursor:pointer}
.oh-group b{font-variant-numeric:tabular-nums}
.oh-group[aria-pressed="true"]{border-color:var(--structural,var(--accent));background:var(--structural,var(--accent));color:var(--on-structural,var(--on-accent,#fff))}
.oh-group:focus-visible{outline:2px solid var(--structural,var(--accent));outline-offset:2px}
.oh-pager{display:flex;gap:8px;align-items:center;justify-content:flex-end;margin:10px 0 0;font-size:13px;color:var(--ink-2)}
.oh-toast{position:fixed;left:0;right:0;bottom:24px;margin:0 auto;width:max-content;max-width:min(600px,calc(100vw - 32px));z-index:10000;
  padding:10px 16px;border:1px solid var(--ok);border-radius:10px;background:var(--panel);color:var(--ink-1);box-shadow:0 6px 24px rgba(12,22,30,.18);font-size:13.5px;line-height:1.45}
.oh-toast.bad{border-color:var(--bad);background:var(--panel);color:var(--ink-1)}
@media (max-width:760px){
  /* On a phone a row is a card: every cell on its own line, the label-free layout reads top-down. */
  .oh-table thead{display:none}
  .oh-table,.oh-table tbody,.oh-table tr,.oh-table td{display:block;width:100%}
  .oh-table tr{border-bottom:1px solid var(--line);padding:6px 0}
  /* The queue density gives every td a fixed 44px row height; as a block that height clips and the
     next cell draws over it. A card's cell is as tall as what it says. */
  .oh-table td{border-bottom:0;padding:4px 10px;height:auto;min-height:0}
  .oh-table td.oh-acts{text-align:left}
  .oh-table td.oh-next{max-width:none}
}

/* ── The Medicare hold backlog (Hub 2026-09-14; public/hold-backlog.js), a view of the Orders board ──
   A QUEUE (13px rows) for the list, the RWModal FORM rules inside the wizards. Every rule that sets a
   background sets a colour in the same rule; state is the semantic family (ok/warn/bad), never the
   accent; the view switch is where-you-are, so it takes the structural colour like the group chips. */
.hb-views{display:inline-flex;gap:0;margin:0 0 14px;border:1px solid var(--line-strong,var(--line));border-radius:999px;overflow:hidden;background:var(--card,var(--panel));color:var(--ink-1)}
.hb-view{padding:7px 14px;border:0;background:var(--card,var(--panel));color:var(--ink-1);font:inherit;font-size:13px;font-weight:500;cursor:pointer}
.hb-view + .hb-view{border-left:1px solid var(--line-strong,var(--line))}
.hb-view[aria-pressed="true"]{background:var(--structural,var(--accent));color:var(--on-structural,var(--on-accent,#fff))}
.hb-view:focus-visible{outline:2px solid var(--structural,var(--accent));outline-offset:2px}
.hb-bar{display:flex;gap:12px;align-items:flex-start;flex-wrap:wrap;margin:0 0 10px}
.hb-lede{flex:1 1 380px;margin:0;font-size:13px;line-height:1.5;color:var(--ink-2)}
.hb-lede b{color:var(--ink-1)}
.hb-filters{display:flex;gap:12px;flex-wrap:wrap;align-items:flex-end;margin:0 0 10px}
.hb-filters .hb-f{flex:0 1 190px}
.hb-filters .hb-q{flex:1 1 220px}
.hb-table td.hb-cov{min-width:170px;max-width:260px}
.hb-table td.hb-verdict{min-width:190px;max-width:300px}
.hb-table td.hb-order{min-width:120px}
.hb-table .hb-item{margin:0 0 3px;font-size:12.5px;line-height:1.45}
.hb-table small.hb-ref{white-space:nowrap}
.hb-table td.hb-verdict .btn{white-space:normal;text-align:left}
.hb-itembox{margin:0 0 10px;padding:8px 10px;border:1px solid var(--line);border-radius:8px;background:var(--card,var(--panel));color:var(--ink-1)}
.hb-itemh{font-size:13.5px}
.hb-itemh small{display:block;font-size:12px;color:var(--ink-2)}
.hb-reqs{margin:6px 0 0;padding:0;list-style:none}
.hb-reqs li{padding:4px 0;border-top:1px dashed var(--line);font-size:13px;line-height:1.45}
.hb-reqs li:first-child{border-top:0}
.hb-reqs li small{display:block;font-size:12px;color:var(--ink-2)}
.hb-reqs li .btn{margin-left:6px}
.hb-list{margin:4px 0 8px 18px;padding:0;font-size:13px;line-height:1.5}
.hb-list li{margin:2px 0}
.hb-num{width:72px;min-height:32px;padding:4px 6px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--card,var(--panel));color:var(--ink-1);font:inherit;font-size:13px}
.hb-mods{width:96px;min-height:32px;padding:4px 6px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--card,var(--panel));color:var(--ink-1);font:inherit;font-size:13px;text-transform:uppercase}
.hb-bt td select{min-height:32px;padding:4px 6px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--card,var(--panel));color:var(--ink-1);font:inherit;font-size:13px}
.hb-bt td input[type="date"]{min-height:32px;padding:4px 6px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--card,var(--panel));color:var(--ink-1);font:inherit;font-size:13px}
@media (max-width:760px){
  .hb-views{display:flex;width:100%}
  .hb-view{flex:1 1 50%}
  .hb-table td.hb-cov,.hb-table td.hb-verdict{max-width:none}
}

/* Belt and braces for the nested-page rule in ops-theme.js: if the script has not run yet, the
   attribute is absent and nothing changes; once it is set the banner cannot flash in first. */
:root[data-embedded] .pgbanner{display:none!important}

/* ── Referral network chip + write-back wizard (Hub migration 350; public/referral-access.js) ──
   A component that owns its surface owns its text: every background here is paired with a colour.
   The chip is a quiet card; nothing in it takes the view's accent. */
.rpa{border:1px solid var(--line);border-radius:8px;padding:8px 10px;margin:6px 0;background:var(--card,var(--panel));color:var(--ink-1)}
.rpa-row{display:flex;flex-wrap:wrap;gap:4px 10px;align-items:baseline;font-size:12.5px;line-height:1.45}
.rpa-tag{font-size:11.5px;font-weight:600;padding:1px 8px;border-radius:999px;border:1px solid var(--line-strong);background:var(--panel);color:var(--ink-1)}
.rpa-id{font-variant-numeric:tabular-nums;color:var(--ink-1)}
.rpa-when{color:var(--ink-2)}
.rpa-when.gone,.rpa-warn{color:var(--warn)}
.rpa-sub{color:var(--ink-2)}
.rpa-val{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:12.5px;padding:1px 6px;border-radius:4px;background:var(--sunk,var(--panel));color:var(--ink-1)}
.rpa-acts{display:flex;flex-wrap:wrap;gap:6px;align-items:center;margin-top:6px}
.rpa-last{margin-top:6px;font-size:12px;color:var(--ink-2)}
.rpa-note{font-size:12.5px;line-height:1.45;color:var(--ink-2)}
/* Item rows use the modal's own option style (.rw-opt: sentence case, 13.5px), never the field-label casing. */
.rpa-items .rw-opt{font-weight:500}
.rpa-msg{width:100%;min-height:220px;font:inherit;font-size:13.5px;line-height:1.5;padding:8px 10px;border:1px solid var(--line-strong);border-radius:6px;background:var(--panel);color:var(--ink-1);box-sizing:border-box}
.rpa-steps{margin:4px 0 8px 18px;padding:0;font-size:13.5px;line-height:1.5}
.rpa-days{width:60px;height:32px;padding:0 6px;border:1px solid var(--line-strong);border-radius:6px;background:var(--panel);color:var(--ink-1)}
.rpa-mount[hidden]{display:none}

/* ═══ FACILITY ORDERS (Hub migration 376) — the wizard and the order drawer, inside dialog.rw ═══
   facility-orders.js renders these on the Facility orders page and on the chart. Forms keep the
   .formcalm scale (14px, generous controls) but with modal-sized gaps; the lines grid scrolls
   sideways on a phone instead of clipping. Every rule that paints a surface names its text. */
.fo-form.formcalm{max-width:none}
.fo-form.formcalm section{margin:0 0 20px}
.fo-form.formcalm section + section{padding-top:18px}
.fo-form.formcalm section > p.sub{margin:0 0 14px}
.fo-form.formcalm .field-grid{gap:16px 18px}
.fo-help{display:block;font-size:12px;line-height:1.45;color:var(--ink-2)}
.fo-vh{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.fo-acts{display:flex;gap:8px;flex-wrap:wrap;align-items:center;margin:10px 0 0}
.fo-picked{display:flex;gap:12px;align-items:center;flex-wrap:wrap;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--panel);color:var(--ink-1);font-size:14px}
.fo-search{display:flex;gap:8px;flex-wrap:wrap}
.fo-search input{flex:1 1 220px;min-width:0;height:40px;padding:0 12px;font-size:14px;border:1px solid var(--line-strong,var(--line));border-radius:8px;background:var(--panel);color:var(--ink-1)}
.fo-hits{display:flex;flex-direction:column;gap:6px;margin:10px 0 0}
.fo-hit{display:block;width:100%;text-align:left;padding:8px 12px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1);font:inherit;font-size:13.5px;cursor:pointer}
.fo-hit:hover,.fo-hit:focus-visible{border-color:var(--structural,var(--accent));background:var(--panel);color:var(--ink-1)}
.fo-hit small{display:block;font-size:12px;color:var(--ink-2)}
.fo-sub{margin:12px 0 0;padding:14px;border:1px solid var(--line);border-radius:10px;background:var(--card);color:var(--ink-1)}
.fo-sub[hidden],.fo-panel[hidden]{display:none}
.fo-lines{display:flex;flex-direction:column;gap:10px}
.fo-line{display:grid;grid-template-columns:minmax(150px,1fr) 88px 112px 60px 96px 96px auto;grid-template-areas:"desc hcpcs kind qty rate cost rm" "spec spec spec vend vend vend vend";gap:8px 8px;align-items:end;padding:10px 12px;border:1px solid var(--line);border-radius:8px;background:var(--card);color:var(--ink-1)}
.fo-lc{display:flex;flex-direction:column;gap:4px;min-width:0}
.fo-lc label{font-size:11px;font-weight:600;letter-spacing:.04em;text-transform:uppercase;color:var(--ink-2)}
.fo-lc input,.fo-lc select,.fo-lc textarea{width:100%;min-width:0;padding:0 9px;font:inherit;font-size:14px;border:1px solid var(--line-strong,var(--line));border-radius:6px;background:var(--panel);color:var(--ink-1)}
.fo-lc input,.fo-lc select{height:36px}
.fo-lc textarea{min-height:58px;padding:7px 9px;line-height:1.45;resize:vertical}
.fo-lc textarea.fo-vendor-in{border-style:dashed;border-color:var(--warn)}
.fo-lc input.fo-qty,.fo-lc input.fo-amt{text-align:right;font-variant-numeric:tabular-nums}
.fo-lc input.fo-code{text-transform:uppercase}
.fo-lc input.fo-code::placeholder{text-transform:none}
.fo-lc-description{grid-area:desc}.fo-lc-hcpcs{grid-area:hcpcs}.fo-lc-kind{grid-area:kind}.fo-lc-qty{grid-area:qty}
.fo-lc-rate{grid-area:rate}.fo-lc-cost{grid-area:cost}.fo-lc-rm{grid-area:rm}.fo-lc-spec{grid-area:spec;align-self:start}.fo-lc-vendor_spec{grid-area:vend;align-self:start}
@media (max-width:760px){
  .fo-line{grid-template-columns:repeat(6,minmax(0,1fr));grid-template-areas:"desc desc desc desc desc desc" "hcpcs hcpcs kind kind qty qty" "rate rate rate cost cost cost" "spec spec spec spec spec spec" "vend vend vend vend vend vend" "rm rm rm rm rm rm"}
}
.fo-list{margin:4px 0 0 18px;padding:0;font-size:13px;line-height:1.5}
.fo-dl{display:grid;grid-template-columns:minmax(120px,max-content) minmax(0,1fr);gap:5px 16px;margin:0;font-size:13px}
.fo-dl dt{color:var(--ink-2);font-weight:600}
.fo-dl dd{margin:0;color:var(--ink-1);overflow-wrap:anywhere}
@media (max-width:560px){.fo-dl{grid-template-columns:1fr}.fo-dl dd{margin-bottom:6px}}
.fo-next{border-color:var(--structural,var(--accent));background:var(--structural-08,var(--card));color:var(--ink-1)}
.fo-next-row{display:flex;gap:8px;align-items:center;flex-wrap:wrap}
.fo-next-row .rw-sp{flex:1 1 auto}
.fo-gap{margin:4px 0 8px;color:var(--ink-2)}
.fo-next-k{font-size:11px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2)}
.fo-docs{display:flex;flex-direction:column;gap:8px}
.fo-doc{display:flex;gap:8px;align-items:center;flex-wrap:wrap;padding:8px 0;border-bottom:1px dashed var(--line)}
.fo-doc:last-child{border-bottom:0}
.fo-doc small{display:block;font-size:12px;color:var(--ink-2)}
.fo-doc .rw-sp{flex:1 1 auto}
.fo-row-acts{white-space:nowrap}
.fo-row-acts .btn{margin:0 4px 4px 0}
.fo-inline{margin:0 0 10px}
.fo-chart-row{margin:0 0 8px;line-height:1.45}
.fo-flag,.rw-l input.fo-flag,.fo-lc .fo-flag{outline:2px solid var(--bad);outline-offset:1px;border-color:var(--bad)}
.fo-flag-note{display:block;margin:4px 0 0;font-size:12px;line-height:1.4;font-weight:600;color:var(--bad);background:transparent}
