/* DVM design system: the custom CSS both apps need beyond the MudBlazor theme.
   Approved 2026-10-24. Every colour is a palette variable, so each rule works in
   light and dark mode without a second copy. Lives in DVM.UI.Shared so both apps load
   one copy (D-082). Link it after MudBlazor's stylesheet AND after Quill's: the .ql-snow
   rules below have the same specificity as Quill's own, so a later Quill sheet would win.
   <link href="_content/DVM.UI.Shared/css/dvm-design-system.css" rel="stylesheet" />   */


/* ---- 1. Form validation (proposal 7) ------------------------------------------
   Palette colours instead of the hard-coded #26B050 and red app.css used to carry. */
.valid.modified:not([type=checkbox]) { outline: 1px solid var(--mud-palette-success); }
.invalid                             { outline: 1px solid var(--mud-palette-error); }
.validation-message                  { color: var(--mud-palette-error); }


/* ---- 2. Update banner button (clinic app only) --------------------------------
   Palette colours instead of the white / #820933 / #F0DDE3 / #E6C9D2 app.css used to carry,
   so the button follows the theme into dark mode. Its own class rather than an inline Style
   because inline styles can't hold :hover and beat MudBlazor's hover rule (Session 102).
   Light: maroon on white 9.5:1 (6.7:1 pressed). Dark: rose on dark ink 6.6:1 (5.0:1). */
.pwa-update-btn {
    background-color: var(--mud-palette-secondary-text) !important;
    color: var(--mud-palette-secondary) !important;
    font-weight: 700;
}
.pwa-update-btn:hover {
    background-color: color-mix(in srgb, var(--mud-palette-secondary) 12%, var(--mud-palette-secondary-text)) !important;
}
.pwa-update-btn:focus-visible,
.pwa-update-btn:active {
    background-color: color-mix(in srgb, var(--mud-palette-secondary) 18%, var(--mud-palette-secondary-text)) !important;
}

/* Dark mode (Chad, 2026-10-25: the bright rose bar with a near-black button read as harsh): the
   banner becomes a deep maroon with rose text (about 4.7:1; 22% rose measured only 4.0) and the button a solid rose with dark ink
   (6.6:1), normal weight, no shadow. Still the loudest thing on screen, without the alarm. */
.dvm-dark .dvm-update-banner {
    background-color: color-mix(in srgb, var(--mud-palette-secondary) 12%, var(--mud-palette-surface)) !important;
    color: var(--mud-palette-secondary) !important;
}
.dvm-dark .dvm-update-banner .mud-typography,
.dvm-dark .dvm-update-banner .mud-icon-root { color: inherit !important; }
.dvm-dark .pwa-update-btn {
    background-color: var(--mud-palette-secondary) !important;
    color: var(--mud-palette-secondary-text) !important;
    font-weight: 500;
    box-shadow: none !important;
}
.dvm-dark .pwa-update-btn:hover { background-color: color-mix(in srgb, var(--mud-palette-secondary) 85%, white) !important; }
.dvm-dark .pwa-update-btn:focus-visible,
.dvm-dark .pwa-update-btn:active { background-color: color-mix(in srgb, var(--mud-palette-secondary) 72%, white) !important; }


/* ---- 3. Grouped report tables (proposal 10) -------------------------------------
   Day Sheet, Activity Report, office Day Sheet.
   Markup: <MudTable Dense Hover FixedHeader FixedFooter Class="dvm-grouped"> (not Striped);
   each group row's MudTr gets dvm-t-top (Day, or Clinic in the office app), dvm-t-sub (vet),
   dvm-t-mid (client) or dvm-t-leaf (patient); treatment lines get RowClass="dvm-line".
   MudTable gives a GroupHeaderTemplate no way to class its own <tr>, so the tier class may go on
   the group's cells instead (the clinic Day Sheet does that); both forms are matched below.
   Remove the inline padding-left: 75px !important from the treatment cell.

   Colour says which level a group row is, so the table doesn't need stripes. One navy hue
   steps down; dark mode sits one step higher because the same percentages on a dark
   surface run together. */
