/* Provider Production — the doctor dashboard, the owner's roster/review/mapping screens, and the
   Lab billing / Practice billing books. Every colour is a token from styles.css so dark mode comes for
   free; the chart palette is --viz-1..8 (already validated for this app's surfaces — see styles.css). */

/* minmax(0, 1fr): a grid column's implicit `auto` track grows to a child's min-content width, so a wide
   table would push the whole card out sideways and #list (overflow auto) would scroll it. Pinning the
   track lets .pr-tablewrap shrink to the column and own the sideways scroll itself (NO-SIDEWAYS-SCROLL rule). */
.pr-wrap { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.pr-nav { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.pr-pill { border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-soft); border-radius: var(--r-full);
  padding: 6px 12px; font-size: var(--t-sm); font-weight: 600; cursor: pointer; font-family: inherit; }
.pr-pill.on { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.pr-pill .pr-badge { display: inline-block; min-width: 18px; padding: 0 5px; margin-left: 6px; border-radius: var(--r-full);
  background: var(--warn); color: #fff; font-size: var(--t-xs); text-align: center; }
.pr-year { margin-left: auto; display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-sm); color: var(--muted); }
.pr-year select { font-size: var(--t-sm); padding: 5px 8px; }

.pr-card { border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface); padding: var(--s4); }
.pr-card h2 { margin: 0 0 var(--s2); font-size: var(--t-md); }
.pr-card h3 { margin: 0 0 var(--s2); font-size: var(--t-sm); color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.pr-sub { color: var(--muted); font-size: var(--t-sm); line-height: 1.45; }
.pr-loading { opacity: .55; transition: opacity var(--dur) var(--ease); }   /* hold the old render, no skeleton flash */
.pr-empty { color: var(--muted); font-size: var(--t-sm); padding: var(--s4); text-align: center; }
.pr-chip { display: inline-block; font-size: var(--t-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--ink-soft); vertical-align: middle; margin-left: 6px; }
.pr-chip.warn { background: color-mix(in srgb, var(--warn) 16%, var(--surface)); color: var(--warn); }
.pr-chip.good { background: color-mix(in srgb, var(--good) 16%, var(--surface)); color: var(--good); }

/* ---- hero: the tier ladder ---- */
.pr-hero { display: grid; gap: var(--s3); }
.pr-hero-top { display: flex; justify-content: space-between; align-items: baseline; flex-wrap: wrap; gap: var(--s2); }
.pr-hero-num, .pr-hero-big { font-size: 40px; font-weight: 700; color: var(--ink); line-height: 1; }   /* ONE hero figure, two names: .pr-hero-big is the new screens' */
.pr-hero-lbl { color: var(--muted); font-size: var(--t-sm); }
.pr-ladder { position: relative; height: 14px; background: var(--surface-3); border-radius: var(--r-full); }
/* ⚠ var(--dur), not .6s. The lifted rule declared a 600 ms width transition — 3.75x the owner's
   <=160 ms motion budget — in a stylesheet whose whole point is that the product's rules are visible in
   it. (Nothing animates it today: the ladder node is rebuilt with its final width on every paint.) */
.pr-ladder-fill { position: absolute; left: 0; top: 0; height: 100%; background: var(--primary); border-radius: var(--r-full); transition: width var(--dur) var(--ease); }
.pr-ladder-fill.top { background: var(--gold); }
.pr-tick { position: absolute; top: -6px; width: 2px; height: 26px; background: var(--line-strong); }
.pr-tick-lbl { position: absolute; top: 24px; transform: translateX(-50%); font-size: var(--t-xs); color: var(--muted); white-space: nowrap; font-variant-numeric: tabular-nums; }
.pr-ladder-wrap { padding-bottom: 22px; }
.pr-next { font-size: var(--t-sm); color: var(--ink-soft); }
.pr-next strong { color: var(--good); }

/* ---- stat tiles ---- */
/* ⚠ THE TRACK IS CAPPED. auto-fit + 1fr made the same tile 175px on Home, 221px once the rail stepped
   aside and 440px on a page with only two of them — one component reading as three designs. A ceiling
   of 260px keeps a tile one size everywhere and lands four of them 2x2 in a narrow column instead of
   3 + 1 orphan. */
.pr-tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 260px)); gap: var(--s3); justify-content: start; }
.pr-tile { border: 1px solid var(--line); border-radius: var(--r-md); padding: var(--s3); background: var(--surface-2); }
.pr-tile-l { font-size: var(--t-xs); color: var(--muted); font-weight: 600; }
.pr-tile-v { font-size: var(--t-xl); font-weight: 700; color: var(--ink); margin-top: 4px; }
.pr-tile-s { font-size: var(--t-xs); color: var(--muted); margin-top: 2px; }

/* ---- charts ---- */
.pr-plot { position: relative; width: 100%; }
.pr-svg { display: block; width: 100%; height: auto; touch-action: pan-y; }
.pr-grid { stroke: var(--line); stroke-width: 1; }
.pr-axis { fill: var(--muted); font-size: 11px; font-variant-numeric: tabular-nums; }
.pr-bar { fill: var(--viz-1); }
.pr-bar.collecting { fill: var(--viz-1); opacity: .42; }
.pr-bar.hover { filter: brightness(1.12); }
.pr-hit { fill: transparent; cursor: default; }
.pr-hit:focus { outline: none; }
.pr-hit:focus + .pr-bar, .pr-hit:hover + .pr-bar { filter: brightness(1.12); }
.pr-tip { position: absolute; top: 4px; z-index: 5; pointer-events: none; min-width: 140px; max-width: 240px;
  background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-md); box-shadow: var(--sh-2);
  padding: 8px 10px; font-size: var(--t-xs); }
.pr-tip-h { font-weight: 700; color: var(--ink); margin-bottom: 3px; }
.pr-tip-v { font-weight: 700; color: var(--ink); font-variant-numeric: tabular-nums; }
.pr-tip-s { color: var(--muted); }
.pr-legend { display: flex; gap: var(--s4); flex-wrap: wrap; font-size: var(--t-xs); color: var(--muted); margin-top: var(--s2); }
.pr-legend i { display: inline-block; width: 12px; height: 12px; border-radius: 3px; background: var(--viz-1); vertical-align: -2px; margin-right: 5px; }
.pr-legend i.faded { opacity: .42; }
.pr-toggle { font-size: var(--t-xs); color: var(--primary); cursor: pointer; background: none; border: 0; padding: 0; font-family: inherit; font-weight: 600; }

/* ---- horizontal bar lists (mix, payers) ---- */
.pr-hlist { display: grid; gap: 6px; }
/* The value cell is an `auto` track, so grid hands it its full one-line width FIRST and the name gets the
   leftover — measured 2026-09-04: "$357,793 CCM $183,042 · RPM $173,024" (234px) left "Kirti Shah" 12px in a
   282px column. Two guards: the name track never drops below 110px, and the muted sub may wrap onto a second
   line when the row is tight (its max-content still wins whenever there is room, so wide rows look the same). */
.pr-hrow { display: grid; grid-template-columns: minmax(110px, 1.2fr) minmax(0, 2fr) auto; gap: var(--s2); align-items: center; font-size: var(--t-sm); }
.pr-hname { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.pr-htrack { height: 10px; background: var(--surface-3); border-radius: var(--r-sm); overflow: hidden; }
.pr-hfill { height: 100%; background: var(--viz-1); border-radius: 0 4px 4px 0; }
.pr-hval { font-variant-numeric: tabular-nums; color: var(--ink); text-align: right; white-space: nowrap; }
.pr-hval small { color: var(--muted); font-weight: 400; white-space: normal; }
.pr-two { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: var(--s4); }
.pr-controls { display: flex; gap: var(--s2); align-items: center; flex-wrap: wrap; margin-bottom: var(--s2); font-size: var(--t-xs); color: var(--muted); }
.pr-controls select { font-size: var(--t-xs); padding: 4px 6px; }
.pr-subtotal { display: flex; gap: var(--s4); flex-wrap: wrap; margin-top: var(--s2); padding-top: var(--s2); border-top: 1px solid var(--line); font-size: var(--t-xs); color: var(--muted); }
.pr-subtotal b { color: var(--ink); font-variant-numeric: tabular-nums; }

/* ---- tables ---- */
.pr-tablewrap { overflow-x: auto; }
.pr-table { width: 100%; border-collapse: collapse; font-size: var(--t-sm); }
.pr-table th, .pr-table td { padding: 7px 8px; border-bottom: 1px solid var(--line); text-align: left; vertical-align: middle; }
.pr-table th { font-size: var(--t-xs); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; font-weight: 600; }
.pr-table td.n, .pr-table th.n { text-align: right; font-variant-numeric: tabular-nums; }
.pr-table tr.click { cursor: pointer; }
.pr-table tr.click:hover td { background: var(--surface-2); }
.pr-table td.up { color: var(--good); } .pr-table td.down { color: var(--danger); }
.pr-table select, .pr-table input[type=checkbox] { font-size: var(--t-xs); }
.pr-note { font-size: var(--t-xs); color: var(--muted); margin-top: var(--s2); line-height: 1.45; }
.pr-actions { display: flex; gap: var(--s2); flex-wrap: wrap; margin-top: var(--s3); }
.pr-warn { padding: var(--s2) var(--s3); border-radius: var(--r-md); font-size: var(--t-sm); line-height: 1.45;
  background: color-mix(in srgb, var(--warn) 12%, var(--surface)); border: 1px solid color-mix(in srgb, var(--warn) 34%, transparent); }
.pr-status { font-size: var(--t-xs); font-weight: 600; padding: 2px 8px; border-radius: var(--r-full); background: var(--surface-3); color: var(--ink-soft); }
.pr-status.pending_review { background: color-mix(in srgb, var(--warn) 16%, var(--surface)); color: var(--warn); }
.pr-status.published { background: color-mix(in srgb, var(--good) 16%, var(--surface)); color: var(--good); }
.pr-status.rejected, .pr-status.failed { background: color-mix(in srgb, var(--danger) 14%, var(--surface)); color: var(--danger); }

/* ---- line-level review (owner) ---- */
.pr-months { display: flex; flex-wrap: wrap; gap: var(--s2); margin: var(--s3) 0; }
.pr-mtab small { font-weight: 400; color: inherit; opacity: .8; margin-left: 4px; }
.pr-strip { font-size: var(--t-sm); color: var(--muted); margin-bottom: var(--s2); }
.pr-strip b { color: var(--ink); font-variant-numeric: tabular-nums; }
.pr-bulk, .pr-bulkall { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; padding: var(--s2) var(--s3);
  border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); margin: var(--s2) 0; font-size: var(--t-sm); }
.pr-bulk[hidden], .pr-bulkall[hidden] { display: none; }   /* a `display` rule beats the UA [hidden]; say it explicitly */
.pr-bulk input, .pr-bulkall input, .pr-bulk select, .pr-bulkall select { font-size: var(--t-sm); padding: 5px 8px; }
/* A <select> is as wide as its longest option ("United Healthcare Medicare Advantage (12,345 · $1,234,567)"
   is wider than a phone); cap it at the row so the card never grows past #list. */
.pr-bulk select, .pr-bulk input, .pr-bulkall select, .pr-bulkall input { max-width: 100%; min-width: 0; }
/* NO-SIDEWAYS-SCROLL rule (owner 2026-08-31; engage.css §7 does this for every other worksheet): the lines
   table must FIT its column on desktop — natural wrapping at spaces, stacked sub-lines (description under
   CPT, visit type under facility; account and claim are COLUMNS of their own since 2026-09-07), denser rows
   on laptops. Only the short cells (date, account, claim, money) stay on one line. The wrapper's overflow-x
   is the phone's last resort — and, since the fourteenth column, the 1223px MacBook's (the FIT note below). */
