/* Pre-Blazor styling so the loading screen matches the themed app canvas. */
html, body {
    background-color: #F6F9F6;
    font-family: "Montserrat", "Helvetica Neue", Helvetica, Arial, sans-serif;
}

/* re: #758 (from the #752 keyboard pass) -- WCAG 2.4.7 Focus Visible and 2.4.11 Focus Not Obscured.

   MudBlazor.min.css removes the focus outline (a:focus-visible{outline:none}, button:focus
   {outline:none}) and marks focus with a 6% hover tint, about 1.09:1 on white. This puts a ring
   back, for KEYBOARD focus only: :focus-visible does not match after a mouse click on a button or
   link, so pointer users see no change.

   Why ":root :focus-visible": MudBlazor's rules are (0,1,1) and .mud-icon-root:focus is (0,2,0).
   ":root :focus-visible" is (0,2,0) and this file loads after MudBlazor.min.css (index.html), so it
   wins by specificity plus order, without !important.

   The colour is the theme primary, read from MudBlazor's palette variable rather than a hex, so it
   follows #748's darkened green. It sits 2px off the control, so it is drawn on the surface around
   it (white or the page grey), never on a green fill. Two places need more than that:
   - the app bar IS green, so there the ring takes the app bar's text colour (white);
   - a filled button can sit on a coloured surface (an alert, a card tint), so it gets a white
     halo filling the 2px gap: the ring then always has white beside it, and the halo has the
     button's own white-text contrast against the fill.

   Text inputs are left out: MudBlazor already draws their focus as a primary underline (which the
   pass found passes), and a text input matches :focus-visible on a mouse click too. */
:root {
    --hebron-focus-ring: var(--mud-palette-primary);
    /* The app bar is fixed, so a control scrolled into view on focus must stop below it, not under it. */
    scroll-padding-top: calc(var(--mud-appbar-height, 64px) + 8px);
}

.mud-appbar {
    --hebron-focus-ring: var(--mud-palette-appbar-text);
}

:root :focus-visible:not(.mud-input-slot) {
    outline: 2px solid var(--hebron-focus-ring);
    outline-offset: 2px;
}

/* Checkboxes, switches and radios keep their real <input> at opacity 0 inside the icon button, so
   a ring on the input would be invisible: draw it on the visible button instead. */
:root .mud-button-root:has(> input:focus-visible) {
    outline: 2px solid var(--hebron-focus-ring);
    outline-offset: 2px;
}

:root .mud-button-filled:focus-visible {
    box-shadow: 0 0 0 2px #FFFFFF;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #3e9c58;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    /* re: #1120: ABOVE every MudBlazor layer, the nav drawer first. At 1000 it sat under the drawer
       (1100), so from 960px up the pinned drawer covered the strip's left end -- exactly where its
       sentence starts -- and a case manager on 30 Sep could see that a bar was there but not read it.
       Above the dialog, snackbar and tooltip layers too (MudBlazor's defaults, 1400-1600; HebronTheme
       sets none): once this strip shows, the app has stopped, and nothing it draws is worth more than
       the sentence saying so. ClientErrorReportingTests pins it above every layer of HebronTheme.Instance. */
    z-index: 2000;
}

    #blazor-error-ui .reload {
        font-weight: 600;
        margin: 0 0.25rem;
    }

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto 0 auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #dce7df;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #3e9c58;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #2f7d45;
}

/* App-bar unread-notification pill (AppShell.razor -> MudBadge BadgeClass).
   MudBadge anchors the pill to the bounding box of the element it wraps -- here a
   MudIconButton whose padding makes that box 48x48 around a 24x24 bell glyph. Stock
   MudBlazor lands the pill at `left: calc(100% - 12px); top: -8px`, i.e. ~12px up and
   right of the glyph and flush with the app bar's top edge, so it reads as a floating
   orphan rather than a badge (Overlap="true" pulls toward the box corner, not the glyph).
   translate() re-centres it on the glyph's top-right corner. The X offset is -50% of the
   pill's own width rather than a fixed -10px so that wider contents ("12", "99+") stay
   centred on that corner instead of growing rightward into the account menu -- for the
   common single-digit pill the two are identical (half of 20px). */