.dvm-grouped           { --dvm-tier-top: 16%; --dvm-tier-sub: 10%; --dvm-tier-mid: 5%; }
.dvm-dark .dvm-grouped { --dvm-tier-top: 22%; --dvm-tier-sub: 16%; --dvm-tier-mid: 10%; }

/* MudBlazor's dense cells are 6px 24px 6px 16px; most of the table's width was padding.
   !important because MudBlazor's own rules are more specific (.mud-table-dense * .mud-table-row
   .mud-table-cell) or already !important (the group indents below). */
.dvm-grouped .mud-table-cell { padding: 4px 8px !important; }
.dvm-grouped .mud-table-cell .mud-icon-button { padding: 4px; }

.dvm-grouped tr.dvm-t-top > .mud-table-cell,
.dvm-grouped .mud-table-cell.dvm-t-top {
    background: color-mix(in srgb, var(--mud-palette-primary) var(--dvm-tier-top), var(--mud-palette-surface));
    color: var(--mud-palette-primary);
    font-weight: 700;
}
.dvm-grouped tr.dvm-t-sub > .mud-table-cell,
.dvm-grouped .mud-table-cell.dvm-t-sub {
    background: color-mix(in srgb, var(--mud-palette-primary) var(--dvm-tier-sub), var(--mud-palette-surface));
    color: var(--mud-palette-primary);
    font-weight: 700;
}
.dvm-grouped tr.dvm-t-mid > .mud-table-cell,
.dvm-grouped .mud-table-cell.dvm-t-mid {
    background: color-mix(in srgb, var(--mud-palette-primary) var(--dvm-tier-mid), var(--mud-palette-surface));
    font-weight: 500;
}
.dvm-grouped tr.dvm-t-leaf > .mud-table-cell,
.dvm-grouped .mud-table-cell.dvm-t-leaf {
    background: transparent;
    font-weight: 500;
}

/* Client and patient links render as 16px MudLinks today; match the 14px group text. */
.dvm-grouped .mud-table-cell .mud-link { font-size: .875rem; font-weight: 500; }

/* Indent by level in 12px steps; treatment lines sit one step past the patient.
   MudBlazor indents every level 48px with !important (tr.mud-table-row-group-indented-N
   td:first-child), which is what the old inline 75px was hiding; these selectors are more
   specific, so with !important they win. */
.dvm-grouped tr > .mud-table-cell:first-child                                { padding-left: 8px !important; }
.dvm-grouped tr.mud-table-row-group-indented-1 > .mud-table-cell:first-child { padding-left: 20px !important; }
.dvm-grouped tr.mud-table-row-group-indented-2 > .mud-table-cell:first-child { padding-left: 32px !important; }
.dvm-grouped tr.mud-table-row-group-indented-3 > .mud-table-cell:first-child { padding-left: 44px !important; }
.dvm-grouped tr.dvm-line > .mud-table-cell:first-child                       { padding-left: 56px !important; }


/* ---- 3b. Page header (Chad 2026-10-25) ----------------------------------------------------
   Every page's title sits on the page itself, not in a card of its own: the title (h5), then its
   actions, then a spacer and any search on the right. The cards below hold the content, so the
   title reads as the page's heading and the page gains the card's padding and shadow.
   Markup: div.dvm-page-header > MudText Typo.h5 Class="dvm-page-title" + buttons [+ MudSpacer + search] */
.dvm-page-header { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; min-height: 48px; }
.dvm-page-header > .dvm-page-title { margin-right: 8px; }
.dvm-page-header > .dvm-page-search { flex: 0 1 320px; }
/* Patient Details search, stacked like the heading beside it: the field and ‹ › on top, the match
   count (or a thin progress bar while searching) underneath, so the block is ~340px wide and fits
   beside the title even on a tablet. */
.dvm-patient-search { flex: none; display: flex; flex-direction: column; }
.dvm-patient-search-row { display: flex; align-items: center; gap: 0; }
.dvm-patient-search-row > .mud-input-control { flex: none; width: 240px; margin-right: 4px; }
.dvm-patient-search > .mud-typography { padding-left: 2px; line-height: 1.2; font-variant-numeric: tabular-nums; white-space: nowrap; }
.dvm-patient-search > .dvm-patient-search-busy { margin-top: 6px; }
/* Never wraps (Chad 2026-10-25): with wrapping, a long patient name pushed the search to a second
   row, so the header jumped between one and two rows as you stepped through matches. */