.pr-lines { table-layout: auto; }                                   /* phone: natural width, the wrapper scrolls (last resort) */
.pr-lines th, .pr-lines td { white-space: normal; overflow-wrap: break-word; vertical-align: top; }
.pr-lines td.nw, .pr-lines td.n, .pr-lines th.n, .pr-lines small.nw { white-space: nowrap; }
.pr-lines td small { display: block; color: var(--muted); font-size: var(--t-xs); line-height: 1.3; }
.pr-lines .pr-chip { margin-left: 0; white-space: normal; overflow-wrap: normal; }     /* reason chips wrap at spaces, never mid-word */
.pr-lines .pr-chip.pr-tag { white-space: nowrap; }                                     /* "≠ appt" / "NP" / "billed ≠" */
.pr-chip.pr-np { color: var(--muted); }                                                /* quiet grey (surface-3 already) */
.pr-chip.pr-billed { background: transparent; border: 1px solid var(--line); color: var(--muted); }
/* A resource ≠ appointment line: warm tint + a 3px left bar (an inset shadow, so the column width does not move). */
.pr-lines tr.pr-flag td { background: color-mix(in srgb, var(--warn) 10%, var(--surface)); }
.pr-lines tr.pr-flag td:first-child { box-shadow: inset 3px 0 0 var(--warn); }
.pr-lines tr.sel td { background: color-mix(in srgb, var(--primary) 8%, var(--surface)); }   /* keep AFTER tr.pr-flag so selection wins */
.pr-cred { background: none; border: 0; padding: 0; font: inherit; color: var(--primary); cursor: pointer; text-align: left; white-space: normal; }
.pr-cred-sel { max-width: min(220px, 100%); font-size: var(--t-xs); }
/* The twelfth column, "Supervising provider" (owner 2026-09-07 20:41: "i want the column for the supervising
   provider to be separate, and something i can change in case there is an error … if the provider is a doctor
   and doesn't have a supervising provider, then it should just be blank"). The cell is a button like .pr-cred
   (the name, the primary colour says it can be changed) and a select like .pr-cred-sel on click. A visit with
   no supervising physician yet gets the warn-toned "choose" — the warn token, because it is something the owner
   must look at, not a fact. "set by you" is a small chip that must not break inside itself. */
.pr-sup { background: none; border: 0; padding: 0; font: inherit; color: var(--primary); cursor: pointer; text-align: left; white-space: normal; }
.pr-sup.warn { color: var(--warn); font-weight: 600; }
.pr-sup-sel { max-width: min(220px, 100%); font-size: var(--t-xs); }
.pr-chip.pr-sup-set { white-space: nowrap; background: color-mix(in srgb, var(--primary) 12%, var(--surface)); color: var(--primary); cursor: help; }
/* The supervising controls on the two bulk bars: their own full-width line under the credit controls, so the
   bar reads as two decisions (who is credited · who supervised) rather than one long row of selects. It wraps
   with min-width: 0 from the start (the .pr-nact lesson at 390); the bar's own rule caps the select and the note. */
.pr-bulk-sup { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; flex-basis: 100%; min-width: 0; padding-top: var(--s2); border-top: 1px solid var(--line); }
.pr-bulk-lbl { color: var(--muted); }
.pr-bulk-lbl b { color: var(--ink); font-variant-numeric: tabular-nums; }
.pr-flagstrip, .pr-flagstrip b { color: var(--warn); }
/* Section tabs under the month tabs: provider production · lab billing · practice billing (same pill as the month tabs). */
.pr-sectabs { display: flex; flex-wrap: wrap; gap: var(--s2); margin: 0 0 var(--s3); }
.pr-sectab small { font-weight: 400; color: inherit; opacity: .8; margin-left: 4px; }
/* The section's analysis block (review): tiles + lists between the section tabs and the filter row. */
.pr-analysis { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s3); padding: var(--s3); margin-bottom: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); }
.pr-analysis[hidden] { display: none; }
.pr-analysis .pr-tile { background: var(--surface); }
.pr-analysis h3 { margin: 0 0 var(--s2); font-size: var(--t-sm); color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.pr-an-head { font-size: var(--t-sm); color: var(--ink); }
/* The hlists in the books and the analysis block hold long names ("United Healthcare Medicare Advantage",
   "99490 · CHRON CARE MGMT SRVC 20 MIN"). The plain .pr-two minimum (280px) packs THREE 282px columns into the
   review's 877px block and two 303px columns on a 1280–1366px laptop — every name ellipsized. 400px keeps one
   column below 816px of row width (the 531–708px book cards, a 1101px review) and two ≥816px (the 1223px review:
   2 × 430px; a 1920px book card: 2 × 589px). min(400px, 100%) so a 280px phone column never overflows. */
.pr-analysis .pr-two, .pr-book .pr-two { grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr)); }
/* Book pages (Lab billing / Practice billing) keep the rail, so a card is ~531px on a 1223px MacBook: tiles auto-fit,
   .pr-two is one column (rule above), the by-month table has ≤6 short columns. minmax(0, 1fr): see .pr-wrap —
   without it the 6-column table (421px min-content) widened the card past #list on a phone and at 1101–1113px. */