.app-bar-notification-badge {
    transform: translate(-50%, 10px);
    /* The pill is decorative (role="status" aria-live="polite") and sits on top of the
       icon button, so without this it punches a hole in the bell's 48px touch target. */
    pointer-events: none;
}

/* #235: the pill for "we could not read the unread count". MudBadge colours it warning rather than
   error, and this makes the marker read as a marker -- heavier than a digit, and ringed so it stays
   legible against the app bar's primary ground. A failed count must never render as a number, and
   must never render as nothing at all: "nothing unread" is the plausible normal state it used to
   impersonate. */
.app-bar-notification-unavailable {
    font-weight: 700;
    box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.35);
}

/* #489: who is signed in, and under which role (SignedInIdentityDisplay.razor). On-site testers keep
   one window per shared role login, and this is how they tell the windows apart.

   The dark wash is for contrast, not decoration. White on the app bar's #3E9C58 is 3.44:1, below the
   4.5:1 that WCAG AA asks of text this small; over a 25% black wash it is 5.62:1. There is no hover or
   pointer style, because it is not a control.

   min-width: 0 is what lets the ellipsis happen. A flex item will not shrink below its content
   without it, and on a phone the name would push the bell and account menu off the screen instead. */
/* #961: the signed-in person's own picture (or initials), which opens My profile. */
.app-bar-avatar {
    display: inline-flex;
    flex: 0 0 auto;
    margin-left: 8px;
    border-radius: 50%;
    color: inherit;
}

.app-bar-avatar:focus-visible {
    outline: 2px solid currentColor;
    outline-offset: 2px;
}

.app-bar-identity {
    display: flex;
    flex-direction: column;
    justify-content: center;
    flex: 0 1 auto;
    min-width: 0;
    max-width: 280px;
    margin: 0 8px;
    padding: 2px 10px;
    border-radius: 6px;
    background-color: rgba(0, 0, 0, 0.25);
    line-height: 1.25;
    text-align: right;
}