.dvm-patient-header { flex-wrap: nowrap; }
/* Title over owners, each one line ending in "…" if too long; the block takes what the search
   leaves (basis 0, so it can never force a wrap). */
.dvm-patient-heading { flex: 1 1 0; min-width: 0; display: flex; flex-direction: column; }
.dvm-patient-heading > .dvm-page-title,
.dvm-patient-heading > .dvm-patient-owners { min-width: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }


/* ---- 4. Editor pages (Letterhead, Exam Report, PPE, Radiograph) ---------------------
   The page never scrolls as a whole; only the editor or form card scrolls.
   Remove the inline height: calc(100vh - 150px) from the Quill container (it undercounts
   the app bar, title row, toolbar and padding, so the page ran ~22px taller than the window).
   Markup: MudContainer Class="dvm-editor-page" > title row (MudPaper) >
           div.dvm-editor-body > MudPaper Class="dvm-editor-card" + MudPaper Class="dvm-editor-side" */
/* The update banner's height is part of the sum too: MainLayout sets --dvm-banner-height (D-083). */
.dvm-editor-page {
    height: calc(100dvh - var(--mud-appbar-height) - var(--dvm-banner-height, 0px));
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding-top: 16px;
    padding-bottom: 16px;
    overflow: hidden;
}
.dvm-editor-body { flex: 1; min-height: 0; display: flex; gap: 16px; align-items: flex-start; }
.dvm-editor-side { flex: 0 0 260px; max-height: 100%; overflow-y: auto; }

/* One rounded card; overflow: hidden is what rounds the corners over Quill's square boxes. */
.dvm-editor-card { flex: 1; min-width: 0; align-self: stretch; display: flex; flex-direction: column; overflow: hidden; }
.dvm-editor-card .ql-toolbar.ql-snow   { flex: none; border: 0; border-bottom: 1px solid var(--mud-palette-divider); }
.dvm-editor-card .ql-container.ql-snow { flex: 1; min-height: 0; border: 0; font-size: inherit; }
.dvm-editor-card .ql-editor            { height: 100%; overflow-y: auto; }

/* Quill's snow theme hard-codes #444 icons and #CCC borders (1.6:1 on the dark surface). */
.ql-snow .ql-stroke, .ql-snow .ql-stroke-miter { stroke: var(--mud-palette-action-default); }
.ql-snow .ql-fill, .ql-snow .ql-stroke.ql-fill  { fill: var(--mud-palette-action-default); }
.ql-snow .ql-picker { color: var(--mud-palette-action-default); }
/* Quill's hover/active rules sit four or five classes deep (.ql-snow.ql-toolbar button:hover …),
   so a shorter selector loses even when loaded later; :is() matches their depth, and load order decides. */
:is(.ql-snow.ql-toolbar, .ql-snow .ql-toolbar) :is(button:hover, button:focus, button.ql-active, .ql-picker-label:hover, .ql-picker-label.ql-active, .ql-picker-item:hover, .ql-picker-item.ql-selected) { color: var(--mud-palette-primary); }
:is(.ql-snow.ql-toolbar, .ql-snow .ql-toolbar) :is(button:hover, button:focus, button.ql-active, .ql-picker-label:hover, .ql-picker-label.ql-active, .ql-picker-item:hover, .ql-picker-item.ql-selected) :is(.ql-stroke, .ql-stroke-miter) { stroke: var(--mud-palette-primary); }
:is(.ql-snow.ql-toolbar, .ql-snow .ql-toolbar) :is(button:hover, button:focus, button.ql-active, .ql-picker-label:hover, .ql-picker-label.ql-active, .ql-picker-item:hover, .ql-picker-item.ql-selected) :is(.ql-fill, .ql-stroke.ql-fill) { fill: var(--mud-palette-primary); }
.ql-snow .ql-picker-options { background: var(--mud-palette-surface); border-color: var(--mud-palette-lines-default); }
.ql-editor.ql-blank::before { color: var(--mud-palette-text-secondary); }