.pr-book { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.pr-book .pr-table th, .pr-book .pr-table td { padding: 6px 6px; }
@media (min-width: 761px) and (max-width: 1300px) { .pr-book .pr-table { font-size: var(--t-xs); } }
/* The right rail comes back at 1101px and leaves a book card 409–490px wide; the practice table's natural minimum
   is ≈421px, so tighten the cells there (≈350px) and it fits without the wrapper scrolling. Not at 1223 — the
   owner's 531px card takes the table at its natural padding. */
@media (min-width: 1101px) and (max-width: 1180px) { .pr-book .pr-table th, .pr-book .pr-table td { padding: 4px 3px; } }
.pr-ebo { display: block; color: var(--muted); font-size: var(--t-xs); }   /* the raw eBO schedule name under the friendly title */
/* FIT (desktop): the fourteen columns must never scroll the PAGE sideways. Auto layout cannot promise that — the longest unbreakable words
   on the real 2025 file ("Chattopadhyay," 82px at 11px, "Lawrenceville(main", "CARMICHAEL-THREADGILL,", "fee,Venipuncture") add up past the
   905px a 1223px MacBook gives the table. So: fixed layout with a percentage plan that keeps every COMMON word whole, <wbr>s after "," and
   before "(" (soft() in review/filters.js), and overflow-wrap:anywhere as the last resort for a rare 19-letter surname.
   Width math at 1223 (Inter): column = 1223 − 32 (.body padding) − 220 (rail) − 16 (gap) − 16 (.list padding) − 34 (.pr-card
   padding+border) = 905px; 1280 → 926px, 1920 → 1230px scale every column up. Phones keep auto layout + wrapper scroll.
   FOURTEEN columns (2026-09-07, "i want the account number and claim number to have its own columns" — Account and Claim after Patient,
   which keeps the name alone): measured in Inter at the 11px / 2px tier, the words that must stay whole need — the FIVE name columns
   "Chattopadhyay," 82 + 4 = 86px each (430), the date "12/31/2025" 69, the ACCOUNT header 56 (the 5-digit number itself is 36), an
   8-digit claim 61, "Collected" 66, "Lawrenceville" 75, the tick 17 — 775px before Patient, CPT and Payer have a pixel, and those three
   need ~55 / 45 / 55 ("Abuajah," 49, a code 40, "Medicare" 53). That is 930–940px, and a 1223px MacBook gives 905. So the plan below sums
   to 100% of 940px, and .pr-lines is never narrower than 940px: on the MacBook the WRAPPER scrolls ~35px (its overflow-x is already auto)
   — the spec's documented fallback — and the PAGE never does. Above ~1260px nothing scrolls. The alternative (a 10.5px tier, or "Acct"
   for the header) was judged worse than a 35px scroll for the owner's own screen; change one line here to choose it.
     (the fourteen-column plan, kept for the record) ck 1.9 · date 7.2 · pat 5.8 · acct 6.0 · claim 7.2 · cpt 5.0 · fac 8.1 · payer 5.8 · amt 7.0 · res/appt/rend/cred/sup 9.2 × 5 = 100.0 of 940px
   SEVENTEEN columns (2026-09-08, owner: "the venipuncture credit needs to go to the doctor that put in the Orders" · "see who signed off the
   note" · "columns*" — Ordered by, Signed by and Note after Supervising provider): two more NAME columns and a button column. The spec's word
   is "narrow": 78px each for the two names (a common surname whole; "Chattopadhyay," takes the overflow-wrap:anywhere fallback there and
   nowhere else) and 62px for "Preview" (48px at the 10px pill tier). Every fourteen-column pixel figure above is KEPT (not squeezed — the
   plan was already at its floor), so the sum is 1190px: on the 1223px MacBook (905px) the WRAPPER scrolls ~285px and the page never does —
   the documented fallback, and the owner's own words put three columns ahead of a fit; from ~1550px nothing scrolls. Hiding the three
   below a breakpoint was judged worse (a column that comes and goes reads as a bug); change one line here to choose it.
     ck 1.5 · date 6.1 · pat 5.0 · acct 4.8 · claim 5.8 · cpt 4.0 · fac 6.6 · payer 4.7 · amt 5.6 · res/appt/rend/cred/sup 7.5 × 5 · ord 6.6 · sig 6.6 · note 5.2 = 100.0 of 1190px */
@media (min-width: 761px) {
  .pr-lines { table-layout: fixed; min-width: 1190px; }
  .pr-lines th, .pr-lines td { overflow-wrap: anywhere; }
  .pr-lines col.pc-ck { width: 1.5%; } .pr-lines col.pc-date { width: 6.1%; } .pr-lines col.pc-pat { width: 5%; } .pr-lines col.pc-acct { width: 4.8%; } .pr-lines col.pc-claim { width: 5.8%; }
  .pr-lines col.pc-cpt { width: 4%; } .pr-lines col.pc-fac { width: 6.6%; } .pr-lines col.pc-payer { width: 4.7%; } .pr-lines col.pc-amt { width: 5.6%; }
  .pr-lines col.pc-res, .pr-lines col.pc-appt, .pr-lines col.pc-rend, .pr-lines col.pc-cred, .pr-lines col.pc-sup { width: 7.5%; }
  .pr-lines col.pc-ord, .pr-lines col.pc-sig { width: 6.6%; } .pr-lines col.pc-note { width: 5.2%; }   /* = 100% */
}
@media (min-width: 761px) and (max-width: 1520px) { .pr-lines th, .pr-lines td { padding: 6px 6px; font-size: 12.5px; } .pr-lines td small { font-size: 11.5px; } }
@media (min-width: 761px) and (max-width: 1400px) { .pr-lines th, .pr-lines td { padding: 5px 5px; font-size: 12px; } .pr-lines th { font-size: 10.5px; } .pr-lines td small { font-size: 11px; } }
@media (min-width: 761px) and (max-width: 1300px) { .pr-lines th, .pr-lines td { padding: 4px 2px; font-size: 11px; } .pr-lines th { font-size: 10px; letter-spacing: .02em; } .pr-lines td small { font-size: 10px; } .pr-lines .pr-chip { font-size: 10px; padding: 1px 5px; } }
/* Beside the review the leaderboard rail steps aside (≤1680px), the same trick the water log and the CCM
   roster use, so a 1223px MacBook gives the fourteen columns ~905px instead of ~640. Scoped to the lines table:
   the dashboard and the roster keep their rail. */
@media (min-width: 761px) and (max-width: 1680px) {
  .body:has(#list .pr-lines) { grid-template-columns: var(--rail-w) 1fr; }
  .body:has(#list .pr-lines) .rail-right { display: none; }
}
@media (min-width: 761px) and (max-width: 1300px) { .body:has(#list .pr-lines) { --rail-w: 220px; } }
.pr-more { display: flex; gap: var(--s2); align-items: center; justify-content: center; padding: var(--s3); font-size: var(--t-sm); color: var(--muted); }
.pr-fold summary { cursor: pointer; font-weight: 600; font-size: var(--t-sm); color: var(--muted); text-transform: uppercase; letter-spacing: .04em; margin-bottom: var(--s2); }

/* ---- the calm review header (owner 2026-09-04 night) + Excel-style header filters ----
   Above the table: a one-line imports card while a review is open, ONE fact line, a collapsed "About this
   report", a quiet names line, compact month pills, the strip with the search box, and a chip row for the
   active filters. Every colour is a token; motion is the house 160 ms. */
.pr-imports.collapsed .viz-head, .pr-imports.collapsed #prImpTable { display: none; }
.pr-imports.collapsed { padding: var(--s3) var(--s4); }
.pr-imp-line { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; font-size: var(--t-sm); color: var(--muted); }
.pr-imp-line b { color: var(--ink); font-weight: 600; }
.pr-imp-line[hidden] { display: none; }
.pr-fact { font-size: var(--t-sm); color: var(--ink-soft); font-variant-numeric: tabular-nums; margin-top: 2px; }
.pr-about { margin-top: 4px; }
.pr-about summary { cursor: pointer; font-size: var(--t-xs); color: var(--muted); list-style: none; }
.pr-about summary::-webkit-details-marker { display: none; }
.pr-about summary::before { content: '▸ '; } .pr-about[open] summary::before { content: '▾ '; }
.pr-about-body { font-size: var(--t-xs); color: var(--muted); line-height: 1.45; padding: 4px 0 0 12px; }
.pr-names { margin-top: var(--s2); font-size: var(--t-xs); color: var(--muted); }
.pr-names .pr-chip { margin-left: 0; cursor: help; }
.pr-months[hidden], .pr-chips[hidden] { display: none; }               /* a display rule beats the UA [hidden] — same note as .pr-bulk */
.pr-months-compact { gap: 4px; margin: var(--s3) 0 var(--s2); }
.pr-months-compact .pr-mtab { padding: 4px 10px; font-size: var(--t-xs); }
.pr-mtab.partial::after { content: ''; display: inline-block; width: 6px; height: 6px; border-radius: 50%; background: var(--warn); margin-left: 5px; vertical-align: 1px; }
.pr-analysis .pr-tiles { gap: var(--s2); }
.pr-analysis .pr-tile { padding: 8px 10px; }
.pr-analysis .pr-tile-v { font-size: var(--t-lg); margin-top: 2px; }
.pr-strip { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.pr-strip-txt { flex: 1 1 260px; }
.pr-strip-q { flex: 0 1 300px; margin-left: auto; }
.pr-strip-q input { width: 100%; max-width: 100%; min-width: 0; font-size: var(--t-sm); padding: 5px 8px; }
.pr-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: var(--s2); }
.pr-fchip { display: inline-flex; align-items: center; gap: 6px; max-width: 100%; border: 1px solid var(--line-strong); background: var(--surface-2); color: var(--ink); border-radius: var(--r-full); padding: 3px 8px 3px 10px; font: inherit; font-size: var(--t-xs); cursor: pointer; }
.pr-fchip span { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 260px; }
.pr-fchip i { font-style: normal; color: var(--muted); }
.pr-fchip:hover i { color: var(--danger); }
/* Header cells as controls — the caret and the dot are absolutely positioned and take NO layout width, so the
   fixed column plan above (and the 903/903 fit at 1223) is untouched. */
.pr-lines th.pr-hcol { position: relative; cursor: pointer; user-select: none; }
.pr-lines th.pr-hcol:hover, .pr-lines th.pr-hcol.open { color: var(--ink); }
.pr-lines th.pr-hcol:focus-visible { box-shadow: inset 0 0 0 2px var(--primary); border-radius: 0; }
.pr-hcaret { position: absolute; right: 1px; bottom: 2px; width: 12px; height: 12px; line-height: 12px; font-size: 11px; text-align: center; color: var(--muted); opacity: 0; transition: opacity var(--dur) var(--ease); }
.pr-hcaret::before { content: '▾'; }
.pr-lines th.n .pr-hcaret { right: auto; left: 1px; }
.pr-lines th.pr-hcol:hover .pr-hcaret, .pr-lines th.pr-hcol:focus-visible .pr-hcaret, .pr-lines th.pr-hcol.open .pr-hcaret, .pr-lines th.sort-asc .pr-hcaret, .pr-lines th.sort-desc .pr-hcaret { opacity: 1; }
.pr-lines th.sort-asc .pr-hcaret::before { content: '▲'; } .pr-lines th.sort-desc .pr-hcaret::before { content: '▼'; }
.pr-lines th.sort-asc .pr-hcaret, .pr-lines th.sort-desc .pr-hcaret { color: var(--primary); font-size: 9px; }
.pr-hdot { position: absolute; top: 3px; right: 3px; width: 6px; height: 6px; border-radius: 50%; background: var(--primary); }
.pr-hdot[hidden] { display: none; }
.pr-lines th.n .pr-hdot { right: auto; left: 3px; }
/* The popover: OUTSIDE .pr-tablewrap (whose overflow-x:auto would clip it), positioned in the card by production.js. */
#prLinesCard { position: relative; }
.pr-hf { position: absolute; z-index: 20; min-width: 240px; box-sizing: border-box; background: var(--surface); border: 1px solid var(--line-strong); border-radius: var(--r-md); box-shadow: var(--sh-2); padding: var(--s3); font-size: var(--t-sm); display: grid; gap: var(--s2); animation: prHfIn 160ms var(--ease); }
@keyframes prHfIn { from { opacity: 0; transform: translateY(-4px); } }
@media (prefers-reduced-motion: reduce) { .pr-hf { animation: none; } }
.pr-hf-h { font-size: var(--t-xs); color: var(--muted); font-weight: 600; text-transform: uppercase; letter-spacing: .04em; }
.pr-hf-sort { display: flex; gap: 6px; }
.pr-hf-sbtn { flex: 1; border: 1px solid var(--line-strong); background: var(--surface); color: var(--ink-soft); border-radius: var(--r-sm); padding: 5px 8px; font: inherit; font-size: var(--t-xs); cursor: pointer; }
.pr-hf-sbtn.on { background: var(--primary); border-color: var(--primary); color: var(--on-primary); }
.pr-hf input[type=search], .pr-hf input[type=date], .pr-hf input[type=number] { width: 100%; min-width: 0; max-width: 100%; box-sizing: border-box; font-size: var(--t-sm); padding: 5px 8px; }
.pr-hf-row { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.pr-hf-row label { display: grid; gap: 2px; font-size: var(--t-xs); color: var(--muted); }
.pr-hf-list { max-height: 240px; overflow-y: auto; display: grid; gap: 2px; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); padding: 4px 0; }
.pr-hf-opt { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 6px; align-items: center; padding: 3px 2px; border-radius: var(--r-sm); font-size: var(--t-xs); cursor: pointer; }
.pr-hf-opt:hover { background: var(--surface-2); }
.pr-hf-opt[hidden] { display: none; }
.pr-hf-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.pr-hf-name small { display: block; color: var(--muted); }
.pr-hf-n { color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }
.pr-hf-show { display: grid; gap: 4px; font-size: var(--t-xs); }
.pr-hf-show label { display: flex; gap: 6px; align-items: center; }
.pr-hf-foot { display: flex; justify-content: space-between; align-items: center; gap: var(--s2); }
.pr-hf-note { margin-left: auto; font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }   /* the tick counter: "18 of 20" */
.pr-hf-note[hidden] { display: none; }
.pr-hf-opt.off { opacity: .5; cursor: default; }                                     /* locked at the 20-value cap */
.pr-hf-opt.off:hover { background: transparent; }
.pr-hf:focus { outline: none; }                                                      /* the phone focuses the popover itself (tabindex -1) */
@media (max-width: 760px) { .pr-hf { right: 0; width: auto; min-width: 0; max-width: none; } }

/* ---- True-up (owner 2026-09-05): one reconciliation, three doors ----
   The pill's page (.pr-trueup), the annual review's compact table (.pr-tu-compact, in card B where the rail is
   already hidden) and the provider's own card (#prMyTrueup). Tokens only; the state is a chip, the explanations
   are .pr-sub / .pr-note — no boxed alerts. minmax(0, 1fr): same reason as .pr-wrap and .pr-book. */
.pr-trueup { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.pr-tu-tiles { margin: var(--s2) 0 var(--s3); }
.pr-tu-tiles .pr-tile-v { white-space: nowrap; }   /* a signed change never breaks after its sign ("−" alone on a line reads as positive) */
.pr-tu-months td.dim, .pr-tu-months th.dim { color: var(--muted); font-weight: 400; }
.pr-tu-months tr.has-note td { border-bottom: 0; }                                   /* the note row under it carries the rule */
.pr-tu-months tr.pr-tu-note td { padding-top: 0; color: var(--muted); font-size: var(--t-xs); line-height: 1.4; white-space: normal; }
.pr-tu-narr { margin: var(--s3) 0 0; padding-left: 18px; font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
/* The owner's "Paid so far" row: amount + note + Save + Confirm wrap as a flex row; "entered by …" takes its own line. */
.pr-tu-pay { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); font-size: var(--t-sm); color: var(--muted); }
.pr-tu-pay label { display: inline-flex; align-items: center; gap: 4px; }
.pr-tu-pay input { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; }
.pr-tu-pay .pr-tu-paid { width: 120px; }
.pr-tu-pay .pr-tu-pnote { flex: 1 1 160px; }
.pr-tu-paidby { flex-basis: 100%; font-size: var(--t-xs); }
.pr-tu-compact th, .pr-tu-compact td { padding: 6px 6px; }
/* Laptops (the rail present, a 409–531px card): the four-column tables take the book pages' smaller type and padding. */
@media (min-width: 761px) and (max-width: 1300px) {
  .pr-trueup .pr-table, .pr-tu-compact, #prMyTrueup .pr-table { font-size: var(--t-xs); }
  .pr-trueup .pr-table th, .pr-trueup .pr-table td, #prMyTrueup .pr-table th, #prMyTrueup .pr-table td { padding: 6px 6px; }
}
/* Lab true-up card: the 5-column month table (Month · Monthly said · Annual says · Change · AccuLab Δ) is ≈375px at natural
   padding, the two Labs / QUA subtotal rows ≈415px ("$36,586 → $36,406" in the last cell) — inside the 531px card at 1223. */
.pr-tu-months tr.pr-tu-stream td { color: var(--muted); font-size: var(--t-xs); border-top: 1px solid var(--line); }
.pr-tu-months tr.pr-tu-stream td:first-child { padding-left: 14px; }          /* indented under the months: a subtotal, not a month */
.pr-tu-months tr.pr-tu-stream + tr.pr-tu-stream td { border-top: 0; }
.pr-tu-months tr.pr-tu-stream td:last-child { white-space: nowrap; }         /* "$141,934 → $142,069" stays one line — auto layout wrapped it at 531 */
.pr-tu-inv .pr-tu-invamt { width: 130px; }                                    /* "$178,700.04" fits with the spinner */
/* The rail is back at 1101px and a card is 409–490px: tighten the five-column table there like the book pages.
   Scoped under .pr-trueup so it outranks the 6px/6px laptop rule above (same specificity, later in the file). */
@media (min-width: 1101px) and (max-width: 1180px) { .pr-trueup .pr-tu-labmonths th, .pr-trueup .pr-tu-labmonths td { padding: 4px 3px; } }

@media (max-width: 760px) {
  .pr-hero-num, .pr-hero-big { font-size: 32px; }
  .pr-hrow { grid-template-columns: minmax(96px, 1fr) minmax(0, 1.4fr) auto; }   /* 96 + 32 gaps + a wrapped value ≤ the 280px analysis column */
  .pr-tick-rate { display: none; }        /* "$550k · 25%" ×3 collides on a phone; the amounts alone read fine */
  .pr-tick-lbl { font-size: 10px; }
}

/* ==================================================================================================
   THE REDESIGNED WORKSPACE (public/production/*) — Phase B.
   Everything above this line still belongs to the OLD screens, three of which are embedded inside
   this shell until Phases C and D replace them; nothing above was changed.

   Rules these follow, all of them the owner's: tokens only (no hex, so dark mode is free), tabular
   figures on everything numeric, chips instead of alert boxes, no motion of our own beyond what
   motion.css already gives, and NO SIDEWAYS SCROLL on desktop — every grid track is minmax(0, 1fr)
   and every table sits in a .viz-table-wrap that owns its own overflow.
   ================================================================================================== */

/* ---- 7.1 the shell: two levels of navigation that must never look alike ----
   .pr-tab is underlined text (mirrors .wtr-tab, styles.css ~5720); .pr-folder is a raised folder tab
   (mirrors .wtr-folder). Somebody who cannot tell the two levels apart cannot tell which one they
   just clicked. */
.pr-head {
  display: flex; flex-wrap: wrap; align-items: flex-end; gap: var(--s3);
  border-bottom: 1px solid var(--line); margin-bottom: var(--s4);
}
.pr-tabs { display: flex; flex-wrap: wrap; gap: var(--s4); margin: 0; padding: 0; }
.pr-tab {
  display: inline-flex; align-items: center; gap: 6px; white-space: nowrap;
  padding: 8px 2px; margin-bottom: -1px;                 /* the underline sits ON the head's border */
  border-bottom: 2px solid transparent;
  color: var(--muted); font-size: var(--t-sm); font-weight: 600; text-decoration: none;
}
.pr-tab:hover { color: var(--ink); }
.pr-tab.on { color: var(--ink); border-bottom-color: var(--primary); }
.pr-tab:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r-sm); }
.pr-tabn {
  min-width: 18px; padding: 0 5px; border-radius: var(--r-full);
  background: var(--primary); color: var(--on-primary);
  font-size: 11px; font-weight: 700; line-height: 18px; text-align: center;
  font-variant-numeric: tabular-nums;
}
.pr-head .pr-year { margin-left: auto; padding-bottom: 6px; }
.pr-folders {
  display: flex; flex-wrap: wrap; gap: 4px; margin: 0 0 var(--s4); padding: 0;
  border-bottom: 1px solid var(--line);
}
.pr-folder {
  padding: 7px 13px; position: relative; top: 1px;
  border: 1px solid var(--line); border-bottom: 0; border-radius: 7px 7px 0 0;
  background: var(--surface-2); color: var(--muted);
  font-size: 12px; font-weight: 600; white-space: nowrap; text-decoration: none;
}
.pr-folder:hover { color: var(--ink); }
.pr-folder.on { background: var(--surface); color: var(--ink); box-shadow: 0 -2px 0 var(--primary) inset; }
.pr-folder:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }

/* ---- 7.2 the pieces ----
   The queue (the water.js needsAttention pattern): severity is a 3px LEFT BORDER and nothing else.
   A row of coloured boxes stops being read within a week, which is exactly when it matters. */
.pr-queue { display: grid; gap: 6px; }            /* #prPlace's own grid gap separates it from what follows */
.pr-qrow {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: var(--s3); align-items: center;
  padding: var(--s3) var(--s3) var(--s3) var(--s4);
  border: 1px solid var(--line); border-left: 3px solid var(--line); border-radius: var(--r-md);
  background: var(--surface); font-size: var(--t-sm); line-height: 1.5; color: var(--ink);
}
.pr-qrow.sev-0 { border-left-color: var(--danger); }
.pr-qrow.sev-1 { border-left-color: var(--warn); }
.pr-qrow.sev-2 { border-left-color: var(--primary); }
.pr-qrow.sev-3, .pr-qrow.sev-ok { color: var(--muted); }
.pr-qtext { min-width: 0; overflow-wrap: break-word; }
.pr-qact { display: flex; gap: var(--s2); flex-wrap: wrap; }
.pr-qact .btn { white-space: nowrap; }
/* ⚠ EVERY ACTION IN THIS WORKSPACE IS A REAL <a href> (§2: the hash is the screen, so Back, reload and
   middle-click all have to work), and .btn (styles.css:1222) never resets the browser's underline on an
   anchor — so Start / Open / Link names rendered as underlined links wearing a button's border. AP hit
   exactly this and patched its own corner (.ap-check-acts a.btn); this is the same patch for ours. */
.pr-wrap a.btn { text-decoration: none; }

/* One sentence saying where the year stands, above the tiles. Not a box — a line. */
.pr-state { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px; font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.pr-state .chip { flex: none; }

/* Tiles: the shared .pr-tiles / .pr-tile above already carry the grid and the type. These add the
   tabular figures the owner asked for on every number, and the four value tones. */
.pr-num { font-variant-numeric: tabular-nums; }
.pr-tile-v.pr-num { white-space: nowrap; }        /* a signed figure must never break after its sign */
.pr-tile-good .pr-tile-v { color: var(--good); }
.pr-tile-warn .pr-tile-v { color: var(--warn); }
.pr-tile-danger .pr-tile-v { color: var(--danger); }
.pr-tile-muted .pr-tile-v { color: var(--muted); }
.pr-tile-s { line-height: 1.4; }

/* The hero on a doctor's page: their name, the state chips, the one big figure, one sentence.
   .pr-hero-big is declared WITH .pr-hero-num at the top of this file — one object, one rule — rather
   than restating its size, weight and colour under a second name. This adds only what the new screens
   want on top: tabular figures (the owner's rule for every number) and a hair more leading. */
.pr-hero-big { font-variant-numeric: tabular-nums; line-height: 1.05; }
.pr-hero-line { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.pr-hero h2 { margin: 0; font-size: var(--t-lg); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* The new cards are the app's .card. minmax(0, …) at every level or a wide table pushes the column
   out and #list scrolls sideways — the fault this whole stylesheet is written around. */
.pr-card2 { min-width: 0; }
.pr-cardsub { font-weight: 400; color: var(--muted); font-size: var(--t-xs); margin-left: 6px; }
#prPlace { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
/* (.pr-loading itself is declared once, at the top of this file — #prPlace carries the class, so an
   id-prefixed copy of the same two declarations bought nothing.) */

/* Two cards side by side, one column under 900px. The embedded OLD screens inside this same host keep
   their own auto-fit rule — their tables and lists were measured against it. */
/* ⚠ auto-fit, NOT a fixed pair with a viewport escape hatch. The rule used to force two columns and
   only relented at a 900px VIEWPORT — but the container is what matters: with the leaderboard rail in
   place #prPlace is ~549px at a 1223px viewport, which squeezed the mix cards into ~217px columns while
   .pr-hrow's own minimum (110px name + value + gaps) is 223px. min(280px, 100%) lets the track fall to
   one column on its own, whatever the window is doing. */
#prPlace .pr-two { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
#prPlace .pr-legacy .pr-two { grid-template-columns: repeat(auto-fit, minmax(min(400px, 100%), 1fr)); }

/* THE month table (Home, the doctor page, Settle the year). .viz-table right-aligns every cell and
   left-aligns the first; the status column is words, so it goes back to the left. */
.pr-mtable th.st, .pr-mtable td.st { text-align: left; font-variant-numeric: normal; }
.pr-mtable td .chip { margin-left: 4px; }
.pr-mtable tbody tr:last-child th, .pr-mtable tbody tr:last-child td { border-bottom: 0; }

.pr-hempty { color: var(--muted); font-size: var(--t-sm); padding: var(--s3) 0; }
.pr-legend i.none { background: transparent; border: 1px solid var(--line-strong); }

/* The Names step's confirmations (owner 2026-09-07: "it feels like everything is figured out"): one line under a
   guessed name saying what the guess means, and one row above the list for confirming the lot. */
.pr-nmeaning { color: var(--muted); font-size: var(--t-xs); line-height: 1.45; margin-top: 2px; }
.pr-nall { display: flex; flex-wrap: wrap; align-items: center; gap: var(--s2) var(--s3); font-size: var(--t-sm); margin-bottom: var(--s3); }
/* On a phone the Confirm button + the KIND select (302px) outgrew the row's 298px column and the whole list scrolled
   sideways; the pair wraps onto two lines there and the select takes the row. */
@media (max-width: 760px) {
  .pr-nact { flex-wrap: wrap; white-space: normal; min-width: 0; }
  .pr-nact select { flex: 1 1 200px; min-width: 0; max-width: 100%; }
}

/* ---- the supervising physician (owner 2026-09-07 evening; per VISIT since 20:40: "the np's visit is dependant
   on the who supervises that visit. always.") ----
   The answer lives on the Lines step's twelfth column (.pr-sup, .pr-sup-sel, .pr-sup-set, .pr-bulk-sup, beside
   .pr-cred above). The 20:21 build's per-NP controls — .pr-nsup (the Names step's registry-default select) and
   .ps-sup (Settings → Names) — and its credited sub-line (.pr-cred-sup) and appointment tag (.pr-tag.pr-sup) are
   REMOVED with their markup (names.js / settings.js / lines.js emit none of them since 20:40). Only the two
   rules below remain from that block. */
/* N3: a row that is still a decision after a save is swapped in place, and the new row fades IN over the same
   140 ms the leaving rows fade out. Two classes, not a transition on .pr-nrow itself, so .saving's dim stays instant. */
.pr-nrow.arriving { opacity: 0; }
.pr-nrow.arriving.on { opacity: 1; transition: opacity 140ms ease-out; }
@media (prefers-reduced-motion: reduce) { .pr-nrow.arriving.on { transition: none; } }
/* Doctor page: the NP-credit list under the tiles ("From Reeves, Erin NP: $0 — you supervised 1,986 of their
   visits"). A list with no bullets; the sentence wraps inside the card. */
.pr-npc { list-style: none; margin: var(--s2) 0 0; padding: 0; display: grid; gap: var(--s1); font-size: var(--t-sm); line-height: 1.45; color: var(--ink-soft); min-width: 0; }
.pr-npc li { overflow-wrap: break-word; min-width: 0; }

/* ---- 8. Performance (P2, 2026-09-07) ----
   Bright cards on the white ground, the same kit, the fixed --viz order. Every wide table sits in
   .pr-tablewrap (its own sideways scroll, never the page's). The printed page IS the buyer document:
   one @media print block below hides the chrome and forces the light tokens. */
.pf-place { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.pf-top { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; justify-content: space-between; }
.pf-body { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.pf-grid2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); gap: var(--s4); }
.pf-filters { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: end; }
.pf-f { display: grid; gap: 2px; font-size: var(--t-xs); color: var(--muted); font-weight: 600; min-width: 0; }
.pf-f select, .pf-f input { font-size: var(--t-sm); padding: 5px 8px; min-width: 120px; max-width: 220px; font-family: inherit; }
.pf-fc { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-sm); color: var(--ink-soft); padding-bottom: 6px; }
.pf-chips { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-top: var(--s2); }
.pf-more { margin-top: var(--s2); }
.pf-more > summary { cursor: pointer; font-size: var(--t-xs); font-weight: 600; color: var(--primary); list-style: none; display: inline-block; }
.pf-more > summary::-webkit-details-marker { display: none; }
.pf-more > summary::before { content: '+ '; }
.pf-more[open] > summary::before { content: '− '; }
.pf-more > .pf-filters { margin-top: var(--s2); }
.pf-numbers { margin-top: var(--s3); }
.pf-numbers:empty { display: none; }
.pf-table th, .pf-table td { font-size: var(--t-sm); }
/* A Performance tile's value may be WORDS ("KHC Lawrenceville(main office)", "Office visits"), not only a figure; the
   kit's nowrap (right for a signed number) pushed a 150px phone tile 40px past its column. Words wrap; a figure has no
   break point inside it, so money still never splits. */
.pf-body .pr-tile-v { white-space: normal; overflow-wrap: anywhere; line-height: 1.15; }
.pf-words { font-size: var(--t-sm); line-height: 1.6; color: var(--ink); }
.pf-words p { margin: 0 0 8px; }
.pf-words p:last-child { margin-bottom: 0; }
/* charts */
.pf-line { fill: none; stroke-width: 2; stroke-linejoin: round; stroke-linecap: round; }
.pf-pt { fill: var(--surface); stroke-width: 2; }
.pf-pt.faded { stroke-dasharray: 2 2; }
.pf-wf-total { fill: var(--viz-1); }
.pf-wf-down { fill: var(--viz-2); opacity: .8; }
.pf-wf-end { fill: var(--viz-3); }
.pf-wf-link { stroke: var(--line-strong); stroke-dasharray: 3 3; }
.pf-wf-val { font-weight: 600; fill: var(--ink-soft); }
.pr-hit:focus + .pf-bar, .pr-hit:hover + .pf-bar, .pr-hit:focus ~ .pf-wf, .pr-hit:hover ~ .pf-wf { filter: brightness(1.12); }
.pf-sw { display: inline-block; width: 10px; height: 10px; border-radius: 2px; margin-right: 5px; vertical-align: -1px; }
.pf-donut { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: var(--s3); align-items: center; position: relative; }
.pf-donut-svg { width: 168px; height: 168px; }
.pf-donut-c { font-size: 13px; font-weight: 700; fill: var(--ink); }
.pf-donut-legend { display: grid; gap: 4px; font-size: var(--t-sm); min-width: 0; }
.pf-dl { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: 8px; align-items: center; }
.pf-dl i { width: 12px; height: 12px; border-radius: 3px; display: inline-block; }
.pf-dl-n { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--ink); }
.pf-dl-v { white-space: nowrap; color: var(--ink); }
.pf-dl-v small { color: var(--muted); }
.pf-arc { cursor: default; }
.pf-arc:focus { outline: none; filter: brightness(1.12); }
.pf-printhead { display: none; }
@media (max-width: 760px) {
  .pf-donut { grid-template-columns: 1fr; justify-items: center; }
  .pf-f select, .pf-f input { max-width: 100%; }
}
@media print {
  :root { --surface: #fff; --surface-2: #fff; --surface-3: #f2f2f2; --ink: #111; --ink-soft: #333; --muted: #555; --line: #cfcfcf; --line-strong: #999; }
  body { background: #fff !important; color: #111 !important; }
  .pf-printhead { display: block; font-size: 11px; color: #333; border-bottom: 1px solid #999; padding-bottom: 4px; margin-bottom: 10px; }
  .pr-tabs, .pr-year, .pr-folders, .pf-top, #pfBar, .pr-tip, .linkbtn, .btn, .rail-right, .rail-left, .topbar, .sidebar, .composer, .list-head { display: none !important; }
  /* The app's three-column grid stays a grid with two hidden rails, so the page printed in a 250px column.
     Print is one column, full width. */
  .app, .body, .rail-center { display: block !important; width: auto !important; max-width: none !important; margin: 0 !important; padding: 0 !important; grid-template-columns: none !important; }
  .card, .pr-card2, .pr-tile, .pr-tiles { break-inside: avoid; page-break-inside: avoid; box-shadow: none !important; }
  .pr-tablewrap { overflow: visible !important; }
  #list, .body, .pr-wrap, .rail-center { overflow: visible !important; height: auto !important; max-height: none !important; }
  .pf-grid2 { grid-template-columns: 1fr 1fr; }
  .pf-numbers:empty { display: none; }
}

.pr-dim { color: var(--muted); }
.pr-delta { font-variant-numeric: tabular-nums; white-space: nowrap; }
.pr-delta.up { color: var(--good); }
.pr-delta.down { color: var(--danger); }

/* A server's refusal, where the person is looking. One amber line of TEXT — not a boxed alert, and
   never a toast behind a dialog. */
.pr-warn-line { color: var(--warn); font-size: var(--t-sm); line-height: 1.45; margin-top: var(--s2); }
.pr-warn-line[hidden] { display: none; }

.pr-back { display: inline-flex; align-items: center; gap: 6px; color: var(--muted); font-size: var(--t-sm); font-weight: 600; text-decoration: none; }
.pr-back:hover { color: var(--ink); }
.pr-back:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r-sm); }

.pr-empty2 { padding: var(--s5); }
.pr-empty-t { color: var(--ink); font-weight: 600; font-size: var(--t-base); }
.pr-empty-h { margin-top: 6px; font-size: var(--t-sm); line-height: 1.5; }
.pr-empty-a { margin-top: var(--s4); }

/* ⚠ Settle the year's tiles get a WIDER track. Paid so far and Owed are the only figures in the
   workspace shown to the cent, and .pr-tile-v is nowrap (a signed figure must never break after its
   sign) — so "$200,930.99" needed 153px of a 139px content box and drew straight through the tile's
   rounded border at 1223px. Nothing scrolls; the number simply spilled. */
#prPlace .pr-settle-tiles .pr-tiles { grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); }

/* The month table without its .viz-table-wrap (monthTable wrap:false — see components.js): a narrow
   table that needs no internal scrollbar must not carry the class that evicts the leaderboard rail. */
.pr-table-plain { min-width: 0; }
.pr-table-plain .viz-table { width: 100%; }

/* Settle the year: label, amount, note, buttons — one row that wraps rather than a form that scrolls. */
.pr-settle-form { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); font-size: var(--t-sm); color: var(--muted); }
.pr-settle-form label { display: inline-flex; align-items: center; gap: 6px; }
.pr-settle-form input { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; }
.pr-settle-form input.pr-paid { width: 130px; font-variant-numeric: tabular-nums; }
.pr-settle-form input.pr-note { flex: 1 1 180px; }
.pr-settle-form .btn { white-space: nowrap; }
/* ⚠ .btn-primary is width:100% app-wide (styles.css:188 — it exists for the login form's stacked
   buttons; .ap-banner, #abBulk and #apvBillBulk each override it the same way). Left alone, Save
   would take the whole card and push the note field and "Mark as settled with them" onto lines of
   their own — a form that reads as three separate decisions instead of one row. */
.pr-settle-form .btn-primary { width: auto; padding: var(--s3) var(--s4); }

.pr-dlg .pr-dlg-body { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.pr-dlg .action-row { margin-top: var(--s4); }

.pr-skel { display: grid; gap: var(--s4); }
.pr-skel .pr-tile .skel-line:last-child { margin-bottom: 0; }

@media (max-width: 760px) {
  /* The 260px ceiling is there so a tile is one size across the DESKTOP screens. On a phone the column
     is narrower than the cap, so a capped tile would sit in a 340px column with 80px of dead space on
     its right — let it fill instead. */
  .pr-tiles { grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
  .pr-qrow { grid-template-columns: minmax(0, 1fr); }     /* the button drops under the sentence */
  .pr-head { gap: var(--s2); }
  .pr-head .pr-year { margin-left: 0; }
}

/* Doctors: six columns in the app's .admin-table (Doctor · Type · Counts toward tiers · Bonus · Next
   tier · Settle the year). Right-align the money on .pr-num — the class that already makes it tabular
   — and tighten the cells on laptops so the six columns fit the ~531px card at 1223 without the
   wrapper scrolling. A row is a link in its first cell (keyboard, middle-click, hover), so the whole
   row only ever needs the pointer. */
#prPlace .admin-table th.pr-num, #prPlace .admin-table td.pr-num { text-align: right; }
.pr-dtable th, .pr-dtable td { vertical-align: top; }
.pr-dtable td .pr-dim { font-size: var(--t-xs); margin-top: 2px; }
.pr-dtable tbody tr[data-href] { cursor: pointer; }
.pr-dtable tbody tr[data-href]:hover td { background: var(--surface-2); }
.pr-dtable a.linkbtn { font-size: inherit; }
@media (min-width: 761px) and (max-width: 1400px) { .pr-dtable th, .pr-dtable td { padding: 7px 7px; font-size: var(--t-sm); } }
@media (min-width: 761px) and (max-width: 1300px) { .pr-dtable th, .pr-dtable td { padding: 5px 4px; font-size: var(--t-xs); } }

/* ==================================================================================================
   PHASE C — the guided review (public/production/reports.js + review/*).
   Same rules as the block above: tokens only, tabular figures, chips not alerts, and nothing here may
   widen its container — the Lines step's table is the widest thing in the workspace and it owns its
   own .pr-tablewrap.
   ================================================================================================== */

/* ---- the Reports list ----
   The app's .admin-table in a .viz-table-wrap, like Doctors. Seven columns at 1223 with the rail in
   place is tight, so the same two laptop steps tighten the cells rather than letting the wrapper
   scroll. The action column never wraps: "Continue" broken across two lines reads as two words. */
.pr-rtable th, .pr-rtable td { vertical-align: top; }
.pr-rtable td .pr-dim, .pr-rtable td small { display: block; font-size: var(--t-xs); color: var(--muted); margin-top: 2px; }
.pr-rtable .pr-rt-act { text-align: right; white-space: nowrap; }
.pr-rtable .pr-rt-act .btn { white-space: nowrap; }
.pr-rtable td .chip { margin-left: 4px; }
.pr-rtable .pr-rt-name { min-width: 0; overflow-wrap: break-word; }
@media (min-width: 761px) and (max-width: 1400px) { .pr-rtable th, .pr-rtable td { padding: 7px 7px; font-size: var(--t-sm); } }
@media (min-width: 761px) and (max-width: 1300px) { .pr-rtable th, .pr-rtable td { padding: 5px 4px; font-size: var(--t-xs); } }

/* The list's one header control ("Check for new reports") sits in the card head beside the title. */
.pr-listhead { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; }

/* ---- the report header (review/index.js) ----
   Title, kind chip, "covers …", the state chip, and a collapsed "About this report". One line of
   facts, never a stack of boxes. */
.pr-rhead { display: grid; gap: 6px; margin-bottom: var(--s4); }
.pr-rhead h2 { margin: 0; font-size: var(--t-lg); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; min-width: 0; }
.pr-rhead h2 .chip { flex: none; }
.pr-rfact { font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.pr-rback { margin-bottom: var(--s2); }
.pr-rabout > summary { cursor: pointer; color: var(--muted); font-size: var(--t-sm); width: fit-content; }
.pr-rabout > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r-sm); }
.pr-rabout-body { margin-top: 6px; font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.pr-rabout-body ul { margin: 6px 0 0; padding-left: 18px; }

/* ---- the stepper ----
   Three steps in a row, joined by a chevron drawn in ::after so no character sits in the accessible
   name. Every step is a link (see components.js: no step is ever disabled); the current one is filled.
   It wraps to one step per line on a phone rather than scrolling sideways. */
.pr-stepper { display: flex; flex-wrap: wrap; align-items: stretch; gap: var(--s2); margin: 0 0 var(--s2); min-width: 0; }
.pr-step {
  display: flex; align-items: center; gap: 8px; min-width: 0; flex: 0 1 auto;
  padding: 7px 12px; border: 1px solid var(--line-strong); border-radius: var(--r-md);
  background: var(--surface); color: var(--ink-soft); text-decoration: none; line-height: 1.25;
}
.pr-step:hover { border-color: var(--primary); color: var(--ink); }
.pr-step:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; }
.pr-step-n {
  flex: none; display: inline-flex; align-items: center; justify-content: center;
  width: 20px; height: 20px; border-radius: var(--r-full);
  background: var(--surface-3); color: var(--muted);
  font-size: 11px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.pr-step-b { display: grid; min-width: 0; }
.pr-step-t { font-size: var(--t-sm); font-weight: 600; color: var(--ink); }
.pr-step-s { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; }
.pr-step.on { border-color: var(--primary); background: var(--primary-soft); }
.pr-step.on .pr-step-n { background: var(--primary); color: var(--on-primary); }
.pr-step.done .pr-step-n { background: var(--good); color: var(--on-primary); }
/* The chevron between steps. It is decorative and belongs to no step, so it is a flex item of its own
   drawn by the row rather than a character inside a link's text. */
.pr-stepper .pr-step:not(:last-child) { position: relative; margin-right: 14px; }
.pr-stepper .pr-step:not(:last-child)::after {
  content: ""; position: absolute; right: -11px; top: 50%; width: 6px; height: 6px;
  border-top: 1.5px solid var(--line-strong); border-right: 1.5px solid var(--line-strong);
  transform: translateY(-50%) rotate(45deg);
}
.pr-stephint { font-size: var(--t-sm); color: var(--muted); line-height: 1.5; margin-bottom: var(--s4); }

/* ---- the segmented control ----
   One question, one answer: two or three segments joined into a single control. Used for the Lines
   step's Doctors | Labs | Fees and its Needs a look | All lines. */
.pr-seg {
  display: inline-flex; flex-wrap: wrap; max-width: 100%; min-width: 0;
  border: 1px solid var(--line-strong); border-radius: var(--r-md); overflow: hidden; background: var(--surface);
}
.pr-segb {
  display: inline-flex; align-items: baseline; gap: 6px; min-width: 0;
  padding: 6px 12px; border: 0; border-left: 1px solid var(--line);
  background: transparent; color: var(--ink-soft); font: inherit; font-size: var(--t-sm); font-weight: 600;
  text-decoration: none; cursor: pointer; white-space: nowrap;
}
.pr-segb:first-child { border-left: 0; }
.pr-segb small { font-weight: 400; color: var(--muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.pr-segb:hover { background: var(--surface-2); color: var(--ink); }
.pr-segb.on { background: var(--primary); color: var(--on-primary); }
.pr-segb.on small { color: var(--on-primary); opacity: .85; }
.pr-segb:focus-visible { outline: 2px solid var(--primary); outline-offset: -2px; }

/* ---- step 1: the names to decide ----
   One row per name: who, how much, why it is here, and the two ways out (pick an account, or say it is
   a room or queue). A grid, not a table — the Account select and the toggle are controls, and a table
   cell that holds a <select> cannot be tightened at 1223 without clipping it. */
/* ⚠ NOT `.pr-names` — that class is TAKEN, by the old review's "2 names not linked" line (line 215
   above). Two rules for one name in one stylesheet is how a screen nobody edited changes shape. */
.pr-namelist { display: grid; gap: var(--s3); }
.pr-nrow {
  display: grid; grid-template-columns: minmax(0, 1.4fr) auto minmax(0, 1fr) auto; gap: var(--s2) var(--s3);
  align-items: center; padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2);
}
.pr-nwho { min-width: 0; }
.pr-nname { font-weight: 600; color: var(--ink); overflow-wrap: break-word; }
.pr-nsub { font-size: var(--t-xs); color: var(--muted); font-variant-numeric: tabular-nums; margin-top: 2px; }
.pr-nfig { font-variant-numeric: tabular-nums; font-weight: 600; white-space: nowrap; }
.pr-npick { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; min-width: 0; }
.pr-npick select { min-width: 0; max-width: 100%; flex: 1 1 160px; font-size: var(--t-sm); padding: 5px 8px; }
.pr-nact { display: flex; gap: var(--s2); align-items: center; white-space: nowrap; }
.pr-nrow .pr-warn-line { grid-column: 1 / -1; margin-top: 0; }
/* Saving: the row dims and says what is happening — the server re-totals every import that mentions
   the name, which is not instant, and a row that just froze reads as a broken button. */
.pr-nrow.saving { opacity: .6; }
.pr-nrow.saving select, .pr-nrow.saving button { pointer-events: none; }
/* Done: a short fade as the row leaves. motion.css owns the tokens; at reduced motion it simply goes. */
.pr-nrow.leaving { opacity: 0; transform: translateY(-2px); transition: opacity 140ms ease-out, transform 140ms ease-out; }
@media (prefers-reduced-motion: reduce) { .pr-nrow.leaving { transition: none; } }
.pr-nauto { margin-top: var(--s4); }
.pr-nauto > summary { cursor: pointer; color: var(--muted); font-size: var(--t-sm); width: fit-content; }
.pr-nauto > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r-sm); }
@media (max-width: 1100px) {
  .pr-nrow { grid-template-columns: minmax(0, 1fr) auto; }
  .pr-npick, .pr-nact { grid-column: 1 / -1; }
}
@media (max-width: 760px) {
  .pr-nrow { grid-template-columns: minmax(0, 1fr); }
  .pr-nfig { grid-column: 1; }
  .pr-stepper { gap: 6px; }
  .pr-stepper .pr-step:not(:last-child) { margin-right: 0; }
  .pr-stepper .pr-step:not(:last-child)::after { display: none; }
  .pr-step { flex: 1 1 100%; }
  .pr-seg { display: flex; width: 100%; }
  .pr-segb { flex: 1 1 auto; justify-content: center; }
}

/* ---- step 3: approve ----
   Three answers and one question: what publishing does, what it changes, what is still loose — then
   Publish / Reject. No new colour and no new box: the sentence is text, the change is a table, the
   caveat is a muted line. */
.pr-approve { display: grid; gap: var(--s4); min-width: 0; }
.pr-approve-lead { margin: 0; font-size: var(--t-base); line-height: 1.5; color: var(--ink); }
.pr-approve-months { margin-top: var(--s2); }
.pr-approve-lines { display: grid; gap: var(--s2); margin-top: var(--s3); }
.pr-approve-note { margin: 0; }
.pr-approve-actions { display: flex; flex-wrap: wrap; gap: var(--s4); align-items: center; }
/* ⚠ .btn-primary is width:100% app-wide (styles.css:188 — the login form's stacked buttons; see the
   same override on .pr-settle-form above). Left alone, Publish takes the whole column and Reject drops
   to a line of its own, which reads as two unrelated decisions rather than one with a way out. */
.pr-approve-actions .btn-primary { width: auto; padding: var(--s3) var(--s4); }
/* The same trap inside every dialog in this workspace — the kit's .action-row holds a .btn-primary and
   a .linkbtn side by side, and a 100%-wide confirm button pushed Cancel onto its own line. */
.pr-dlg .action-row .btn-primary { width: auto; padding: var(--s3) var(--s4); }
.pr-dlg-label { display: block; margin-top: var(--s3); margin-bottom: 6px; color: var(--ink-soft); font-weight: 600; }
.pr-dlg textarea.pr-why {
  display: block; width: 100%; box-sizing: border-box; min-height: 78px; resize: vertical;
  font-size: var(--t-sm); line-height: 1.45; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
}
.pr-dlg textarea.pr-why:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }
/* The before/after tables: six money columns in the app's .admin-table, tightened on laptops the way
   the roster is (.pr-dtable above) so they fit the ~531px card at 1223 without the wrapper scrolling. */
#prPlace .pr-atable th.pr-num, #prPlace .pr-atable td.pr-num { text-align: right; }
.pr-atable td, .pr-atable th { vertical-align: top; white-space: nowrap; }
.pr-atable td:first-child, .pr-atable th:first-child { white-space: normal; }
@media (min-width: 761px) and (max-width: 1400px) { .pr-atable th, .pr-atable td { padding: 7px 7px; font-size: var(--t-sm); } }
@media (min-width: 761px) and (max-width: 1300px) { .pr-atable th, .pr-atable td { padding: 5px 4px; font-size: var(--t-xs); } }

/* ---- Phase C, the guided review's remaining rules (2026-09-07) ----
   A grep of every class the new modules emit against the three stylesheets left these with no rule.
   Appended, never spliced: this file is written by more than one session. */
/* Screen-reader-only. The workspace had no such class and two controls need one: the Reports list's
   action column header ("Open") and the Names step's per-row "Account for <name>" label. Without it
   both print as visible text. */
.pr-vh { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
/* The review frame and the step wrappers. minmax(0, 1fr) at every level or the Lines step's twelve
   columns widen the column and #list scrolls sideways (owner rule §1). */
.pr-review { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; min-width: 0; }
.pr-names-step { min-width: 0; }
.pr-lines-step { display: grid; grid-template-columns: minmax(0, 1fr); gap: 0; min-width: 0; }
/* The hook engage.css §7 reads to step the leaderboard rail aside at ≤1680px — its twin on the table
   itself is .pr-lines (the @media rule above). */
.pr-wide { min-width: 0; }
.pr-secnav { display: flex; flex-wrap: wrap; gap: var(--s2); margin-bottom: var(--s3); min-width: 0; }
/* Parser warnings — a line inside the "About this report" fold and nowhere else, never a banner. */
.pr-rwarn { margin-top: 6px; }
.pr-rwarn-list ul { margin: 6px 0 0; padding-left: 18px; }
.pr-rwarn-list li { margin-bottom: 2px; overflow-wrap: break-word; }
.pr-rwarn-list[hidden] { display: none; }
/* "Re-totalling…" on a Names row: .chip (styles.css) sets display:inline-flex, and an author `display`
   beats the UA [hidden] — the same trap .pr-bulk[hidden] and friends spell out above. */
.pr-nwait[hidden] { display: none; }
/* The Credited-to cell and the row tick: JS hooks, each given the one rule it actually wants.
   (.pr-hf-find / -text / -from / -to / -min / -max are JS hooks too, styled by attribute at
   `.pr-hf input[type=…]` above.) */
.pr-credcell, .pr-supcell { min-width: 0; }
.pr-rowck { cursor: pointer; }

/* ==================================================================================================
   PHASE D (2026-09-07) — Practice money (.pm-), Settings (.ps-), and the release gate (.pr-rel).
   Appended, never spliced: this file is written by more than one session. Same rules as the blocks
   above: tokens only, tabular figures, chips not alerts, and nothing here may widen its container —
   every wide table sits in its own .viz-table-wrap and scrolls INSIDE it (NO-SIDEWAYS-SCROLL rule).
   ================================================================================================== */

/* ---- D1. Practice money (public/production/practice.js) ---- */
.pm-place { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); min-width: 0; }
/* A card head that holds two controls (the Fees series select and Show numbers). */
.pm-head { display: flex; flex-wrap: wrap; gap: var(--s3); align-items: center; }
.pm-series { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs); color: var(--muted); }
.pm-series select { font-size: var(--t-xs); padding: 4px 6px; max-width: 100%; }

/* The AccuLab checks ledger: the app's .admin-table in a .viz-table-wrap, like Doctors. Money right-
   aligned on .pr-num (the class that already makes it tabular); the action column never wraps. */
#prPlace .pm-ledger th.pr-num, #prPlace .pm-ledger td.pr-num { text-align: right; }
.pm-ledger th, .pm-ledger td { vertical-align: top; }
.pm-ledger td .pr-dim { font-size: var(--t-xs); margin-top: 2px; }
.pm-ledger .pm-act { text-align: right; white-space: nowrap; }
.pm-ledger .pm-act .btn { white-space: nowrap; }
.pm-ledger tr.pm-total th { border-bottom: 0; color: var(--ink); font-weight: 600; }
.pm-ledger tr.pm-total th:first-child { text-align: left; }
/* The one open inline form: a full-width row under the month it belongs to, on the second surface so
   it reads as part of that row and not as another row of figures. */
.pm-ledger tr.pm-ledger-form td { background: var(--surface-2); text-align: left; white-space: normal; }
.pm-ledger tr.pm-ledger-form .pr-settle-form { margin-top: 0; padding-top: 0; border-top: 0; }
.pm-ledger tr.pm-ledger-form .pr-warn-line { margin-top: 6px; }
/* The amount and note boxes (both editors). Own classes — `.pr-note` is a muted-text rule elsewhere in
   this file and must not land on an <input>. */
.pr-settle-form input.pm-amt { width: 130px; font-variant-numeric: tabular-nums; }
.pr-settle-form input.pm-note { flex: 1 1 180px; }
/* Fees on the annual: the five kinds in a .viz-table; the first column is words. */
.pm-kinds th:first-child, .pm-kinds td:first-child { text-align: left; white-space: normal; }
.pm-kinds tr.pm-total th { border-bottom: 0; color: var(--ink); }
.pm-kinds td .chip { margin-left: 4px; }
/* Laptops (the rail present, a ~531px card at 1223): tighten the ledger's six columns like the roster. */
@media (min-width: 761px) and (max-width: 1400px) { .pm-ledger th, .pm-ledger td { padding: 7px 7px; font-size: var(--t-sm); } }
@media (min-width: 761px) and (max-width: 1300px) { .pm-ledger th, .pm-ledger td { padding: 5px 4px; font-size: var(--t-xs); } }
@media (max-width: 760px) {
  .pm-head { gap: var(--s2); }
  .pr-settle-form input.pm-amt { width: 110px; }
}

/* ---- D2. Settings (public/production/settings.js): the registry, the bonus ladder, About ----
   The Names table sits in the kit's .viz-table-wrap and scrolls INSIDE it — six columns with two selects
   will not fit a 531px card at 1223. */
.ps-place { display: grid; grid-template-columns: minmax(0, 1fr); gap: var(--s4); }
.ps-place .pr-folders { margin-bottom: 0; }              /* the grid gap already separates the folders from the card */
.ps-table td { vertical-align: top; }
.ps-table select { font-size: var(--t-sm); padding: 5px 8px; min-width: 150px; max-width: 100%; }
.ps-nname { font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.ps-nchips { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 4px; }
.ps-table .pr-warn-line { margin-top: 4px; }
/* Saving: the row dims and says what is happening — the server re-totals every import that mentions the
   name, which is not instant, and a row that just froze reads as a broken control. */
.ps-row.saving { opacity: .6; }
.ps-row.saving select { pointer-events: none; }
.ps-wait[hidden], .ps-onfile[hidden] { display: none; }
.ps-saved-cell { white-space: nowrap; }
.ps-saved { color: var(--good); font-weight: 600; font-size: var(--t-sm); }
.ps-note { font-size: var(--t-sm); color: var(--muted); line-height: 1.5; margin-top: var(--s3); }
/* The ladder editor: three bands, each a from-$ and a rate-% box. */
.ps-tiers { margin-top: var(--s3); }
.ps-bands { display: grid; gap: var(--s2); }
.ps-band { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; font-size: var(--t-sm); color: var(--muted); }
.ps-band label { display: inline-flex; align-items: center; gap: 6px; }
.ps-band input { width: 110px; font-variant-numeric: tabular-nums; font-size: var(--t-sm); padding: 5px 8px; text-align: right; min-width: 0; }
.ps-band input[data-f="rate"] { width: 64px; }
.ps-bandn { font-weight: 600; color: var(--ink); min-width: 52px; }
.ps-form-row { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; margin-top: var(--s3); padding-top: var(--s3); border-top: 1px solid var(--line); font-size: var(--t-sm); color: var(--muted); }
.ps-form-row label { display: inline-flex; align-items: center; gap: 6px; }
.ps-form-row select { font-size: var(--t-sm); padding: 5px 8px; }
.ps-form-row .btn-primary { width: auto; padding: var(--s3) var(--s4); }
/* The versions list: the bands column is a sentence, so it wraps and reads left (the .viz-table default is a figure). */
.ps-vtable td, .ps-vtable th { white-space: normal; text-align: left; }
.ps-vtable td:first-child { white-space: nowrap; }
/* Facts: short paragraphs, the key phrase in ink. */
.ps-facts { display: grid; gap: var(--s2); font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.5; }
.ps-facts b { color: var(--ink); }
.ps-radios { display: grid; gap: var(--s2); font-size: var(--t-sm); color: var(--ink); }
.ps-radios label { display: flex; gap: 8px; align-items: flex-start; }
.ps-radios label.off { color: var(--muted); }
.ps-radios input { margin-top: 3px; }
@media (max-width: 760px) {
  .ps-band input { width: 96px; }
  .ps-band input[data-f="rate"] { width: 56px; }
  /* ⚠ mobile.css turns every .admin-table into its own `display: block; overflow-x: auto; nowrap`
     scroller on phones. With two selects a row, the registry's cells then reached 1,175px inside a
     274px block — and #list itself scrolled sideways to 622px at 390 (measured 09-07). Put the table
     back to being a table so the kit's .viz-table-wrap is the ONE scroller, let the cells wrap, and cap
     the two selects (their widest option is "Nurse practitioner — left the practice"). */
  .ps-table { display: table; overflow: visible; white-space: normal; }
  .ps-table select { min-width: 120px; max-width: 180px; }
  /* …and even then Chrome let the two <select>s' layout overflow leak past the wrapper's overflow:auto
     into #list (367px of scroll in a 340px list; every other element measured inside). `contain: paint`
     clips the wrapper for real; the native select menus draw outside the DOM and are unaffected. */
  .ps-place .viz-table-wrap { contain: paint; }
}
/* The ladder on the Settings card has no fill to speak of and three ticks a hundred dollars apart on a
   ~$860k scale — in a 581px card at 1223 the labels "$550k · 25%" / "$650k · 35%" / "$750k · 40%" ran
   into one another (measured 09-07). Stack each label's rate under its amount here: half the width,
   and the ladder keeps the doctor page's one-line labels where the card is wider. */
.ps-place .pr-tick-rate { display: block; }
.ps-place .pr-ladder-wrap { padding-bottom: 38px; }

/* ---- D5. Release / Hold (doctor.js hero head, doctors.js "Doctor's page" column + card head) ----
   A chip states the fact (Visible / Not yet) and ONE small button does the opposite. Stacked in the table
   cell so the seventh column costs the ~531px card at 1223 one chip-width, not a chip plus a button side
   by side. (.btn-sm is styles.css's; the cell rule only tightens it inside the roster table.) */
.pr-rel { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.pr-rel-head { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.pr-rel-cell { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.pr-rel-btn { white-space: nowrap; }
.pr-dtable td .pr-rel-btn { padding: 2px 8px; font-size: var(--t-xs); line-height: 1.4; }
.pr-hero .pr-warn-line { margin: 0; }

/* ==================================================================================================
   FIRST-YEAR PRORATION (2026-09-07 21:00) — hire dates, last days worked, leaves of absence.
   Appended, never spliced: this file is written by more than one session. Tokens only; every date box is
   the app's own <input type="date"> at the size of the selects beside it; nothing here may widen its
   container — the fields WRAP at 1223 and again at 390, and no wrapper scrolls for them.
   ================================================================================================== */

/* ---- the Names step's 'hire' row: the date line spans the row's grid, under the two selects ---- */
.pr-nrow .pr-nhire { grid-column: 1 / -1; display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; min-width: 0; font-size: var(--t-sm); color: var(--muted); }
.pr-nrow .pr-nhire label { font-weight: 600; color: var(--ink-soft); }
.pr-nrow .pr-nhire input[type="date"] { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; font-variant-numeric: tabular-nums; }
/* ⚠ .btn-primary is width:100% app-wide (styles.css:188); left alone, Save takes the whole line. */
.pr-nrow .pr-nhire .btn-primary { width: auto; padding: 5px 12px; }
.pr-nrow.saving .pr-nhire input { pointer-events: none; }
/* The last-day ask: one date box inside the kit's dialog, at the size of the reason textarea's text. */
.pr-dlg input.pr-dlg-date { display: block; font-size: var(--t-sm); padding: 6px 8px; min-width: 0; max-width: 100%; font-variant-numeric: tabular-nums; border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); }
.pr-dlg input.pr-dlg-date:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }

/* ---- Settings → Names: the People card (settings.js personHtml) ----
   One BLOCK per person on the second surface, like a Names-step row: the head (name, chips, the tick or the
   wait chip), the three fields with one Save, the leaves. A grid of blocks, never a table — a table cell that
   holds three date boxes cannot be tightened at 1223 without clipping them. */
.ps-people { display: grid; gap: var(--s3); }
.ps-person { padding: var(--s3); border: 1px solid var(--line); border-radius: var(--r-md); background: var(--surface-2); min-width: 0; }
.ps-phead { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; min-width: 0; }
.ps-phead .ps-nchips { margin-top: 0; }
.ps-pfields { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; margin-top: var(--s2); min-width: 0; font-size: var(--t-sm); color: var(--muted); }
.ps-pfields label { font-weight: 600; color: var(--ink-soft); }
.ps-pfields input[type="date"] { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; font-variant-numeric: tabular-nums; }
.ps-pfields .ps-ptoggle { display: inline-flex; align-items: center; gap: 6px; font-weight: 400; color: var(--ink); cursor: pointer; }
.ps-pfields .btn-primary { width: auto; padding: 5px 12px; }
/* The leaves: a heading word, the list (dates – note – Remove), then the add form on one wrapping line. */
.ps-leaves { margin-top: var(--s2); padding-top: var(--s2); border-top: 1px dashed var(--line); font-size: var(--t-sm); color: var(--muted); min-width: 0; }
.ps-leaves-h { font-weight: 600; color: var(--ink-soft); margin-right: var(--s2); }
.ps-leave-list { list-style: none; margin: 4px 0 0; padding: 0; display: grid; gap: 4px; }
.ps-leave-list li { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: baseline; font-variant-numeric: tabular-nums; color: var(--ink); min-width: 0; }
.ps-leave-list li .pr-dim { overflow-wrap: anywhere; }
.ps-leave-list li .linkbtn { font-size: var(--t-xs); }
.ps-leave-form { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; margin-top: var(--s2); min-width: 0; }
.ps-leave-form label { font-weight: 600; color: var(--ink-soft); }
.ps-leave-form input { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; }
.ps-leave-form input[type="date"] { font-variant-numeric: tabular-nums; }
.ps-leave-form input.ps-leave-note { flex: 1 1 200px; }
/* Saving: the block dims and the wait chip says so (a hire date re-prices targets — it is quick, and the
   chip says "Saving…", never "Re-totalling…"). */
.ps-person.saving { opacity: .6; }
.ps-person.saving input, .ps-person.saving button { pointer-events: none; }
.ps-person .pr-warn-line { margin-top: var(--s2); }
.ps-person .ps-saved { margin-left: auto; }
/* Phones: every label and its box become a line of their own, the box filling it; the toggle and the
   buttons keep their own width. The Names-step date line does the same. */
@media (max-width: 760px) {
  .ps-pfields label:not(.ps-ptoggle), .ps-leave-form label { flex: 1 1 100%; margin-bottom: -4px; }
  .ps-pfields input[type="date"], .ps-leave-form input { flex: 1 1 100%; }
  .ps-pfields .ps-ptoggle { flex: 1 1 100%; }
  .ps-person .ps-saved { margin-left: 0; }
  .pr-nrow .pr-nhire label { flex: 1 1 100%; margin-bottom: -4px; }
  .pr-nrow .pr-nhire input[type="date"] { flex: 1 1 100%; }
}

/* ==================================================================================================
   THE NURSE-PRACTITIONER FORMULA (2026-09-07 23:38) — the base salary.
   Owner: "Set the bonus threshold at 3x the NP's base salary. Borgia makes 135,000." Appended, never spliced
   (this file is written by more than one session). Two money boxes — the Names step's 'salary' row
   (names.js salaryHtml) and the People card's field (settings.js personHtml) — and nothing else. Tokens
   only; the box sits at the size of the date boxes beside it; the fields WRAP at 1223 and 390, no scroller.
   ================================================================================================== */

/* The money box: a "$" sign glued to a right-aligned, tabular text box (inputmode numeric — never
   type=number, see format.js parseDollars). One rule for both screens. */
.pr-money { display: inline-flex; align-items: center; gap: 4px; min-width: 0; }
.pr-money-sign { color: var(--muted); font-size: var(--t-sm); }
.pr-money input { width: 110px; min-width: 0; max-width: 100%; font-size: var(--t-sm); padding: 5px 8px; text-align: right; font-variant-numeric: tabular-nums; }
/* The Names step's 'salary' row reuses the hire line's layout (.pr-nhire: spans the grid under the two
   selects, wraps, dims its hint). The derived threshold beside the box is a figure, so it is tabular. */
.pr-nrow .pr-nsalary .pr-dim { font-variant-numeric: tabular-nums; }
.pr-nrow.saving .pr-nsalary input { pointer-events: none; }
/* The People card: the field's label for a physician's dash is a plain span (no box to point at), styled
   like the labels around it; the derived threshold and the dash are dim, tabular figures. */
.ps-pfields .ps-plabel { font-weight: 600; color: var(--ink-soft); }
.ps-pfields .ps-thr, .ps-pfields .ps-nosal { font-variant-numeric: tabular-nums; }
.ps-pfields .ps-nosal { cursor: help; }
/* Phones: the box takes its own line like the date boxes; the sign stays glued to it. */
@media (max-width: 760px) {
  .ps-pfields .pr-money, .pr-nrow .pr-nsalary .pr-money { flex: 1 1 100%; }
  .ps-pfields .pr-money input, .pr-nrow .pr-nsalary .pr-money input { flex: 1 1 auto; width: auto; }
  .ps-pfields .ps-plabel { flex: 1 1 100%; margin-bottom: -4px; }
}

/* ==================================================================================================
   ACCOUNT · CLAIM · CHART (2026-09-07, owner: "i want the account number and claim number to have its own
   columns, and for you to use this report to connect it to ecw patient chart"). Appended, never spliced
   (this file is written by more than one session); the column PLAN itself lives in the FIT block above,
   because a plan is one sum. Tokens only; chips not alerts; nothing here may widen its container — the
   lines table already sits in .pr-tablewrap, which owns any sideways scroll (never the page, never #list).
   ================================================================================================== */

/* The two number cells (lines.js rowHtml): one line, tabular digits, never split mid-number. On a phone
   the table is auto layout and the wrapper scrolls, so nowrap costs nothing there either. */
.pr-lines td.pr-acctcell, .pr-lines td.pr-claimcell { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* "Chart" — a small pill under the account number, the primary colour saying it does something (like .pr-cred
   and .pr-sup beside it), on its own line so the Account column stays as narrow as its header. */
.pr-chart { display: block; margin-top: 2px; padding: 1px 7px; font: inherit; font-size: var(--t-xs); line-height: 1.4; color: var(--primary);
  background: transparent; border: 1px solid color-mix(in srgb, var(--primary) 40%, transparent); border-radius: var(--r-full); cursor: pointer; }
.pr-chart:hover { background: color-mix(in srgb, var(--primary) 10%, var(--surface)); }
.pr-chart:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
@media (min-width: 761px) and (max-width: 1300px) { .pr-chart { font-size: 10px; padding: 0 5px; } }   /* the 11px tier: 38px wide, inside the 56px column */

/* The Account / Claim popover (filters.js hfBodyHtml): the exact box is the kit's search box; one muted
   sentence under it says what Apply does with a number typed there. */
.pr-hf-hint { font-size: var(--t-xs); color: var(--muted); line-height: 1.4; }

/* The Chart dialog (lines.js chartHtml) inside the kit's .pr-dlg: label · value rows, then the verdict chip with
   its sentence, then the candidates as a plain list. The value column is minmax(0, 1fr) so a long payer name or
   facility wraps inside the 380px card instead of widening it (the phone rule of every dialog here). */
.pr-chart-row { display: grid; grid-template-columns: 96px minmax(0, 1fr); gap: var(--s2); padding: 5px 0; border-bottom: 1px solid var(--line); font-size: var(--t-sm); }
.pr-chart-row > span:last-child { color: var(--ink); overflow-wrap: anywhere; font-variant-numeric: tabular-nums; }
.pr-chart-verdict { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; margin-top: var(--s3); font-size: var(--t-sm); color: var(--ink); }
.pr-chart-verdict > .pr-dim { flex-basis: 100%; font-size: var(--t-xs); }
.pr-chart-cands { flex-basis: 100%; margin: var(--s1) 0 0; padding-left: 18px; font-size: var(--t-sm); color: var(--ink); line-height: 1.5; }
.pr-chart-note { margin-top: var(--s2); font-size: var(--t-xs); line-height: 1.45; }

/* ==================================================================================================
   ORDERED BY · SIGNED BY · NOTE (2026-09-08, owner 09-07 19:50 "the venipuncture credit needs to go to the doctor
   that put in the Orders … check who put in the orders for the labs" · 19:55 "preview the progress note … see who
   signed off the note" · 09-08 10:00 "columns*"). Appended, never spliced (this file is written by more than one
   session); the column PLAN lives in the FIT block above, because a plan is one sum. Tokens only; chips not alerts;
   nothing here may widen its container — the table sits in .pr-tablewrap, which owns any sideways scroll (never the
   page, never #list). The words in the cells are filters.js CHECK_WORDS.
   ================================================================================================== */

/* The three cells (lines.js rowHtml): min-width: 0 like their neighbours, so a long name wraps inside the column. */
.pr-ordcell, .pr-sigcell, .pr-notecell { min-width: 0; }
/* "check" — DIM on purpose: a look-up nobody has run yet is not a warning (6,000 draws a year must not shout). The
   muted ink, a dotted underline saying it does something, the primary colour only on hover / focus. */
.pr-check { background: none; border: 0; padding: 0; font: inherit; color: var(--muted); cursor: pointer; text-align: left;
  text-decoration: underline dotted; text-underline-offset: 2px; }
.pr-check:hover, .pr-check:focus-visible { color: var(--primary); }
.pr-check:disabled { cursor: default; text-decoration: none; opacity: .7; }
/* A found name: plain ink (it is a fact, not a control — the credit follows it through the Credited-to cell). */
.pr-check-who { color: var(--ink); }
/* "no order found" / "no note found" / "protected": muted words; protected in the warn ink, because it is the one
   state the owner cannot clear from here. */
.pr-check-none { color: var(--muted); font-size: var(--t-xs); }
.pr-check-none.pr-check-prot { color: var(--warn); font-weight: 600; }
/* "not linked" beside an ordering name the registry does not know — the Names step's chip, quiet grey. */
.pr-lines .pr-chip.pr-check-unlinked { color: var(--muted); }
/* "Preview" — the same small pill as "Chart" (the primary colour says it does something), sized for its 62px column. */
.pr-preview { display: inline-block; padding: 1px 7px; font: inherit; font-size: var(--t-xs); line-height: 1.4; color: var(--primary);
  background: transparent; border: 1px solid color-mix(in srgb, var(--primary) 40%, transparent); border-radius: var(--r-full); cursor: pointer; white-space: nowrap; }
.pr-preview:hover { background: color-mix(in srgb, var(--primary) 10%, var(--surface)); }
.pr-preview:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
@media (min-width: 761px) and (max-width: 1300px) { .pr-preview { font-size: 10px; padding: 0 5px; } }   /* the 11px tier: 48px wide, inside the 62px column */

/* The bulk bar's check control: its own full-width line under the credit and supervising controls, the same shape
   as .pr-bulk-sup (min-width: 0 from the start — the .pr-nact lesson at 390, so the long button label wraps rather
   than widening the bar). The progress chip beside it: .pr-chip is display:inline-block, and an author `display`
   beats the UA [hidden] — say the hidden state explicitly (the .pr-bulk[hidden] trap above). */
.pr-bulk-check { display: flex; flex-wrap: wrap; gap: var(--s2); align-items: center; flex-basis: 100%; min-width: 0; padding-top: var(--s2); border-top: 1px solid var(--line); }
.pr-bulk-check .btn { white-space: normal; text-align: left; min-width: 0; }
.pr-chip.pr-check-prog { margin-left: 0; font-variant-numeric: tabular-nums; background: color-mix(in srgb, var(--primary) 12%, var(--surface)); color: var(--primary); }
.pr-chip.pr-check-prog[hidden] { display: none; }

/* The note dialog (lines.js openNote) — the kit's .pr-dlg, widened: a progress note is a page, and the 380px card
   (styles.css .chooser-card) would show it through a letterbox. min() keeps it inside a phone; the card's own
   width:100% does the rest. */
.chooser-card.pr-dlg-note { max-width: min(960px, calc(100vw - 24px)); }
.pr-note-head { display: grid; gap: 4px; margin-bottom: var(--s3); font-size: var(--t-sm); color: var(--ink-soft); }
.pr-note-signed { font-size: var(--t-base); color: var(--ink); }
.pr-note-signed b { font-weight: 700; }
.pr-note-meta { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s4); font-variant-numeric: tabular-nums; }
.pr-note-meta b { color: var(--ink); }
.pr-note-hint { font-size: var(--t-xs); line-height: 1.5; overflow-wrap: anywhere; }
/* The copy-able hint: one click selects the whole phrase (user-select: all), the Copy button beside it does the rest. */
.pr-note-copy { user-select: all; -webkit-user-select: all; padding: 1px 5px; border-radius: var(--r-sm); background: var(--surface-2); color: var(--ink); font-size: var(--t-xs); }
/* The note itself: a sandboxed iframe as wide as the card and as tall as the screen allows. White paper on purpose —
   the ONE literal colour in this file: eClinicalWorks' HTML assumes a white page, and a srcdoc document is transparent
   until it paints one, so a dark surface under black text would be unreadable. color-scheme: light for the same
   reason (the UA must not dark-invert the document's form controls or scrollbars into an unreadable mix). */
.pr-note-frame { display: block; width: 100%; height: min(68vh, 760px); border: 1px solid var(--line); border-radius: var(--r-sm); background: #fff; color-scheme: light; box-sizing: border-box; }
@media (max-width: 760px) {
  /* 390: the head stacks, the hint wraps, the frame takes what the phone gives; the bulk button wraps to two lines. */
  .pr-note-frame { height: min(60vh, 560px); }
  .pr-note-meta { gap: 2px var(--s3); }
  .pr-bulk-check .btn { flex: 1 1 100%; }
}

/* ==================================================================================================
   NOTES (2026-09-08 — spec D7/D8, the owner's 09-08 rules: office notes against 24 h, imaging reads against 5 days,
   labs excluded; the noon reminders, the payroll-Wednesday hold, the leave KIND). Appended, never spliced (this file
   is written by more than one session). Tokens only; chips not alerts; tabular figures; nothing here may widen its
   container — the per-provider table sits in .pr-tablewrap, which owns any sideways scroll (never the page).
   ================================================================================================== */

/* ---- Performance → Notes (performance/notes.js) ---- */
/* The month select in the frame's top row, in place of the part-of-year control (index.js FEEDLESS). */
.pf-month { display: inline-flex; align-items: center; gap: 6px; font-size: var(--t-xs); color: var(--muted); font-weight: 600; }
.pf-month select { font-size: var(--t-sm); padding: 5px 8px; font-family: inherit; max-width: 100%; }
/* The per-provider table: ten columns — the first is words, the rest figures (.n right-aligns, .pr-num makes them
   tabular). The "All providers" row is the total: bold, a stronger rule above it. A rate cell carries its parts dim. */
.pf-ntable td:first-child { white-space: nowrap; }
.pf-ntable td .chip { margin-left: 4px; vertical-align: 1px; }
.pf-ntable td .pr-dim { font-size: var(--t-xs); white-space: nowrap; }
.pf-ntable tr.pf-nt-all td { font-weight: 600; border-top: 2px solid var(--line-strong); border-bottom: 0; }
@media (min-width: 761px) and (max-width: 1400px) { .pf-ntable th, .pf-ntable td { padding: 6px 6px; font-size: var(--t-xs); } .pf-ntable td .pr-dim { display: block; } }

/* ---- the doctor page's Notes card (notes.js notesCard, doctor.js loadNotes) ----
   The kit's tiles; a tile label here is a sentence ("Office notes locked within 24 hours") and wraps. */
#prNotesCard .pr-tile-l { white-space: normal; line-height: 1.3; }
#prNotesCard .pr-tile-s { overflow-wrap: anywhere; }

/* ---- Settings → Names → People: the leave KIND (settings.js personHtml) ---- */
.ps-leave-form select { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; }
.ps-leave-list li .chip { vertical-align: 1px; }
.ps-leave-hint { margin-top: 4px; font-size: var(--t-xs); line-height: 1.45; }
@media (max-width: 760px) { .ps-leave-form select { flex: 1 1 100%; } }

/* ---- Settings → Bonus rules: the Note-reminders card (settings.js notesCard) ----
   One form: the dry-run switch on its own line (the sentence beside it IS the explanation), the four facts on a
   wrapping line like the People card's fields, the templates as a grid of labelled textareas, the buttons on the
   kit's .ps-form-row. No boxed alert anywhere: a refusal is the card's amber line, the state is the head chip. */
.ps-switch { display: flex; align-items: flex-start; gap: 8px; font-size: var(--t-sm); color: var(--ink); line-height: 1.5; cursor: pointer; }
.ps-switch input { margin-top: 4px; }
.ps-switch b { color: var(--ink); }
.ps-nfields { display: flex; flex-wrap: wrap; gap: var(--s2) var(--s3); align-items: center; margin-top: var(--s3); min-width: 0; font-size: var(--t-sm); color: var(--muted); }
.ps-nfields label { font-weight: 600; color: var(--ink-soft); }
.ps-nfields input { font-size: var(--t-sm); padding: 5px 8px; min-width: 0; max-width: 100%; }
.ps-nfields input[type="date"] { font-variant-numeric: tabular-nums; }
.ps-nfields .ps-nint { display: inline-flex; align-items: center; gap: 6px; }
.ps-nfields .ps-nint input { width: 52px; text-align: right; font-variant-numeric: tabular-nums; }
.ps-nfields input.ps-ncc { flex: 1 1 260px; }
.ps-nfields input[type="email"] { flex: 0 1 260px; }
.ps-tpls { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(360px, 100%), 1fr)); gap: var(--s3); margin-top: var(--s3); }
.ps-tpl { display: grid; gap: 4px; min-width: 0; font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.45; }
.ps-tpl label b { color: var(--ink); }
.ps-tpl textarea {
  display: block; width: 100%; box-sizing: border-box; min-height: 104px; resize: vertical;
  font: inherit; font-size: var(--t-sm); line-height: 1.45; padding: 8px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--ink);
}
.ps-tpl textarea:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }
/* A mail template's subject line: one box above the body, the same border and type as the body so the pair reads as
   one message (settings.js templateHtml, data-shape="mail"). */
.ps-tpl input.ps-tpl-sub {
  display: block; width: 100%; box-sizing: border-box; font: inherit; font-size: var(--t-sm); padding: 6px 10px;
  border: 1px solid var(--line-strong); border-radius: var(--r-sm); background: var(--surface); color: var(--ink); min-width: 0;
}
.ps-tpl input.ps-tpl-sub:focus-visible { outline: 2px solid var(--primary); outline-offset: -1px; }
/* The facts under the four fields (thresholds, days before a leave, the last run): muted sentences, one per line. */
.ps-nline { margin-top: 4px; font-size: var(--t-xs); line-height: 1.5; }
/* The merge-field legend and the missing-contact list: muted lines; the fields and the names are chips. */
.ps-merge { margin-top: var(--s2); font-size: var(--t-xs); color: var(--muted); line-height: 1.6; }
.ps-merge .ps-mf { display: inline-block; margin: 0 10px 2px 0; }
.ps-merge .ps-mf.pr-dim code { color: var(--muted); }
.ps-merge code { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11px; color: var(--ink); background: var(--surface-2); padding: 1px 5px; border-radius: var(--r-sm); }
.ps-contacts { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; margin-top: 6px; }
/* ⚠ .btn-primary is width:100% app-wide (styles.css:188); .ps-form-row already narrows it. The two sample buttons
   sit beside Save on the same row and never wrap mid-label. */
.ps-form-row .btn { white-space: nowrap; }
/* The quoted policy: a document quotation — a hairline on the left in the line token (the one place a rule of
   colour is allowed here, and it is not a colour), the standards table in the app's .viz-table, the clauses
   numbered the way the policy numbers them. Open by default; a fold so the card stays readable on a phone. */
.ps-policy { margin-top: var(--s4); padding-left: var(--s3); border-left: 3px solid var(--line-strong); font-size: var(--t-sm); color: var(--ink-soft); line-height: 1.55; }
.ps-policy > summary { cursor: pointer; font-weight: 600; color: var(--ink); width: fit-content; list-style: none; }
.ps-policy > summary::-webkit-details-marker { display: none; }
.ps-policy > summary::before { content: '+ '; color: var(--muted); }
.ps-policy[open] > summary::before { content: '− '; }
.ps-policy > summary:focus-visible { outline: 2px solid var(--primary); outline-offset: 2px; border-radius: var(--r-sm); }
.ps-policy h4 { margin: var(--s3) 0 4px; font-size: var(--t-sm); color: var(--ink); display: flex; gap: 8px; align-items: baseline; }
.ps-policy h4 .ps-pn { color: var(--muted); font-variant-numeric: tabular-nums; font-weight: 600; min-width: 1.2em; }
.ps-policy .ps-plead { margin: 0 0 6px; color: var(--ink); }
.ps-policy ol.ps-clauses { margin: 0; padding-left: 0; list-style: none; counter-reset: clause; display: grid; gap: 4px; }
.ps-policy ol.ps-clauses > li { position: relative; padding-left: 2.6em; counter-increment: clause; }
.ps-policy ol.ps-clauses > li::before { content: attr(data-sec) "." counter(clause); position: absolute; left: 0; top: 0; color: var(--muted); font-size: var(--t-xs); font-variant-numeric: tabular-nums; }
.ps-policy .ps-ptable { margin: var(--s2) 0; }
.ps-policy .ps-ptable th, .ps-policy .ps-ptable td { text-align: left; white-space: normal; font-variant-numeric: normal; }
.ps-policy .ps-ptable td:first-child { white-space: nowrap; }
.ps-policy .ps-pnote { margin-top: var(--s2); }
@media (max-width: 760px) {
  .ps-nfields label { flex: 1 1 100%; margin-bottom: -4px; }
  .ps-nfields input, .ps-nfields input[type="email"], .ps-nfields input.ps-ncc { flex: 1 1 100%; }
  .ps-nfields .ps-nint { flex: 1 1 100%; }
  .ps-nfields .ps-nint input { flex: 0 0 64px; }
  .ps-form-row .btn { white-space: normal; }
}
