    /* Figures: equal-width digits so money and codes line up in a column.
       Hang this on anything that shows an amount, a code or a count. */
    .num { font-variant-numeric: tabular-nums; text-align: right; }
    * { box-sizing: border-box; }
    body {
      margin: 0; background: var(--surface); color: var(--ink);
      font-family: var(--font-sans);
    }
    h1, h2, h3, .rh-heading { font-family: var(--font-sans); }
    .rh-mono { font-family: var(--font-mono); }
    a { color: var(--ruby); }
    a:hover { color: var(--cherry); }
    button { font-family: var(--font-sans); cursor: pointer; }
    button:disabled { cursor: not-allowed; opacity: 0.5; }
    input, textarea, select { font-family: inherit; }
    /* Motion only explains what happened (a control answering, a tab changing):
       120-240ms, ease-out, never decorative. */
    :where(button, a, .btn, .nav-item, .tab, .rail-item) {
      transition: background-color var(--motion), color var(--motion), border-color var(--motion);
    }
    @media (prefers-reduced-motion: reduce) {
      *, *::before, *::after { animation-duration: 0.01ms !important; animation-iteration-count: 1 !important; transition-duration: 0.01ms !important; scroll-behavior: auto !important; }
    }
    :where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="password"], input[type="date"], input[type="number"], textarea, select) {
      background: var(--field); border: 1px solid var(--border-strong); border-radius: var(--radius-md);
    }

    /* ---- Outer app rail: New Claim / History, always visible ---- */
    #appRoot { display: flex; min-height: 100vh; }
    #appRail {
      width: 72px; flex: none; background: var(--plum); display: flex; flex-direction: column;
      align-items: center; gap: 6px; padding: 18px 0;
      /* Sticky for the same reason #sidebar is: the rail ends in the provider
         chip, and on a page taller than the window a chip anchored to the
         bottom of the document is a chip you have to go looking for. */
      position: sticky; top: 0; height: 100vh;
      /* Sticky makes the rail its own stacking context, so the practice menu's
         z-index only counts inside it: without a layer here, the page's sticky
         headers (z-index 5) painted over the menu where it opens beside the
         rail. 10 sits above those and below the side panel (40), the patient
         picker (100) and the login screen (1000), which should all cover it. */
      z-index: 10;
    }
    .rail-item {
      display: flex; flex-direction: column; align-items: center; gap: 5px; width: 58px; padding: 9px 4px 8px;
      border-radius: var(--radius-md); border: none; background: none; color: rgba(255, 255, 255, 0.65); font-size: var(--text-xs); font-weight: 600;
    }
    .rail-item:hover { background: rgba(255, 255, 255, 0.08); color: var(--cream); }
    .rail-item.active { background: rgba(255, 255, 255, 0.14); color: var(--cream); }
    .rail-item svg { flex: none; }

    /* The provider chip is the account affordance, not a fourth destination in
       the list, so it sits at the far end behind a rule rather than in line
       with New Claim / History / Patients. It lives in the rail rather than the
       sidebar because the sidebar hides itself on every route but New Claim,
       and a profile you can only reach from one screen is not a profile. */
    #railSpacer { flex: 1; }
    #railDivider { width: 40px; height: 1px; flex: none; background: rgba(255, 255, 255, 0.16); margin: 4px 0 10px; }
    .rail-avatar, .rail-workspace-mark {
      width: 28px; height: 28px; border-radius: 50%; flex: none;
      display: flex; align-items: center; justify-content: center;
      background: rgba(255, 255, 255, 0.16); color: var(--cream);
      font-size: var(--text-xs); font-weight: 800;
    }
    .rail-item.active .rail-avatar { background: var(--ruby); }
    /* Square where the avatar is round: the place you are in, beside the
       person you are. Same size and colour, so the rail reads as one family. */
    .rail-workspace-mark { border-radius: var(--radius-sm); }
    /* The library is reference, not a place work happens: an icon in the
       bottom group, like a settings cog, never a fourth primary item. */
    .rail-item.rail-secondary { padding: 7px 4px; }

    /* ---- Auth (sign-in build plan, Stage 4) ---- */
    /* Quiet on purpose: gold is this app's decoration colour, never alarm --
       AUTH_MODE=off is the normal state everywhere today, not a problem. */
    #authOffBanner {
      display: flex; align-items: center; gap: 8px; padding: 7px 20px;
      background: rgba(184, 150, 90, 0.12); border-bottom: 1px solid var(--border-soft);
      color: var(--gold-text); font-size: var(--text-sm); font-weight: 600;
    }
    #authOffBanner svg { flex: none; }
    /* A fixed overlay, not a swap of #appRoot's own display -- the app
       underneath can keep its static skeleton without being touched, and
       nothing here has to coordinate with the flex layout above it. */
    #loginScreen {
      display: none; position: fixed; inset: 0; z-index: 1000;
      align-items: center; justify-content: center; background: var(--plum);
    }
    #loginScreenCard { width: 340px; text-align: center; }
    #loginScreenLogo { display: flex; align-items: center; justify-content: center; gap: 10px; margin-bottom: 20px; }
    #loginScreenMark { width: 40px; height: 40px; flex: none; display: block; }
    #loginScreenLogo .wordmark { font-family: var(--font-wordmark); font-weight: 400; font-size: var(--text-lg); color: var(--ink); }
    #loginScreen .page-title, #loginScreen .page-subtitle { text-align: center; }
    /* Single column and left-aligned labels read better than the 2-up grid
       the Claim form uses -- this card is much narrower than that form. */
    #loginScreen .field-grid { grid-template-columns: 1fr; text-align: left; margin-top: 16px; }
    #loginScreen .btn-primary { width: 100%; padding: 11px 16px; margin-top: 16px; }
    #loginScreenError { margin-top: 12px; margin-bottom: 0; }
    /* A plain-text secondary action within the login card -- "Forgot
       password?", "Back to sign in". Not .rh-link: that's reserved for the
       name of an object you can open (a patient, a case, a claim), and this
       opens a step of this same form, not a record. Underlined like
       .rh-link anyway, for the same colorblind/low-contrast reason -- never
       color alone as the only affordance. */
    .login-text-btn {
      background: none; border: none; padding: 0; margin-top: 14px;
      font-size: var(--text-sm); color: var(--ink-2); text-decoration: underline; cursor: pointer;
    }
    .login-text-btn:hover { color: var(--ink); }
    /* The new-provider welcome (welcome.js): the same full-screen card as the
       login screen, wider because it carries a form rather than two fields,
       and scrollable so a short window cannot hide the save button. */
    #welcomeScreen {
      display: none; position: fixed; inset: 0; z-index: 1000;
      align-items: center; justify-content: center; background: var(--plum);
      padding: var(--space-6); overflow: auto;
    }
    #welcomeScreenCard { width: 560px; max-width: 100%; }
    #welcomeScreenLogo { display: flex; align-items: center; gap: 10px; margin-bottom: var(--space-4); }
    #welcomeScreenMark { width: 40px; height: 40px; flex: none; display: block; }
    #welcomeScreenLogo .wordmark { font-family: var(--font-wordmark); font-weight: 400; font-size: var(--text-lg); color: var(--ink); }
    #welcomeScreen .field-grid { margin-top: var(--space-2); }
    /* A grid column is at least as wide as its content, so a long label or
       placeholder would widen one column and leave this card's three grids
       out of line with each other. */
    #welcomeScreen .field-grid > label { min-width: 0; }
    /* Hung on the container, not on `.field-grid + .section-title`: a sibling
       selector here would stop matching the moment anything is wrapped. */
    #welcomeScreenCard > .section-title { margin-top: var(--space-5); }
    #welcomeStatus { margin-top: var(--space-3); margin-bottom: 0; }

    #loginMfaSetupQr { display: flex; justify-content: center; margin: 14px 0 6px; }
    #loginMfaSetupSecret { font-family: ui-monospace, monospace; font-size: var(--text-xs); word-break: break-all; }
    #loginMfaSetupCode, #loginMfaCode { text-align: center; letter-spacing: 6px; font-size: var(--text-lg); }

    /* Library rule cards: the quote is set off as quotation, with gold as
       decoration only. */
    .rule-quote { margin: 10px 0 6px; padding-left: 10px; border-left: 2px solid var(--gold); color: var(--ink-2); font-size: var(--text-sm); line-height: 1.5; }
    .rule-line { font-size: var(--text-sm); color: var(--ink); line-height: 1.5; margin-top: 6px; }
    /* Marks a rule that is not applied yet: the anomaly is labelled, the card
       otherwise reads like every other. Gold border is decoration; the text is
       --gold-text, which passes AA on the card. */
    .rule-status {
      display: inline-block; font-size: var(--text-xs); font-weight: 700; color: var(--gold-text);
      border: 1px solid var(--gold); border-radius: var(--radius-pill); padding: 1px 8px;
    }
    .library-filter { margin-bottom: 12px; }
    /* The rule side panel sits over the current view rather than replacing
       it, so a provider reading a claim never loses their place. */
    .rule-panel {
      position: fixed; top: 0; right: 0; bottom: 0; width: min(460px, 100vw); z-index: 40;
      background: var(--card); border-left: 1px solid var(--border); box-shadow: -12px 0 32px rgba(0, 0, 0, 0.12);
      overflow-y: auto; padding: 20px 24px 32px;
    }
    .rule-panel[hidden] { display: none; }
    .rule-panel-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 8px; }
    .rule-panel .card { margin-bottom: 14px; }
    .rule-breadcrumb { font-size: var(--text-sm); color: var(--ink-2); margin-bottom: 10px; }
    .rule-related-row { padding: 6px 0; font-size: var(--text-sm); line-height: 1.45; }
    .rule-report textarea { width: 100%; box-sizing: border-box; min-height: 72px; margin-top: 8px; }
    /* A rail item is 58px wide and a provider name is not. The chip buys back
       what it can -- narrower gutters, a smaller label -- and anything still too
       long is trimmed, with the full name and organization on the aria-label. */
    .rail-profile, .rail-workspace { padding-left: 2px; padding-right: 2px; }
    .rail-profile-name, .rail-workspace-name {
      max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
      font-size: var(--text-xs); letter-spacing: -0.01em;
    }

    /* Which practice you are in sits at the top of the rail, under the mark,
       for the same reason the provider chip sits in the rail at all: the
       sidebar hides itself on most routes, and the practice your screen is
       showing is not something to hunt for. A rule under it keeps it apart from
       the four places, since it is not one of them. */
    #railWorkspaceDivider { width: 40px; height: 1px; flex: none; background: rgba(255, 255, 255, 0.16); margin: 2px 0 6px; }

    /* The menu opens beside the rail rather than over it. #appRail is sticky,
       which makes it the containing block, so `top` is set from the button. */
    /* Invitations waiting. Gold is decoration, and this is one: the count is
       in the button's label. Ringed in plum so it reads against the mark. */
    .rail-workspace-mark { position: relative; }
    .rail-workspace-dot {
      position: absolute; top: -3px; right: -3px; width: 9px; height: 9px;
      border-radius: 50%; background: var(--gold); box-shadow: 0 0 0 2px var(--plum);
    }
    /* The practices panel moved to Settings -> Provider (1 Nov 2026), so it is
       ordinary page content now: .section-title and .card give it its chrome,
       and the popover's positioning, fixed width, shadow and own scrolling went
       with it. It only takes focus so an accepted or withdrawn invitation does
       not drop the caret on the body -- never a visible ring. */
    #providerPracticesPanel:focus { outline: none; }
    #workspaceInviteForm { grid-template-columns: 1fr; }
    #workspaceInviteForm .btn { justify-self: start; }
    .workspace-row { padding: var(--space-2); display: flex; flex-direction: column; gap: var(--space-2); }
    .workspace-row-actions { display: flex; gap: var(--space-2); }
    .workspace-row-actions .btn { padding: var(--space-1) var(--space-3); }
    .workspace-item {
      display: flex; align-items: center; gap: var(--space-3); width: 100%;
      padding: var(--space-2); border: none; background: none; border-radius: var(--radius-md);
      font: inherit; text-align: left; color: var(--ink);
    }
    .workspace-item:hover, .workspace-item:focus-visible { background: var(--surface); }
    .workspace-item:disabled { opacity: 0.6; }
    .workspace-item-text { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
    .workspace-item-name {
      font-size: var(--text-base); font-weight: 600;
      overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
    }
    .workspace-item-role { font-size: var(--text-sm); color: var(--ink-2); }
    /* The current one is marked with a check, not a fill: the menu is a list of
       places, and nothing here is the page's main action. */
    .workspace-item-check { width: 16px; flex: none; color: var(--plum); visibility: hidden; }
    .workspace-item[aria-current="true"] .workspace-item-check { visibility: visible; }

    .route { display: none; flex: 1; min-width: 0; }
    .route.active { display: flex; }
    [hidden] { display: none !important; }

    /* ---- History route ---- */
    #historyView.route.active, #patientsView.route.active, #recordView.route.active, #providerView.route.active, #libraryView.route.active, #billingView.route.active { display: block; }
    #historyView, #patientsView, #recordView, #providerView, #libraryView { flex: 1; min-width: 0; padding: 32px 44px; max-width: 900px; }
    #billingView { flex: 1; min-width: 0; padding: 32px 44px; max-width: 1000px; }
    /* Routes that browse a record rather than work a queue have no nav of
       their own, so the sidebar steps out of the way rather than standing
       there empty. */
    #sidebar[hidden] { display: none; }

    .bucket-count {
      font-size: var(--text-xs); font-weight: 700;
      border-radius: var(--radius-pill); padding: 1px 6px;
      background: var(--border-soft); color: var(--ink-2);
    }

    .history-breadcrumb { font-size: var(--text-sm); color: var(--ink-2); margin-bottom: 16px; }
    .history-breadcrumb a { cursor: pointer; }
    .history-row-link { background: none; border: none; padding: 0; margin: 0; width: 100%; text-align: left; }
    .history-row-link:hover .activity-row { background: var(--surface); }

    /* ---- History encounter view (read mode) ---- */
    /* Tabs are quiet: ruby is the page's one main button, not its navigation.
       The active tab is plum with a ruby underline. */
    .tabs { display: flex; gap: 2px; margin: 18px 0 20px; border-bottom: 1px solid var(--border-soft); overflow-x: auto; }
    .tab {
      font-family: var(--font-sans); font-weight: 600; font-size: var(--text-base); padding: 10px 16px 11px; white-space: nowrap;
      border: none; border-bottom: 3px solid transparent; border-radius: 0; background: none; color: var(--ink-2);
    }
    .tab:hover { background: var(--border-soft); }
    /* Browse by category is how most people find a code, so it is set larger
       than the lists around it: bigger heading, tabs and rows. */
    /* Home's visit list: a step larger than the Claims page, in espresso. */
    [data-slot="codeBrowse"] { margin-top: 4px; }
    [data-slot="codeBrowse"] .tab { font-size: var(--text-md); padding: 12px 20px 13px; }
    [data-slot="codeBrowse"] .activity-row { padding: 18px 20px; gap: 16px; }
    [data-slot="codeBrowse"] .activity-icon { width: 44px; height: 44px; font-size: var(--text-lg); }
    [data-slot="codeBrowse"] .activity-title { font-size: var(--text-lg); }
    [data-slot="codeBrowse"] .activity-sub { font-size: var(--text-base); }
    #libraryView .section-title:has(+ [data-slot="codeBrowse"]) { font-size: var(--text-md); margin-top: 28px; }
    .tab.active, .tab.active:hover { background: none; color: var(--plum); border-bottom-color: var(--ruby); }
    .ro-kv { display: grid; grid-template-columns: 140px 1fr; gap: 6px 14px; font-size: var(--text-sm); margin: 0 0 6px; }
    .ro-kv dt { color: var(--ink-2); font-weight: 600; }
    .ro-kv dd { margin: 0; }
    .ro-list { margin: 6px 0 14px; padding-left: 20px; font-size: var(--text-sm); line-height: 1.6; }
    .table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); margin-bottom: 16px; }
    .table th, .table td { text-align: left; padding: 7px 10px; border-bottom: 1px solid var(--border-soft); }
    .table th { color: var(--ink-2); font-weight: 600; font-size: var(--text-xs); text-transform: uppercase; letter-spacing: 0.03em; }
    .ro-warning {
      background: rgba(207, 66, 74, 0.1); border: 1px solid rgba(207, 66, 74, 0.3); border-radius: var(--radius-md);
      padding: 10px 12px; font-size: var(--text-sm); color: var(--garnet); margin-bottom: 8px;
    }
    .ro-transcript { white-space: pre-wrap; font-size: var(--text-base); line-height: 1.65; }
    .ro-revisions-toggle {
      margin-top: 20px; background: none; border: none; padding: 0; font-size: var(--text-sm); font-weight: 600;
      color: var(--ink-2); cursor: pointer; display: inline-flex; align-items: center; gap: 4px;
    }
    .ro-revisions-toggle:hover { color: var(--ruby); }
    .ro-revisions-toggle::before { content: "\203A"; display: inline-block; transition: transform var(--motion-fast); }
    .ro-revisions-toggle.open::before { transform: rotate(90deg); }
    .ro-revisions-list { margin-top: 8px; border-left: 2px solid var(--border-soft); padding-left: 12px; display: flex; flex-direction: column; gap: 4px; }
    .ro-revision-row { background: none; border: none; padding: 3px 0; margin: 0; text-align: left; font-size: var(--text-sm); color: var(--ink-2); cursor: pointer; }
    .ro-revision-row:hover { color: var(--ink); }
    .ro-revision-row.selected { color: var(--ruby); font-weight: 600; }
    .ro-version-banner {
      font-size: var(--text-xs); color: var(--gold-text); background: rgba(184, 150, 90, 0.14); border-radius: var(--radius-sm);
      padding: 6px 10px; margin-bottom: 12px; display: inline-block;
    }

    /* ---- Payer response (the denial loop) ---- */
    .payer-money { display: flex; flex-wrap: wrap; gap: 22px; margin: 4px 0 16px; }
    .payer-money div { display: flex; flex-direction: column; gap: 2px; }
    .payer-money .label { font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: var(--ink-2); }
    .payer-money .value { font-size: var(--text-md); font-weight: 700; font-family: var(--font-mono); }
    .payer-money .value.at-risk { color: var(--garnet); }
    .payer-route {
      display: inline-block; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
      padding: 5px 11px; border-radius: var(--radius-pill); margin-bottom: 14px;
      background: rgba(219, 42, 51, 0.1); color: var(--garnet);
    }
    .payer-route.calm { background: rgba(184, 150, 90, 0.18); color: var(--plum); }
    .payer-finding { padding: 12px 14px; border: 1px solid var(--border-soft); border-radius: var(--radius-md); margin-bottom: 8px; }
    .payer-finding .head { display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; margin-bottom: 4px; }
    .payer-finding .code { font-family: var(--font-mono); font-weight: 600; font-size: var(--text-sm); color: var(--plum); }
    .payer-finding .amount { margin-left: auto; font-family: var(--font-mono); font-size: var(--text-sm); font-weight: 600; }
    .payer-finding .desc { font-size: var(--text-sm); margin-bottom: 6px; }
    .payer-finding .why { font-size: var(--text-sm); color: var(--ink-2); line-height: 1.55; }
    .payer-finding.unknown { border-style: dashed; }
    /* Set apart from the payer-response text it follows inside a claim card. */
    [data-payment-history] { margin-top: 16px; }
    .payer-deadline { font-size: var(--text-sm); color: var(--ink-2); margin-top: 12px; }
    .payer-deadline .urgent { color: var(--garnet); font-weight: 600; }
    .appeal-letter {
      white-space: pre-wrap; font-size: var(--text-sm); line-height: 1.65; background: var(--surface);
      border: 1px solid var(--border-soft); border-radius: var(--radius-md); padding: 14px 16px; margin: 10px 0;
    }
    .appeal-warning {
      background: rgba(207, 66, 74, 0.1); border: 1px solid rgba(207, 66, 74, 0.35); border-radius: var(--radius-md);
      padding: 10px 12px; font-size: var(--text-sm); color: var(--garnet); margin: 10px 0;
    }
    /* Submitting is irreversible; it gets its own space rather than sitting
       flush against the letter you were reading. */
    .submit-actions { margin-top: 18px; padding-top: 16px; border-top: 1px solid var(--border-soft); }
    .submit-actions .stedi-note { font-size: var(--text-sm); color: var(--ink-2); margin-bottom: 10px; }
    .amend-row {
      display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
      padding: 8px 0; border-bottom: 1px solid var(--border-soft);
    }
    .amend-code { font-family: var(--font-mono); font-weight: 600; font-size: var(--text-sm); color: var(--plum); flex: none; }
    .amend-desc { font-size: var(--text-sm); color: var(--ink-2); flex: 1; min-width: 120px; }
    .amend-row select, .amend-row input {
      font: inherit; font-size: var(--text-sm); padding: 5px 8px; border-radius: var(--radius-sm);
      border: 1px solid var(--border); background: var(--card); color: var(--ink);
    }
    .amend-row input { min-width: 110px; }
    /* The whole context field is the drop target, so a dragged file does not
       have to be aimed at a small button. */
    .drop-active { outline: 2px dashed var(--ruby); outline-offset: 3px; border-radius: var(--radius-md); }

    .record-locked {
      font-size: var(--text-sm); color: var(--ink-2); background: var(--card);
      border: 1px solid var(--border-soft); border-radius: var(--radius-md);
      padding: 10px 12px; margin-bottom: 12px;
    }
    .ro-transcript-edit {
      width: 100%; min-height: 160px; font: inherit; font-size: var(--text-base); line-height: 1.65;
      border: none; background: none; color: var(--ink); resize: none; padding: 0;
    }
    .ro-transcript-edit:focus:not(:focus-visible) { outline: none; }
    .appeal-quote { display: flex; gap: 8px; align-items: flex-start; font-size: var(--text-sm); margin-bottom: 6px; line-height: 1.5; }
    .appeal-quote .verdict {
      flex: none; font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
      padding: 2px 7px; border-radius: var(--radius-pill); margin-top: 1px;
    }
    .appeal-quote .verdict.verified { background: rgba(78, 122, 69, 0.14); color: var(--success); }
    .appeal-quote .verdict.paraphrased { background: rgba(184, 150, 90, 0.2); color: var(--plum); }
    .appeal-quote .verdict.unsupported { background: rgba(107, 15, 30, 0.12); color: var(--garnet); }
    #remittanceInput {
      width: 100%; min-height: 120px; font-family: var(--font-mono); font-size: var(--text-xs);
      line-height: 1.5; padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius-md);
      background: var(--field); color: var(--ink); resize: vertical;
    }
    .activity-row {
      display: flex; align-items: center; gap: 14px; padding: 14px 16px;
    }
    /* Hairlines between stacked rows, hung on the container rather than
       between the rows themselves. A row is often wrapped in a link to make
       the whole row clickable, and `.activity-row + .activity-row` silently
       stops matching the moment it is -- which is why these lists had no
       separators at all. The container does not care what its children are. */
    .card-rows > * + *, .row-list > * + * { border-top: 1px solid var(--border-soft); }
    .activity-icon {
      width: 30px; height: 30px; border-radius: var(--radius-md); flex: none; display: flex; align-items: center;
      justify-content: center; color: var(--plum); background: rgba(255, 184, 200, 0.32);
    }
    .activity-row.claim .activity-icon { color: var(--garnet); background: rgba(184, 150, 90, 0.2); }
    .activity-main { flex: 1; min-width: 0; }
    .activity-title { font-weight: 600; font-size: var(--text-base); }
    /* Who wrote a line of text near a CPT code (AMA licence rule b). A tag
       beside CMS or AMA words; Ruby's own notes also get a left rule. */
    .src-tag { display: inline-block; white-space: nowrap; flex: none; margin-right: 6px; padding: 0 6px; border: 1px solid var(--border); border-radius: var(--radius-sm); font-size: var(--text-xs); font-weight: 600; letter-spacing: .02em; color: var(--ink-2); vertical-align: 1px; }
    .src-tag a { color: inherit; }
    .cpt-notice { margin-top: 16px; font-size: var(--text-xs); color: var(--ink-3); }
    .cpt-notice:empty { display: none; }
    .how-this-works { display: inline; font-size: var(--text-xs); color: var(--ink-3); }
    .how-this-works summary { display: inline; cursor: pointer; text-decoration: underline; }
    .how-this-works[open] summary { display: block; margin-bottom: 4px; }
    .how-this-works p { margin: 0; max-width: 60ch; line-height: 1.5; }
    .src-ruby { border-left: 3px solid var(--border); padding-left: 8px; font-style: italic; }
    .activity-sub { font-size: var(--text-sm); color: var(--ink-2); margin-top: 2px; }
    .activity-meta { display: flex; align-items: center; gap: 10px; flex: none; }
    .activity-date { font-size: var(--text-xs); color: var(--ink-3); white-space: nowrap; }
    .activity-pill {
      font-size: var(--text-xs); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em;
      border-radius: var(--radius-pill); padding: 3px 9px; white-space: nowrap; color: var(--ink-2); background: var(--surface);
      border: 1px solid var(--border-soft);
    }
    .activity-pill.submitted, .activity-pill.reviewed, .activity-pill.accepted { color: var(--success); background: rgba(78, 122, 69, 0.12); border-color: transparent; }
    .activity-pill.denied { color: var(--garnet); background: rgba(107, 15, 30, 0.1); border-color: transparent; }
    .activity-pill.draft { color: var(--ink-2); background: var(--surface); }
    /* A visit's status (visitStatusPill). The words carry it; colour only backs
       them up. Loud for the two that wait on the provider, quiet otherwise. */
    .activity-pill.visit-ready, .activity-pill.visit-paid { color: var(--success); background: rgba(78, 122, 69, 0.12); border-color: transparent; }
    .activity-pill.visit-needs_review { color: var(--garnet); border-color: var(--garnet); background: var(--surface); }
    .activity-pill.visit-needs_info { color: var(--garnet); background: rgba(107, 15, 30, 0.1); border-color: transparent; }
    .activity-pill.visit-held { color: var(--warn); border-color: transparent; background: var(--warn-bg); }
    /* Archived: gold like visit-held, quiet rather than a warning -- it is a
       filed-away state, not a problem. */
    .activity-pill.archived { color: var(--gold-text); border-color: var(--gold); background: var(--surface); }
    /* The status block sits directly above the record's tab strip, which has
       no section title of its own to space it -- so the block carries the gap. */
    [data-visit-status-block] { margin-bottom: 18px; }
    /* Claim tracker (visitTracker): five steps, filled in from the visit's
       status. Shape carries the state -- filled done, ring for where it is,
       a cross for a payer problem, bars for held -- so it reads without colour. */
    .visit-tracker-icon { flex: none; display: block; }
    /* Pills differ in length, so the icon before them would wander from row
       to row. A fixed slot for the pill keeps every tracker in one column. */
    .visit-pill-slot { display: inline-flex; min-width: 236px; }
    @media (max-width: 640px) { .visit-pill-slot { min-width: 0; } }
    .visit-tracker {
      list-style: none; margin: 0 0 12px; padding: 0;
      display: grid; grid-template-columns: repeat(5, minmax(0, 1fr));
    }
    .visit-tracker > li { position: relative; text-align: center; padding-top: 0; min-width: 0; }
    /* The line into each step hangs off the step itself, not a sibling
       selector -- see "Be wary of adjacent-sibling selectors" in CLAUDE.md. */
    .visit-tracker > li::before {
      content: ""; position: absolute; top: 8px; right: 50%; width: 100%; height: 2px;
      background: var(--border); z-index: 0;
    }
    .visit-tracker > li:first-child::before { display: none; }
    .visit-tracker > li.reached::before { background: var(--plum); }
    .visit-tracker .node { position: relative; z-index: 1; display: block; margin: 0 auto; background: var(--surface); border-radius: 50%; }
    .visit-tracker .step-label { display: block; margin-top: 6px; font-size: var(--text-xs); font-weight: 600; color: var(--ink-3); overflow-wrap: anywhere; }
    .visit-tracker li.done .step-label { color: var(--ink-2); }
    .visit-tracker li[aria-current] .step-label { color: var(--ink); }
    .visit-tracker .step-status { display: block; margin-top: 2px; font-size: var(--text-xs); font-weight: 700; color: var(--plum); }
    .visit-tracker li.problem .step-status { color: var(--garnet); }
    .visit-tracker li.held .step-status { color: var(--gold-text); }
    .visit-tracker-detail { font-size: var(--text-sm); color: var(--ink-2); margin: -4px 0 4px; }
    .sr-only { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
    .visit-status-actions { display: flex; gap: 8px; flex-wrap: wrap; margin-top: 10px; }
    .visit-hold-form { margin-top: 10px; display: flex; flex-direction: column; gap: 8px; max-width: 520px; }
    .visit-hold-form textarea { min-height: 60px; }
    .visit-hold-form label { font-size: var(--text-sm); font-weight: 600; color: var(--ink-2); }

    /* ---- Sidebar ---- */
    #sidebar {
      width: 240px; flex: none; background: var(--card); border-right: 1px solid var(--border);
      display: flex; flex-direction: column; padding: 24px 16px; position: sticky; top: 0; height: 100vh;
    }
    #logoRow { display: flex; align-items: center; gap: 10px; padding: 0 8px 22px; }
    #logoMark { width: 34px; height: 34px; flex: none; display: block; }
    #logoRow .wordmark { font-family: var(--font-wordmark); font-weight: 400; font-size: var(--text-lg); }

    #navList { display: flex; flex-direction: column; gap: 2px; }
    .nav-group { display: flex; flex-direction: column; gap: 2px; }
    /* A bucket's count is the reason to look at the sidebar at all, so it sits
       at the end of the row where the pipeline nav puts its dot. */
    .nav-item .bucket-count { margin-left: auto; }
    .nav-item.active .bucket-count { background: rgba(92, 26, 50, 0.12); color: var(--plum); }
    .nav-item {
      display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: var(--radius-md);
      color: var(--ink-2); border: none; background: none; text-align: left; width: 100%; font-size: var(--text-base); font-weight: 600;
    }
    .nav-item:hover { background: var(--border-soft); }
    .nav-item.active, .nav-item.active:hover { background: rgba(92, 26, 50, 0.1); color: var(--plum); font-weight: 700; }
    .nav-item svg { flex: none; }
    .nav-item .nav-label { flex: 1; }
    .nav-item .nav-dot { width: 6px; height: 6px; border-radius: 50%; flex: none; border: 1.3px solid currentColor; background: transparent; }
    .nav-item.has-data .nav-dot { background: var(--gold); border-color: var(--gold); }
    .nav-item.active.has-data .nav-dot { background: var(--plum); border-color: var(--plum); }


    /* ---- Intake screen: patient + case selection, shown before the claim flow ---- */
    #intakeModal {
      display: none; position: fixed; inset: 0; background: rgba(37, 28, 27, 0.45);
      align-items: flex-start; justify-content: center; padding: 60px 20px; z-index: 100;
    }
    #intakeModal.open { display: flex; }
    #intakeScreen {
      background: var(--card); border-radius: var(--radius-xl); box-shadow: var(--shadow-card); padding: 28px 32px;
      width: 100%; max-width: 480px; max-height: 80vh; overflow-y: auto; position: relative;
    }
    /* Asked as a question the visit cannot start without, the picker is the
       page rather than a popup over it: the visit behind it has nothing to
       show yet. "Change patient" mid-visit stays a popup. */
    #appShell.choosing #main { display: none; }
    #intakeModal.page { position: static; inset: auto; background: none; padding: 0; z-index: auto; flex: 1; min-width: 0; }
    #intakeModal.page.open { display: block; }
    #intakeModal.page #patientSearchInput { width: 100%; box-sizing: border-box; padding: 10px 12px; border: 1px solid var(--border); border-radius: var(--radius-md); font: inherit; background: #fff; }
    #intakeModal.page #intakeScreen { max-width: 760px; max-height: none; overflow: visible; box-shadow: none; background: none; border-radius: 0; padding: 32px 44px; }
    #closeIntakeBtn {
      position: absolute; top: 18px; right: 18px; border: none; background: none; color: var(--ink-2);
      font-size: var(--text-lg); line-height: 1; cursor: pointer; padding: 4px;
    }

    /* ---- Patient/case indicator: always visible, opens the picker on demand ---- */
    #patientCaseBar {
      display: flex; align-items: center; justify-content: space-between; gap: 12px;
      padding: 10px 16px; margin-bottom: 22px; border-radius: var(--radius-md); background: var(--card); border: 1px solid var(--border);
    }
    #patientCaseLabel { font-size: var(--text-sm); font-weight: 600; color: var(--ink-2); }
    #patientCaseLabel.assigned { color: var(--ink); }

    .intake-section { margin-bottom: 24px; }
    .intake-list { display: flex; flex-direction: column; gap: 6px; margin-bottom: 10px; }
    .intake-option {
      display: flex; flex-direction: column; align-items: flex-start; gap: 2px; padding: 10px 14px; border-radius: var(--radius-md);
      border: 1px solid var(--border); background: var(--card); text-align: left; font-size: var(--text-sm);
    }
    .intake-option:hover { background: var(--border-soft); }
    .intake-option.selected { border-color: var(--ruby); background: rgba(219, 42, 51, 0.06); }
    .intake-option .intake-option-title { font-weight: 700; color: var(--ink); }
    .intake-option .intake-option-meta { color: var(--ink-2); font-size: var(--text-xs); }
    .intake-form { display: flex; flex-direction: column; gap: 8px; margin-top: 8px; }
    .intake-form input, .intake-form select {
      font: inherit; padding: 9px 12px; border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--card); color: var(--ink);
    }
    .intake-form label { display: flex; flex-direction: column; gap: 4px; font-size: var(--text-xs); font-weight: 600; color: var(--ink-2); }
    #startClaimBtn { align-self: flex-start; margin-top: 8px; }

    .patients-toolbar { display: flex; gap: 8px; align-items: center; margin-bottom: 12px; }
    .patients-toolbar .row-input { flex: 1; margin-bottom: 0; }
    .patients-toolbar .btn { flex: none; }
    .show-archived-toggle {
      display: flex; align-items: center; gap: 5px; flex: none;
      font-size: var(--text-sm); color: var(--ink-2); white-space: nowrap;
    }
    .show-archived-toggle input { margin: 0; }
    /* Standing on its own under the lists rather than inline in the toolbar. */
    .show-archived-footer { margin-top: var(--space-4); }
    /* Archive/unarchive: reversible, so no destructive two-step confirm like
       Delete -- one quiet button, not set apart in .submit-actions. */
    .archive-action { margin-top: 10px; }
    .archive-action .status { margin-top: 4px; }
    /* Send to extension keeps Archive's shape on purpose: both are reversible
       and both sit outside .submit-actions, where Submit and Delete live. */
    .extension-actions { margin-top: 10px; }
    .extension-actions .status { margin-top: 4px; }
    #addPatientForm { margin-bottom: 12px; }
    /* An underpayment flag: one line, then Appeal and Dismiss (RCM UI polish,
       1 Nov 2026). Gold on its tint rather than the red of .status.error --
       a shortfall is a second look, not a failure. The pair is already in
       brandContrast.test.js ("warning on its tint"). */
    .underpaid-flag {
      margin-top: var(--space-2); padding: var(--space-2) var(--space-3);
      border-radius: var(--radius-md); background: var(--warn-bg); color: var(--warn);
    }
    .underpaid-flag-line { font-size: var(--text-sm); }
    /* The dismiss control is a wrapper holding its button and a hidden form;
       display:contents lets the button join this row and the form drop onto
       its own line when opened, without a second layout rule. */
    .underpaid-flag-actions { display: flex; flex-wrap: wrap; gap: var(--space-2); align-items: center; margin-top: var(--space-2); }
    .underpaid-flag-actions > [data-dismiss-controls] { display: contents; }
    .underpaid-flag-actions .row-input { margin-bottom: 0; }
    /* The dismiss form sits inside the flag now, so it takes the flag's size
       rather than the page's -- a 16px question above a 14px flag read as the
       more important of the two. */
    .underpaid-flag-actions label { font-size: var(--text-sm); }

    .duplicate-warning { margin-top: var(--space-4); padding: 14px var(--space-4); border-radius: var(--radius-lg); background: var(--warn-bg); }
    .duplicate-warning h3 { margin: 0 0 2px; font-size: var(--text-md); font-weight: 700; }
    .duplicate-warning p { margin: 0 0 var(--space-2); font-size: var(--text-sm); }
    .duplicate-match { display: block; width: 100%; text-align: left; margin-top: var(--space-2); padding: 10px var(--space-3); border-radius: var(--radius-md); background: var(--card); border: 1px solid var(--border-soft); font: inherit; cursor: pointer; }
    .duplicate-match .what { display: block; font-size: var(--text-sm); }
    .form-actions { display: flex; gap: 8px; margin-top: 14px; }
    /* Insurance inside a New patient form. Hung on the container so it keeps
       its gap whatever sits above it. */
    .insurance-fields { margin-top: 14px; }
    /* .field-grid label sets display, which beats the UA's [hidden]. */
    .insurance-fields [hidden] { display: none; }
    .insurance-fields .field-hint, .address-fields .field-hint { font-size: var(--text-xs); color: var(--ink-2); margin: 2px 0 6px; }
    /* What a payer said about a card. The pills reuse the visit pills' own
       colour pairs rather than introducing any -- the words carry the answer,
       and this is never the loudest thing on its screen. */
    .elig-answer { margin-top: var(--space-3); display: flex; flex-direction: column; align-items: flex-start; gap: var(--space-2); }
    .elig-answer .elig-detail { font-size: var(--text-sm); color: var(--ink-2); }
    .activity-pill.elig-active { color: var(--success); background: rgba(78, 122, 69, 0.12); border-color: transparent; }
    .activity-pill.elig-inactive, .activity-pill.elig-not_found { color: var(--warn); border-color: transparent; background: var(--warn-bg); }
    .activity-pill.elig-unknown { color: var(--ink-2); background: var(--surface); }
    /* Every answer Ruby can get today is a test answer, so every answer says
       so -- in the result itself, never a tooltip, and for as long as the
       answer is on screen. An "Active coverage" someone believes is worse
       than no check at all. */
    .elig-mock { font-size: var(--text-xs); color: var(--warn); background: var(--warn-bg); padding: var(--space-1) var(--space-2); border-radius: var(--radius-sm); }
    .insurance-fields details { margin-top: 10px; }
    .insurance-fields summary, .insurance-history summary, .rule-context summary, .payer-ids summary { cursor: pointer; font-size: var(--text-sm); font-weight: 600; color: var(--ink-2); }
    .rule-context { margin-top: 8px; }
    .insurance-history > .card { margin-top: 10px; }