/* Header (ClinicLetterhead mock, Chad 2026-10-25): the title, then the actions right after it, with
   Delete pushed to the far end. A long patient line wraps the actions onto a second row. */
.dvm-editor-header { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 8px 16px; }
.dvm-editor-title { min-width: 0; overflow-wrap: anywhere; }
/* The back arrow hugs the title; the header's 16px gap is for the action row. */
.dvm-editor-back { margin-left: -8px; margin-right: -12px; }
/* Below desktop the header stays one row (Chad 2026-10-25): a long patient line wrapped the title to
   three lines and pushed the actions under it, 181px of header on a tablet. The title gives way
   and ends in an ellipsis; the full text is in its tooltip. Delete keeps a little distance. */
@media (max-width: 1279.98px) {
    .dvm-editor-header { flex-wrap: nowrap; }
    .dvm-editor-title { flex: 1 1 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
    .dvm-editor-actions { flex: 0 0 auto; flex-wrap: nowrap; }
    .dvm-editor-actions > .mud-button-outlined-error { margin-left: 16px; }
}
.dvm-editor-actions { flex: 1 1 auto; display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }

/* What fills the card under the letterhead band: the Quill editor, the form, or the skeleton. */
.dvm-editor-card > .dvm-fill { flex: 1; min-height: 0; }

/* The letterhead the PDF adds, read-only, in the PDF's order; the maroon rule marks where the page
   ends and the letter begins. */
.dvm-letterhead { flex: none; display: flex; align-items: center; gap: 20px; padding: 16px 32px 12px; border-bottom: 2px solid var(--mud-palette-secondary); }
.dvm-letterhead-text { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.dvm-letterhead-name { font-weight: 700; line-height: 1.3; }
.dvm-letterhead-phones { margin-left: auto; align-self: stretch; display: flex; flex-direction: column; align-items: flex-end; justify-content: flex-end; gap: 2px; white-space: nowrap; }
.dvm-letterhead-note { margin-bottom: auto; }
/* Sized by the card, not the window: on a landscape tablet with the menu open the card is only
   ~430px wide, and the full band wrapped to 276px and left the letter 59px. Narrow, it keeps the
   name, practice and phones on one short band and drops the address and the note. */
.dvm-editor-card { container-type: inline-size; }
@container (max-width: 639.98px) {
    .dvm-letterhead { padding: 8px 16px; gap: 12px; }
    .dvm-letterhead-logo { height: 40px !important; }
    .dvm-letterhead-name { font-size: 1rem !important; }
    .dvm-letterhead-text > :last-child, .dvm-letterhead-note { display: none; }
}
/* A short window gets the compact band too, whatever the card's width, so the letter or the
   findings keep the height (landscape tablet: 233px of form before, with the full band). */
@media (max-height: 899.98px) {
    .dvm-letterhead { padding: 8px 16px; gap: 12px; }
    .dvm-letterhead-logo { height: 40px !important; }
    .dvm-letterhead-name { font-size: 1rem !important; }
    .dvm-letterhead-text > :last-child, .dvm-letterhead-note { display: none; }
}

/* Radiograph (ClinicRadiograph mock, Chad 2026-10-25): one scrolling form under the band. The
   details share a row; the findings are a grid, region name then Right and Left, so each region is
   one line instead of a card. Cervical and Back span both sides. */
.dvm-rg-body { padding: 16px 24px; display: flex; flex-direction: column; gap: 20px; }
.dvm-rg-details { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px 24px; }
.dvm-rg-findings { display: grid; grid-template-columns: 140px minmax(0, 1fr) minmax(0, 1fr); column-gap: 24px; row-gap: 4px; align-items: start; }
.dvm-rg-findings-title { grid-column: 1 / -1; font-weight: 500; }
/* Top-aligned, so a short side starts level with a long one rather than at its last line. */
.dvm-rg-region { padding-top: 6px; font-size: 0.875rem; font-weight: 500; }
.dvm-rg-findings > .dvm-rg-both { grid-column: 2 / -1; }
/* Narrow card (portrait, or landscape with the menu open): the region name goes above its pair. */
@container (max-width: 559.98px) {
    .dvm-rg-body { padding: 12px 16px; }
    .dvm-rg-findings { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); column-gap: 16px; }
    .dvm-rg-findings > span[aria-hidden] { display: none; }
    .dvm-rg-region { grid-column: 1 / -1; padding: 8px 0 0; }
    .dvm-rg-findings > .dvm-rg-both { grid-column: 1 / -1; }
}

/* Below 960px the details panel moves above the editor; the editor still fills what's left. */
@media (max-width: 959.98px) {
    .dvm-editor-body { flex-direction: column-reverse; align-items: stretch; }
    .dvm-editor-side { flex: none; max-height: none; }
}

/* Tablet portrait (D-083, Chad 2026-10-25): the details collapse into a compact strip above the
   editor, so the editor keeps most of the height (stacked as a column it left the editor ~220px). */
@media (max-width: 959.98px) {
    /* The panel's MudStack renders as div.d-flex.flex-column (no mud-stack class), and MudBlazor's
       utility classes are !important, so this has to be too. */
    .dvm-editor-side > .d-flex { flex-direction: row !important; flex-wrap: wrap !important; align-items: center !important; gap: 8px !important; }
    .dvm-editor-side > .d-flex > * { flex: 1 1 160px; margin: 0; }
    /* The strip says what it is by its fields; the heading would take a slot of its own. */
    .dvm-editor-side .dvm-editor-side-title { display: none; }
    /* A smaller band, so the letter keeps the height. */
    .dvm-letterhead { padding: 10px 16px 8px; gap: 12px; }
    .dvm-letterhead-logo { height: 48px !important; }
    .dvm-letterhead-note { display: none; }
}


/* ---- 5. Pages that fit the window (D-083) ----------------------------------------------
   The page never scrolls as a whole; one area inside it does. MainLayout sets
   --dvm-banner-height on MudLayout while the update banner shows, so no page tracks the
   banner or computes a height from vh.
   Markup: MudContainer Class="dvm-fit-page" > header MudPaper > div.dvm-fit-row >
           MudPaper Class="dvm-fill-tabs dvm-fit-main" + MudPaper Class="dvm-fill-tabs dvm-fit-side" */
.dvm-fit-page {
    height: calc(100dvh - var(--mud-appbar-height) - var(--dvm-banner-height, 0px));
    display: flex;
    flex-direction: column;
    gap: 16px;
    padding-top: 16px;
    padding-bottom: 16px;
    overflow: hidden;
}

/* Takes the height the header leaves; its cards sit side by side at the old 9/3 grid split. */
.dvm-fit-row  { flex: 1; min-height: 0; display: flex; gap: 16px; }
.dvm-fit-main { flex: 3 1 0; min-width: 0; }
.dvm-fit-side { flex: 1 1 0; min-width: 0; }

/* A card or area that scrolls its own content rather than the page. Comes after
   .dvm-editor-card so it can lift that card's overflow: hidden for a plain form. */
.dvm-scroll { overflow-y: auto; }

/* A card holding MudTabs: the tabs fill the card and the open panel scrolls. */
.dvm-fill-tabs { display: flex; flex-direction: column; min-height: 0; }
.dvm-fill-tabs > .mud-tabs { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.dvm-fill-tabs > .mud-tabs > .mud-tabs-panels { flex: 1; min-height: 0; overflow-y: auto; }
/* The panels scroll, so they clip whatever touches their edges, including a card's or table's
   elevation shadow. Leave a few pixels for it (MudBlazor's elevation 1–2 shadows reach about 5px
   down and 2px to the sides). A PanelClass such as pa-4 overrides this with more. */
.dvm-fill-tabs > .mud-tabs > .mud-tabs-panels { padding: 0 2px 6px; }

/* A tab panel whose table fills it: rows scroll under the fixed header; search and pager stay put.
   Scoped to .mud-tabs-panels because MudBlazor also puts a MudTabPanel's Class on its tab header. */
.mud-tabs-panels > .mud-tab-panel.dvm-table-panel { height: 100%; display: flex; flex-direction: column; }
.mud-tabs-panels > .mud-tab-panel.dvm-table-panel > .mud-table { flex: 1; min-height: 0; display: flex; flex-direction: column; }
/* Only the table grows: MudBlazor gives .mud-input-control flex: 1 1 auto, so a search field above the table would stretch too. */
.mud-tabs-panels > .mud-tab-panel.dvm-table-panel > :not(.mud-table) { flex: none; }
.mud-tabs-panels > .mud-tab-panel.dvm-table-panel > .mud-table > .mud-table-container { flex: 1; min-height: 0; }

/* A single area (usually a dvm-fill-tabs wrapper) that takes all the height a fit page has left. */
.dvm-fit-fill { flex: 1 1 0; min-height: 0; }

/* Equal columns in a .dvm-fit-row (Patient Details' four report tables). */
.dvm-fit-col { flex: 1 1 0; min-width: 0; }

/* A tab panel holding a .dvm-fit-row (with an optional header card above it): the panel fills
   the tab, the row takes what the header leaves. 8px replaces the gutter MudGrid used to add. */
.mud-tabs-panels > .mud-tab-panel.dvm-row-panel { height: 100%; display: flex; flex-direction: column; gap: 8px; padding-top: 8px; }
.mud-tabs-panels > .mud-tab-panel.dvm-row-panel > :not(.dvm-fit-row) { flex: none; }

/* A box (column or card) whose MudTable fills it: rows scroll under the fixed header; the
   table's toolbar and pager, and anything above the table, keep their own height. */
.dvm-fill-table { display: flex; flex-direction: column; min-height: 0; }
.dvm-fill-table > :not(.mud-table) { flex: none; }
.dvm-fill-table > .mud-table { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.dvm-fill-table > .mud-table > :not(.mud-table-container) { flex: none; }
.dvm-fill-table > .mud-table > .mud-table-container { flex: 1; min-height: 0; }

/* Tablet portrait (below 960px; D-083, Chad 2026-10-25): a two-card page stays side by side and
   still fits the window. The side card keeps a fixed 240px so the main card gets the rest. */
@media (max-width: 959.98px) {
    .dvm-fit-row > .dvm-fit-side { flex: 0 0 240px; }
}


/* Dev: SQL Query (Chad 2026-10-25): the query cards keep their height; Result takes the rest and
   scrolls inside itself, horizontally too, since JSON rows run long. */
.dvm-sql-main { display: flex; flex-direction: column; gap: 8px; min-height: 0; }
.dvm-sql-main > * { flex: none; }
.dvm-sql-main > .dvm-sql-result-card { flex: 1; min-height: 0; display: flex; flex-direction: column; }
.dvm-sql-result { flex: 1; min-height: 0; overflow: auto; margin: 4px 0 0; font-family: ui-monospace, Consolas, monospace; font-size: 0.8125rem; white-space: pre; width: 100%; resize: none; padding: 8px; border: 1px solid var(--mud-palette-lines-inputs); border-radius: var(--mud-default-borderradius); background: transparent; color: var(--mud-palette-text-primary); }

/* Dashboard (ClinicDashboard mock, approved 2026-10-24; built Chad 2026-10-25). The welcome card keeps
   its height; the three cards share the rest and each scrolls its own list. Three across on a
   desktop, two plus Recently opened underneath on a tablet in landscape, stacked in portrait. */
.dvm-welcome { flex: none; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px; padding: 20px 24px; }
.dvm-welcome-text { display: flex; flex-direction: column; gap: 2px; }
.dvm-dash-grid { flex: 1; min-height: 0; display: grid; gap: 16px; grid-template-columns: 1.2fr 1.2fr .9fr; grid-auto-rows: minmax(0, 1fr); }
.dvm-dash-card { min-height: 0; display: flex; flex-direction: column; overflow: hidden; }
.dvm-dash-card-head { flex: none; display: flex; align-items: center; gap: 8px; padding: 12px 16px; border-bottom: 1px solid var(--mud-palette-table-lines); }
.dvm-dash-card-body { flex: 1; min-height: 0; overflow-y: auto; }
.dvm-dash-card .dvm-num { text-align: right; font-variant-numeric: tabular-nums; }
.dvm-nowrap { white-space: nowrap; }
.dvm-strong { font-weight: 700; }
.dvm-ellipsis { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.dvm-recent-list { list-style: none; margin: 0; padding: 4px 0; }
.dvm-recent { display: flex; align-items: flex-start; gap: 14px; padding: 8px 16px; }
.dvm-recent > .mud-icon-root { margin-top: 2px; flex: none; }
.dvm-recent-text { flex: 1; display: flex; flex-direction: column; min-width: 0; }
.dvm-recent-when { flex: none; margin-top: 2px; white-space: nowrap; }
.dvm-recent-text > * { display: block; max-width: 100%; }
@media (max-width: 1279.98px) {
    /* A smaller logo and padding keep the greeting and both shortcuts on one line; wrapped, the
       card was 217px and left the lists ~140px. */
    .dvm-welcome { padding: 12px 16px; gap: 8px 16px; }
    .dvm-welcome .mud-image { width: 56px !important; height: auto; }
    .dvm-dash-grid { grid-template-columns: 1fr 1fr; }
    .dvm-dash-grid > .dvm-dash-recent { grid-column: 1 / -1; }
}
@media (max-width: 959.98px) {
    .dvm-dash-grid { grid-template-columns: 1fr; }
}

/* ---- 6. Connection chip (clinic app bar; D-084 session) ----------------------------------
   Online, Offline and Checking are one chip shape. The outlined ones take the app bar's own
   text colour (MudBlazor would give them the page's text colour, dark on the navy bar); the
   checking span in app.css dims it to 60%. One width for all three so the bar doesn't shift. */
.mud-appbar .dvm-conn-chip { min-width: 104px; justify-content: center; margin: 0 4px; }
.mud-appbar .dvm-conn-chip.mud-chip-outlined { color: inherit; border-color: currentColor; }
.mud-appbar .dvm-conn-chip.mud-chip-outlined .mud-chip-icon { color: inherit; }


/* ---- 7. User-chosen colours (D-084) ------------------------------------------------------
   Some text is drawn in the colour a user picked for themselves (who performed a history line).
   Markup: Class="dvm-user-color" Style="--dvm-user-color: <the user's colour>".
   Light mode shows the colour as chosen. Dark mode mixes it toward white, so a dark pick (black,
   deep green) stays readable on the dark surface while still looking like the same colour;
   35% keeps even black at about 5:1 on the dark card. */
/* The table forms repeat the class: MudBlazor colours every body cell with
   .mud-table-root .mud-table-body .mud-table-cell, which outranks a single class. */
.dvm-user-color,
.mud-table-root .mud-table-body .mud-table-cell.dvm-user-color { color: var(--dvm-user-color, var(--mud-palette-text-primary)); }
.dvm-dark .dvm-user-color,
.dvm-dark .mud-table-root .mud-table-body .mud-table-cell.dvm-user-color { color: color-mix(in oklab, var(--dvm-user-color, var(--mud-palette-text-primary)) 35%, white); }


/* ---- 8. Sign-in card (clinic app now; the office app's office.css has the same values) -------
   A centred card near the top of the page, 380px at most, logo centred above the name. */
.dvm-login-page { display: flex; justify-content: center; padding: 64px 16px; }
.dvm-login-card { width: 100%; max-width: 380px; }
.dvm-login-logo { display: block; margin: 0 auto 8px; }


/* ---- 9. "New" beside a list's title (Patient Details > Reports; Chad, 2026-10-25) -------------
   Four lists share the row, so on a tablet each column is about 170px. There the toolbar's 24px
   gutters shrink to 8px and the button drops its word to just the + (its tooltip and aria-label
   still say what it makes), so title and button stay on one line. */
@media (max-width: 1279.98px) {
    .dvm-fill-table > .mud-table > .mud-toolbar { padding-left: 8px; padding-right: 8px; }
    .dvm-new-btn .dvm-new-btn-text { display: none; }
    /* A square the same height as the worded button, with the + centred (MudBlazor's start-icon
       margins assume a label follows, so they're cleared). */
    .mud-button-root.dvm-new-btn { min-width: 0; width: 30px; height: 30px; padding: 0; }
    .mud-button-root.dvm-new-btn .mud-button-icon-start { margin: 0; }
}