.app-bar-identity-name,
.app-bar-identity-role {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.app-bar-identity-name {
    font-size: 0.875rem;
    font-weight: 600;
}

.app-bar-identity-role {
    font-size: 0.75rem;
}

/* The compact logo for phone width (AppShell.razor swaps it in below the sm breakpoint).
   hebron-mark.png is the green glyph; this knocks it out white, the way hebron-logo-white.png is
   the white knockout of the wordmark. */
.app-bar-logo-mark {
    width: auto;
    filter: brightness(0) invert(1);
}

@media (max-width: 599.98px) {
    .app-bar-identity {
        max-width: none;
        margin: 0 4px;
        padding: 2px 8px;
    }

    .app-bar-identity-name {
        font-size: 0.8125rem;
    }

    .app-bar-identity-role {
        font-size: 0.6875rem;
    }
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* #192: the required asterisk for a required CHECKBOX. MudBlazor puts `mud-input-required` on the
   wrapper for every input type, but its own rule hangs the asterisk off
   `.mud-input-required > .mud-input-control-input-container > .mud-input-label::after`, and the
   boolean variant has no `.mud-input-label` -- it renders its caption as a `.mud-typography` span
   inside the `.mud-checkbox` label. Without this, an acknowledgement a form will refuse to submit
   without looks exactly like an optional one. */
.mud-input-control.mud-input-required.mud-input-control-boolean-input .mud-checkbox > .mud-typography::after {
    content: "*";
}

/* #203: the signature LINE (InlineSignatureField).

   What this replaces is an outlined MudPaper card with pa-4 padding, a pen icon, a subtitle1 heading,
   a role chip, a caption sentence and a filled button -- roughly 120-140px collapsed, once per
   signature field, on forms that carry up to three of them. "this is really bulky and big. We're
   going to kind of make these look like real signature boxes" (Nate, PSH workflow demo paragraph 227).

   Two rows: the rule, which is the thing one signs on and where the action sits, and the caption
   naming whose signature it is. A ruled line is also what tells a signature apart from the boxed date
   field beneath it, which is the confusion #203 exists to remove -- so the border here is deliberately
   NOT the input border: heavier, full width, and with no box closing round it. */
/* No margin of its own: both hosts are DynamicFormRenderer's per-field `<div class="mb-3">`, which is
   where every other field on the form gets its spacing from. The card used to carry `mb-3` itself, so
   a signature sat further from its neighbour than any other field did. */
.signature-line {
    display: block;
}

.signature-line__rule {
    display: flex;
    align-items: flex-end;
    gap: 0.5rem;
    min-height: 2.5rem;
    padding-bottom: 0.25rem;
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

.signature-line__rule--signed {
    align-items: center;
    border-bottom-color: var(--mud-palette-success);
}

.signature-line__caption {
    display: flex;
    flex-wrap: wrap;
    align-items: baseline;
    gap: 0.125rem 0.75rem;
    padding-top: 0.25rem;
}

.signature-line__label {
    font-weight: 500;
}

/* The capture surface replaces the rule while it is open, so it keeps the same left edge rather than
   indenting the canvas away from the line it belongs to. */
.signature-line__capture {
    padding-bottom: 0.25rem;
    border-bottom: 2px solid var(--mud-palette-lines-default);
}

/* #217: how much room the workflow position bar takes at the foot of the viewport. Zero unless the
   bar is actually on screen, so nothing that reads it moves when there is no workflow.

   It is declared HERE, globally, because two owners need the same number: the bar itself
   (Components/Workflows/WorkflowPositionBar.razor.css) and the form-filling page's pinned Save Draft
   / Submit row (Pages/Forms/InstanceDetail.razor.css), which must not end up underneath it. A custom
   property is the only thing that crosses from the shell into a scoped page stylesheet, and one
   number in one place is what stops those two drifting apart.

   The :has() is what makes it self-maintaining: the reservation exists exactly while the bar does,
   with nothing to remember to turn off. */
:root {
    --hebron-workflow-bar-height: 0px;
}

body:has(.workflow-position-bar) {
    --hebron-workflow-bar-height: 52px;

    /* And nothing at the foot of a page ends up behind the bar. */
    padding-bottom: var(--hebron-workflow-bar-height);
}

/* #221: the client list on a tablet.
   ---------------------------------------------------------------------------------------------
   Measured, not guessed. Chromium at 768x1024 (iPad portrait) and 1024x768 (iPad landscape),
   signed in as a case manager, /clients:

     viewport 768  ->  grid scroller 736px wide, table wants 845px, Actions cell spans 759-845
     viewport 1024 ->  drawer stays pinned (MudDrawer's default breakpoint is Md/960), so the
                       scroller is 752px and the same 109px -- the entire Actions cell -- is clipped

   0 of 7 rows showed a single action button in either orientation, the row itself is not a link
   (computed cursor `auto`, no anchor, no RowClick), and the grid's overflow is `auto` with no
   visible scrollbar on a touch device. So on the tablet Nate described -- "you pull a tablet out
   of a bag ... start typing someone's name and then you just kind of work with them from there"
   (PSH demo, paragraph 069) -- there was no way to open a client from the caseload at all.

   845px is the demand of six COLUMNS, not of the content in them, and that was worth checking
   before blaming the data: no seeded client has an HMIS ID and every one is in exactly one
   programme, so the obvious worry was that real Hebron records would be wider still. They are not.
   Filling every HMIS cell and adding programme chips in the live page left the table at 845px --
   cells wrap rather than widening their column. Which is why the fix below removes COLUMNS, and
   why the Actions cell is pinned rather than merely given room.

   Lg (1280px) is where the grid was measured to fit unaided, so that is the threshold -- it is
   MudBlazor's own breakpoint value, and it is the width, not the device, that decides. A narrow
   desktop window has the identical problem and gets the identical treatment.

   What is NOT here, deliberately: nothing for ClientDetail. Its eight MudSimpleTables were
   measured at 768 (including a synthetic seven-column Documents table with realistic filenames,
   which the seed never renders because no client has a document) and none of them overflows --
   table cells wrap. Its ten tabs do not fit, but MudBlazor renders working scroll buttons, so
   they are reachable. Styling that is merely cramped is not styling that is broken.

   SUPERSEDED IN PART, re: #464 item 3 and then re: #605. The tab-strip half of that paragraph no
   longer describes this file: the strip WRAPS, at every width, and the rules that do it are stated
   unconditionally above the below-Lg block, under the comment beginning "re: #464 item 3, re: #605
   item 1". The tables half still stands and nothing was added for them.

   Two things changed, in that order. #464 item 3 changed the RULING below Lg -- the scroll buttons
   did work, and "cramped is not broken" stopped being the answer once the tablet was the intake
   device. #605 changed the MEASUREMENT above it: the sentence "its ten tabs do not fit, but
   MudBlazor renders working scroll buttons" was written about a tablet and is just as true of a
   desk -- 1600px of tabs in an 880px strip at 1280, and still 80px over at 1920. See that comment
   for the numbers and for who decided. */
.hebron-hmis-under-name {
    /* At Lg and up the HMIS ID column below is visible and this would be the same number twice. */
    display: none;
}

/* #431: a household member sits beneath their head in the expanded client list. The indent is the
   visual half; the Name cell also carries hidden text naming the head, which is the half a screen
   reader gets. Kept small so it still fits the tablet grid #221 measured. */
.hebron-household-member {
    padding-left: 1.25rem;
}

.hebron-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* #518: an ordinary date field on a form being filled in is a row -- the picker, then a "Today" button
   beside its calendar icon (DynamicFormRenderer.DatePicker). The PICKER is what gives way at phone
   width: min-width: 0 lets a flex item shrink below its content, so the button never pushes the row
   wider than the screen and never squeezes the calendar icon out of the box. The button keeps its
   width, and nowrap stops "Today" breaking across two lines when the row is tight.
   height pins the 44px thumb target at every width -- MudBlazor's Size.Small outlined button measures
   30.8px on its own, a mouse target, and this is a control a case manager hits with a thumb on a phone.
   margin-top centres that 44px button on the 56px outlined input box rather than on the whole control,
   so a validation message appearing under the box does not drag the button down with it: MudBlazor 9.2
   puts the box 8px down (.mud-input-outlined-with-label, for the floating label), plus 6px to centre.
   Measured in Chromium at 320, 375, 768 and 1280px against the real MudBlazor markup: no horizontal
   scroll, the calendar icon inside the box, the 44px-tall "Today" beside it. */
.hebron-date-field {
    display: flex;
    align-items: flex-start;
    gap: 4px;
    max-width: 100%;
}

.hebron-date-field__picker {
    flex: 1 1 auto;
    min-width: 0;
}

.hebron-date-field__today {
    flex: 0 0 auto;
    margin-top: 14px;
    height: 44px;
    white-space: nowrap;
}

/* re: #464 -- the in-place camera on a form's upload field. Same construction as the capture
   panel's (Components/Capture/CapturePanel.razor.css): a <label> wrapping a visually hidden file
   input, because that is the one shape every mobile browser opens the camera from on a tap -- a
   script-driven .click() on a hidden input loses the user gesture on Safari after any await.

   Here rather than in a scoped stylesheet because UploadField has none, and because the input is
   rendered by a CHILD component (InputFile), which a scoped rule would have to reach through
   ::deep anyway. Styled to read as a filled primary button: on a device with a camera it IS the
   primary way this field gets filled. */
.hebron-upload-field__camera {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.375rem 1rem;
    border-radius: var(--mud-default-borderradius, 4px);
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    font-weight: 500;
    cursor: pointer;
    user-select: none;
}

.hebron-upload-field__camera:focus-within {
    outline: 2px solid var(--mud-palette-primary-darken, currentColor);
    outline-offset: 2px;
}

.hebron-upload-field__camera--busy {
    opacity: 0.6;
    pointer-events: none;
}

/* Hidden but still in the accessibility tree and still focusable, so a keyboard or switch user
   reaches the camera through the same control as a finger. */
.hebron-upload-field__camera input[type=file] {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    opacity: 0;
    cursor: pointer;
}

/* re: #605 item 2 -- A TAB BAR SITS ABOVE THE PANEL IT SWITCHES. Every MudTabs in this app, every
   width. This is the one rule in this file that is not about a breakpoint at all.
   ---------------------------------------------------------------------------------------------
   THE DEFECT, measured on the shipped build rather than read off a stylesheet. A tab panel whose
   first child is a MudGrid inherits that grid's margin-top: -24px, which COLLAPSES through
   .mud-tab-panel and pulls the panel's border box 24px ABOVE .mud-tabs-panels. That element is
   position: relative and later in the DOM, so it won hit-testing over the bottom half of every tab:

     /clients/{id}, 1280x800 AND 1920x1080, signed in as a case manager
         tab row 196-244   .mud-tabs-panels top 244   .mud-tab-panel top 220
         .mud-grid margin-top -24px, the overlapping .mud-grid-item's own padding-top 24px
         elementFromPoint(centreX, tabTop + 4)  ->  DIV.mud-tab
         elementFromPoint(centreX, tabTop + 24) ->  DIV.mud-grid-item
         elementFromPoint(centreX, tabTop + 44) ->  DIV.mud-grid-item
         ALL TEN tabs, at BOTH widths.

     /reports, 1920x1080, signed in as a director
         panels top 282   panel top 258   first child .mud-grid margin-top -24px
         ALL FIVE tabs, the same three probes, the same answers.

   NOTHING IS DRAWN in that band -- it is the grid item's padding -- which is why it never showed up
   in a screenshot or a visual review, and why it survived #221, #464, #589 and #604. A rendered
   48px tab answered to 24. On a mouse that costs precision; on a thumb it costs the tap, and
   Playwright refuses the click outright ("mud-grid-item from mud-tabs-panels subtree intercepts
   pointer events").

   WHY THIS ONE IS NOT SCOPED TO .hebron-client-tabs, when everything below it is. #604 scoped its
   rules to a marker class because they are LAYOUT and a global version would have restyled
   ReportsPage, which nobody had measured. That reasoning does not carry here: /reports was measured
   before this rule was written and has the identical overlap, and a z-index moves no box -- it
   changes which element answers a pointer, and only among siblings inside .mud-tabs. So the rule
   goes where the defect is.

   .mud-tabs is in the selector for specificity (0,2,0) rather than reach: .mud-tabs-tabbar only
   ever exists inside one. */
.mud-tabs .mud-tabs-tabbar {
    z-index: 1;
}

/* re: #464 item 3, re: #605 item 1 -- the client file's TAB STRIP, at EVERY width.
   ---------------------------------------------------------------------------------------------
   These six rules shipped in #604 inside the below-Lg block. They are stated unconditionally now,
   because the premise that made them a tablet change was wrong: ten tabs do not fit a desk either.

   MEASURED on the shipped build, Chromium, signed in as a case manager, on /clients/{id}. MudTabs
   writes style="min-width:160px" on each tab INLINE (MinimumTabWidth, MudBlazor 9.2.0's default),
   so ten of them demand 1600px whatever their labels say:

     viewport   tab-bar row   scrolling strip   tabs demand   not wholly on screen
     768x1024   704px         608px             1600px        7 of 10
     1024x768   720px         624px             1600px        7 of 10
     1280x800   976px         880px             1600px        6 of 10  (tab lefts 320..1760)
     1920x1080  1616px        1520px            1600px        1 of 10  (WORKFLOWS, 80px over)

   So the chevrons #221 called an acceptable affordance were the desktop experience too, at every
   desk width in normal use -- and MudBlazor's strip is overflow: hidden with NO scrollbar, so there
   was no second way to the last tabs at any of those four widths.

   WHAT THE TABS ACTUALLY WANT, which is the number that decides this. Each tab's own content plus
   its padding, measured with a Range over its text at 1280 and again at 1920 (identical at both):

     OVERVIEW 108  PERSONAL INFO 150  ADDRESSES 116  INCOME 87  NOTES 76
     ENROLLMENTS 139  DOCUMENTS 123  FORMS 79  HOUSEHOLD 123  WORKFLOWS 128     TOTAL 1129px

   1129px, not 1600px. The 471px difference is MinimumTabWidth padding ten labels out to a width
   none of them needs. Page chrome around the strip is a constant 304px (240px pinned drawer + 32px
   of MudTabs pa-4 on each side), so the whole strip fits ONE row from 1433px of viewport upward.

   WHICH IS WHY WRAPPING IS THE DESKTOP ANSWER TOO, and why it does not look like a mistake on a
   wide screen: a wrapped strip only wraps when it must. Measured after this change, same build:
   1920x1080 -> ONE row, ten tabs, nothing off screen, nothing clipped. 1280x800 -> TWO rows,
   because 1129 does not fit 976 and no arrangement of ten tabs would. The alternative that looked
   attractive -- keep one row above Lg and merely drop MinimumTabWidth -- was rejected by the same
   measurement: it fixes 1920 and leaves 1280 exactly as broken as it is today, and 1280 is a
   laptop, not an edge case.

   The other two alternatives are the ones #604 rejected below Lg, for reasons that do not change
   with the pointer: a nicer scroll affordance is still an affordance to discover, and folding the
   quieter tabs into a menu would decide for a case manager which half of a client's file is
   secondary. #605 says not to change which tabs exist.

   WHOSE DECISION. This one is TechJoy's, made on the numbers above by the author of the pull
   request that carries them, under #605, which was filed for exactly this decision and left it
   open. It is NOT a Hebron decision and nobody at Hebron has been asked: docs/scoping/
   OPEN-QUESTIONS.md question 6 is "Answered by TechJoy, 18 September 2026 -- not yet confirmed with
   Hebron", and its answer is "build device-agnostic ... everything works on a desktop, improves by
   itself on a touchscreen", which is what a width-responsive wrap is.

   WHAT A DESK GIVES UP, stated rather than buried: 48px of height whenever the viewport is under
   1433px, and MudBlazor's sliding underline, which is replaced by a static one (see .mud-tab-slider
   below). Both were true below Lg already; they are now true above it. */
.hebron-client-tabs .mud-tabs-tabbar-content .mud-tabs-tabbar-wrapper {
    /* width: max-content is what makes the strip one endless row; a definite width is what lets it
       wrap. transform is !important because MudTabs writes translateX() INLINE as it scrolls, and a
       leftover offset would drag row one off the left edge of a strip that no longer scrolls. */
    width: 100%;
    flex-wrap: wrap;
    transform: none !important;
    transition: none;
}

.hebron-client-tabs .mud-tab {
    /* Both overrides are against MudBlazor rather than against us: width:100% comes from its
       stylesheet and would give each tab a row of its own once the wrapper has a definite width,
       and min-width:160px is written INLINE from MudTabs.MinimumTabWidth, which is why it takes
       !important. That and the transform above are the only two !important declarations in this
       file, and both exist for the same reason: they beat an inline style MudTabs writes, which
       nothing weaker can.

       44px IS A FLOOR AND NOT A TARGET, and it is deliberately the SAME number above Lg as below,
       which is worth saying because 44 is the WCAG 2.5.5 thumb minimum and a desk is a mouse.
       Measured: the narrowest tab is NOTES at 76px of its own content, at 768, 1280 and 1920 alike.
       So this floor does not bind at any width today, and any desktop-only floor up to 76 would not
       bind either -- it would be a second number with nothing to do. A floor above 76 would start
       padding real labels out again, which is the thing this change removes. One number, stated so
       a shorter label later cannot quietly fall through it. */
    width: auto;
    min-width: 44px !important;
    flex: 0 1 auto;
}

.hebron-client-tabs .mud-tabs-scroll-button {
    /* The pair of chevrons is what wrapping replaces. Hidden rather than left disabled so the 96px
       they occupy goes back to the tabs, and so a screen reader is not offered "Scroll tabs right"
       for a strip that does not scroll. Worth 96px at 1280, where the strip goes 880 -> 976. */
    display: none;
}

.hebron-client-tabs .mud-tab-slider {
    /* MudBlazor's active-tab indicator is ONE absolutely-positioned bar at the foot of the whole
       strip, placed by a left/width percentage. Correct for one row; on two rows it lands under the
       wrong one. CSS cannot tell how many rows a wrap produced, and this strip is one row at 1920
       and two at 1280, so the indicator that works for both is the one below rather than this. */
    display: none;
}

.hebron-client-tabs .mud-tab.mud-tab-active {
    /* ...so the active tab carries its own underline instead. inset box-shadow rather than a border
       so nothing moves by 2px as the selection changes. */
    box-shadow: inset 0 -2px 0 0 var(--mud-palette-primary);
}

@media (max-width: 1279.98px) {
    .hebron-col-hide-below-lg {
        display: none;
    }

    /* #518: "Today" is a thumb target on the tablet too, and this is also where the row is tightest.
       min-width does two things at once below Lg: it pins the 44px floor so a later Size or padding
       change cannot quietly shrink the target, and it REPLACES MudBlazor's own 64px .mud-button-root
       floor, which the button does not need -- at 320px that hands 8px back to the date box. Measured
       in Chromium: 55.9x44 at 320, 375 and 768; 64x44 at 1280, where MudBlazor's floor takes over
       again. The selector carries .mud-button-root for the specificity that override needs. */
    .hebron-date-field__today.mud-button-root {
        min-width: 44px;
        min-height: 44px;
    }

    .hebron-hmis-under-name {
        display: block;
    }

    /* Size.Small icon buttons measure 26x26 -- a 16px glyph in 5px of padding. That is a mouse
       target, and this is the one control on the page a case manager has to hit with a thumb while
       holding the tablet. 44px is the WCAG 2.5.5 / Apple HIG minimum. Left alone above Lg, where
       the pointer is a mouse and the denser row is worth more than the bigger target. */
    .hebron-row-actions .mud-icon-button {
        min-width: 44px;
        min-height: 44px;
    }

    /* re: #427 -- the control that goes straight into a client's intake. Size.Small keeps it inside
       the Open work row at desk width; on the tablet a case manager is holding while sitting with
       the client it is the first thing they press, so it takes the same 44px floor. */
    .hebron-open-the-work.mud-button-root {
        min-width: 44px;
        min-height: 44px;
    }

    /* re: #464 -- the form field's camera control takes the SAME 44px floor as the capture panel's,
       at the same threshold. It is only ever rendered where the browser answered that a tap opens a
       camera, which is a touchscreen, which is a thumb. Stated at this breakpoint rather than
       unconditionally so the rule stays where every other touch-target rule in this file is; on a
       desktop the control is not rendered at all, so there is nothing for it to cost. */
    .hebron-upload-field__camera {
        min-width: 44px;
        min-height: 44px;
    }

    /* re: #464 item 3, re: #605 -- the ClientDetail TAB STRIP used to be styled HERE, below Lg
       only. It is now stated unconditionally, above this block, under the comment beginning
       "re: #605 -- the client file's TAB STRIP". Nothing about the tablet rendering changed; what
       changed is that a desk gets the same treatment, because the ten tabs never fitted one either.
       Left as a pointer rather than deleted silently, because "the tablet rules are in the below-Lg
       block" was true of this file for one day and is written down in #464, #604 and their tests. */
}

/* re: #714: in-app help. The drawer renders the user guide's markdown; the tour card sits above
   the page's own content rather than over it. */
.help-body p,
.help-body ul,
.help-body ol {
    margin: 0 0 0.75rem;
}

.help-body ul,
.help-body ol {
    padding-left: 1.25rem;
}

.help-body code {
    font-size: 0.85em;
    background: var(--mud-palette-background-gray);
    padding: 0 0.25rem;
    border-radius: 3px;
}

.help-body .help-heading {
    font-size: 1rem;
    margin: 1rem 0 0.5rem;
}

.help-body .help-note {
    margin: 0 0 0.75rem;
    padding: 0.5rem 0.75rem;
    border-left: 3px solid var(--mud-palette-primary);
    background: var(--mud-palette-background-gray);
}

.help-body .help-table {
    border-collapse: collapse;
    margin: 0 0 0.75rem;
    font-size: 0.85rem;
}

.help-body .help-table th,
.help-body .help-table td {
    border: 1px solid var(--mud-palette-lines-default);
    padding: 0.25rem 0.5rem;
    vertical-align: top;
    text-align: left;
}

.help-section {
    margin-bottom: 1.25rem;
}

.tour-card {
    border-left: 4px solid var(--mud-palette-primary);
}

/* re: #996: the Help page's table of contents. */
.help-toc-list {
    list-style: none;
    margin: 0 0 0.5rem;
    padding: 0;
}

.help-toc-link {
    display: block;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    color: var(--mud-palette-text-primary);
    text-decoration: none;
}

.help-toc-link:hover,
.help-toc-link:focus-visible {
    background: var(--mud-palette-action-default-hover);
}

.help-toc-current {
    font-weight: 600;
    color: var(--mud-palette-primary);
}

.help-open-in-help,
.help-all-help {
    font-size: 0.875rem;
    color: var(--mud-palette-primary);
}

/* re: #713 -- an element put in full screen is drawn on the browser's default backdrop, which is
   black, unless it says otherwise. The kiosk screen and the reports page both paint the theme's own
   background and scroll inside themselves, so a long reports tab is still readable on the TV. */
.kiosk-screen,
.reports-page:fullscreen {
    background: var(--mud-palette-background);
    min-height: 100vh;
    overflow-y: auto;
}

.reports-page:fullscreen {
    padding: 24px;
}

/* #762 -- WCAG 1.4.10 Reflow (320px) and 1.4.4 Resize Text (200%). Wrap rather than hide, and
   never clip: nothing below uses overflow:hidden.

   A switch whose label is a sentence ("Require a second person to approve a payment", /payments).
   MudBlazor gives a boolean input `flex: 0 0 auto`, so beside the status line it would not shrink,
   and its label ran 65px past the edge at 320px. Allowed to shrink, the label wraps instead. The
   min-width stays auto on purpose: at 0 the control shrinks below its own label, which then runs
   out of the control rather than out of the page -- the same overflow, one box further in. */
.mud-input-control.hebron-wrapping-label {
    flex: 0 1 auto;
    max-width: 100%;
}

/* The steps of a workflow instance (/workflows/{id}): four cells, two of them a fixed 10rem and
   11rem, need ~464px. Below the sm breakpoint each step becomes a wrapping row -- number and name on
   the first line, the status chip and the action under them -- instead of a table that cut the status
   chips off at its own edge. The long selectors are there to outrank MudBlazor's own
   `.mud-simple-table table * tr { display: table-row }`; a plain `.hebron-step-table tr` loses. */
@media (max-width: 599.98px) {
    .hebron-step-table.mud-simple-table table tbody tr {
        display: flex;
        flex-wrap: wrap;
        align-items: flex-start;
    }

    .hebron-step-table.mud-simple-table table tbody tr > td {
        width: auto !important;
    }

    .hebron-step-table.mud-simple-table table tbody tr > td:nth-child(2) {
        flex: 1 1 10rem;
    }
}

/* A native file input asks for ~316px whatever its container offers (/my/documents). */
input[type="file"] {
    max-width: 100%;
}

/* re: #978 -- ONE CONTROL PER FILE PICKER. Every MudFileUpload here sets Hidden="false" and passes a
   FilePickerButton (Components/Shared/FilePickerButton.razor) as its custom content. Hidden="false"
   keeps the native input out of display:none, so it is still the keyboard stop and still carries
   the aria-label #750/#755 gave it; this rule hides it VISUALLY only, which is what removes the
   browser's own "Choose files / No file chosen" from beside the button.

   Clipped rather than display:none, visibility:hidden or opacity on a full-size box: the first two
   take it out of the tab order and the accessibility tree, and the third leaves an invisible target
   over the page. Scoped to .mud-file-upload so the camera inputs (.hebron-upload-field__camera,
   .capture-panel__camera, [data-camera-control]), which sit OVER their own visible label on purpose,
   are untouched. A MudFileUpload left at Hidden="true" still carries the `hidden` attribute, which
   this rule does not override. */
.mud-file-upload {
    position: relative;
}

.mud-file-upload input[type="file"] {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* The input has the keyboard focus but cannot show it, so the ring goes on the button beside it --
   the same move the checkbox rule near the top of this file makes for MudBlazor's hidden inputs. */
:root .mud-file-upload:has(input[type="file"]:focus-visible) .hebron-file-picker {
    outline: 2px solid var(--hebron-focus-ring);
    outline-offset: 2px;
    box-shadow: 0 0 0 2px #FFFFFF;
}
