/*
 * Shared Component Styles for Medical Practice Server
 * Common UI/UX patterns and styling for consistent design
 */

/* ===== LAYOUT & CONTAINERS ===== */
/* Padding here is ON TOP of the 1rem `.rz-body` already applies, so anything
   set here is doubled up before content starts. The gutter is governed from
   .rz-body in MainLayout; this stays at zero so the two do not compound.
   (Below 768px .rz-body drops to 0 and this was already 0 — unchanged.) */
.page-container {
    width: 100%;
    min-height: calc(100vh - 60px);
    background: var(--rz-body-background-color, var(--rz-base-50, #f8f9fa));
    padding: 0;
    box-sizing: border-box;
}

/* Custom content styling - Radzen components handle their own theming */

/* ===== STATISTICS CARDS ===== */
.stats-grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 1rem;
    margin-bottom: 2rem;
}

/* Statistics content inside RadzenCards */
.stat-content {
    text-align: center;
    transition: transform 0.2s ease;
}

.stat-content.clickable {
    cursor: pointer;
}

.stat-content.clickable:hover {
    transform: translateY(-2px);
}

.stat-header {
    margin-bottom: 0.5rem;
}

.stat-header.success { --stat-color: var(--rz-success); }
.stat-header.info { --stat-color: var(--rz-info); }
.stat-header.warning { --stat-color: var(--rz-warning); }
.stat-header.secondary { --stat-color: var(--rz-secondary); }
.stat-header.danger { --stat-color: var(--rz-danger); }

.stat-icon {
    font-size: 2rem;
    color: var(--stat-color, var(--rz-primary));
    opacity: 0.9;
}

.stat-value {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--rz-text-color);
    margin: 0.5rem 0;
    line-height: 1.2;
}

.stat-value-loading {
    font-size: 1.6rem;
    font-weight: 700;
    color: var(--rz-text-secondary-color);
    margin: 0.5rem 0;
    line-height: 1.2;
    animation: pulse 1.5s ease-in-out infinite alternate;
}

@keyframes pulse {
    from { opacity: 0.4; }
    to { opacity: 1; }
}

.stat-label {
    font-size: 0.875rem;
    color: var(--rz-text-secondary-color);
    font-weight: 500;
    letter-spacing: 0.5px;
}

.stat-trend {
    font-size: 0.75rem;
    margin-top: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.stat-trend.up {
    color: var(--rz-success);
}

.stat-trend.down {
    color: var(--rz-danger);
}

/* ===== PAGE HEADERS ===== */
.page-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;

    /* No TOP padding. This header always sits directly inside a RadzenCard, which
       already supplies its own padding — the two stacked, plus .page-title's own
       margin-bottom, leaving a conspicuous band of white space above every page
       title. Bottom padding kept to separate the title from the content below. */
    padding: 0 0 0.75rem 0;
}

.page-title {
    display: flex;
    align-items: center;
    justify-content: flex-start;
    gap: 1rem;
    height: 100%;
    min-height: 40px;

    /* No margin: .page-title is a flex ITEM of .page-header, which owns the
       spacing. Its own margin-bottom simply added to the header's padding. */
    margin: 0;
}

.page-title h1 {
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.5rem;
    font-weight: 600;
    color: var(--rz-text-color);
}

.page-icon {
    font-size: 1.5rem;
    color: var(--rz-primary);
    display: flex;
    align-items: center;
    line-height: 1;
}

.page-actions {
    display: flex;
    gap: 0.5rem;
    align-items: center;
}

/* ===== FILTER SECTIONS ===== */
/* Filter sections now use RadzenCard, keeping only layout classes */

.filter-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    flex-wrap: wrap;
    gap: 1rem;
}

.filter-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.filter-label {
    font-weight: 600;
    color: var(--rz-text-secondary-color);
    font-size: 0.875rem;
    white-space: nowrap;
    margin-right: 0.5rem;
}

.filter-buttons {
    display: flex;
    gap: 0.25rem;
    flex-wrap: wrap;
}

.search-group {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 300px;
}

/* ===== DATA GRIDS ===== */
.modern-data-grid {
    border-radius: 8px;
    overflow: hidden;
}

/* Improved row height and cell padding for better text wrapping */
.modern-data-grid .rz-datatable-data tr {
    min-height: 60px;
}

.modern-data-grid .rz-datatable-data td {
    vertical-align: top;
    padding: 12px 8px;
}

/* Better badge wrapping in data grids */
.modern-data-grid .rz-badge {
    white-space: normal !important;
    word-wrap: break-word !important;
    line-height: 1.3 !important;
    min-height: auto !important;
    display: inline-block !important;
}

/* Improved text wrapping for all data grid content */
.modern-data-grid .rz-datatable-data td > div {
    white-space: normal;
    word-wrap: break-word;
    line-height: 1.4;
}

/* Enhanced reason comment styling */
.modern-data-grid .rz-datatable-data td div[style*="border-left: 3px solid"] {
    border-left-color: var(--rz-primary) !important;
    background-color: color-mix(in srgb, var(--rz-panel-background-color) 92%, var(--rz-text-color) 8%) !important;
    max-width: 100%;
    box-sizing: border-box;
}

/* ===== EMPTY STATES ===== */
.empty-state {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 4rem 2rem;
    text-align: center;
    border: 2px dashed rgba(128, 128, 128, 0.3);
    border-radius: 12px;
    margin: 2rem;
}

.empty-state-icon {
    font-size: 4rem;
    margin-bottom: 1rem;
    color: var(--rz-text-disabled-color);
    opacity: 0.5;
}

.empty-state-title {
    font-size: 1.25rem;
    font-weight: 600;
    color: var(--rz-text-secondary-color);
    margin-bottom: 0.5rem;
}

.empty-state-description {
    font-size: 0.875rem;
    color: var(--rz-text-disabled-color);
    max-width: 400px;
    line-height: 1.5;
}

/* ===== LOADING STATES ===== */
.loading-container {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 3rem;
    gap: 1rem;
}

.loading-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid var(--rz-border-300);
    border-top: 3px solid var(--rz-primary);
    border-radius: 50%;
    animation: spin 1s linear infinite;
}

@keyframes spin {
    0% { transform: rotate(0deg); }
    100% { transform: rotate(360deg); }
}

/* ===== BUTTONS & CONTROLS ===== */
.button-group {
    display: flex;
    gap: 0.25rem;
}

/* ===== RESPONSIVE DESIGN ===== */
@media (max-width: 1200px) {
    .stats-grid {
        grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
    }
}

@media (max-width: 768px) {
    .page-container {
        padding: 0rem;
    }
    
    .stats-grid {
        grid-template-columns: 1fr;
        gap: 0.75rem;
    }
    
    .stat-card {
        padding: 1rem;
    }
    
    .filter-row {
        flex-direction: column;
        align-items: stretch;
    }
    
    .search-group {
        min-width: auto;
        width: 100%;
    }
    
    .page-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 1rem;
    }
    
    .card-header,
    .card-body {
        padding: 1rem;
    }
}

@media (max-width: 576px) {
    .page-title h1 {
        font-size: 1.5rem;
    }
    
    .stat-value {
        font-size: 1.5rem;
    }
    
    .modern-data-grid,
    .e-grid {
        font-size: 0.8rem !important;
    }
    
    .e-grid .e-headercell,
    .e-grid .e-rowcell {
        padding: 0.5rem !important;
        font-size: 0.8rem !important;
    }
}

/* ===== OVERLAY SYSTEM ===== */
/* Global overlay container for proper z-index layering */
.overlay-container {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    pointer-events: none;
    z-index: 10000;
}

.overlay-container > * {
    pointer-events: auto;
}

/* Profile dropdown overlay styling */
.profile-dropdown-portal {
    position: fixed !important;
    z-index: 10001 !important;
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15) !important;
    min-width: 280px;
    opacity: 1 !important;
    visibility: visible !important;
}

/* Sidebar overlay styling */
.sidebar-overlay-portal {
    position: fixed !important;
    top: 0 !important;
    left: 0 !important;
    right: 0 !important;
    bottom: 0 !important;
    background-color: rgba(0, 0, 0, 0.7) !important;
    z-index: 9999 !important;
    opacity: 1 !important;
    visibility: visible !important;
}

/* Force visibility for overlay elements */
.sidebar *,
.profile-dropdown *,
.profile-dropdown-portal *,
.sidebar-overlay-portal,
.overlay-container * {
    opacity: 1 !important;
    visibility: visible !important;
}

/* Special exceptions for elements that should have transparency */
.sidebar-overlay,
.sidebar-overlay-portal {
    opacity: 1 !important;
    background-color: rgba(0, 0, 0, 0.7) !important;
}

/* Note: Dark theme support is now automatic through Radzen theme-aware CSS variables */

/* ===== PRIORITY BADGES ===== */
.priority-badge {
    display: inline-block;
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    color: white;
    text-align: center;
    font-weight: 500;
    font-size: 0.75rem;
    min-width: 60px;
    text-transform: capitalize;
}

/* ── Clickable text ───────────────────────────────────────────────────────
   THE link treatment for text that navigates: primary colour + underline.

   Before this existed the same intent was expressed three ways — `text-primary`
   plus inline `cursor: pointer; text-decoration: underline`, the same thing
   fully inline, and a no-underline variant — so half the app's links were
   underlined and half were not. Colour alone is not a sufficient affordance,
   so underline is the standard and this class is the only place it is set.

   `patient-name-link` is the same treatment under the name CLAUDE.md documents
   for patient navigation; keep both so that convention resolves to real CSS. */
.clickable-text,
.patient-name-link {
    color: var(--rz-primary);
    text-decoration: underline;
    cursor: pointer;
}

/* ── Patient tab strip ────────────────────────────────────────────────────
   The navigation tabs live INSIDE the patient identity card rather than in a
   second card below it. The two used to square their facing corners and draw
   a border to look joined, but each still paid 20px of top and bottom padding
   — 40px of dead space at the seam, on the screen clinicians spend their day
   on.

   Same treatment as .metric-grid-embedded on the dashboard: negative margins
   bleed the strip to the card's edges so it does not sit in a box within a
   box, and one hairline separates identity from navigation.

   The divider is deliberately at FULL weight (0.28), not the 0.2 used for
   vertical rules elsewhere. A lone horizontal line surrounded by whitespace
   lands near 13% effective opacity at 0.667px device width and simply is not
   there; long vertical rules survive the same alpha because there is more of
   them to see. */
.patient-tab-strip {
    margin: 1rem -20px -20px -20px;
    padding: 0.75rem 20px;
    border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.28));
}

/* ── Action rows excluded from text selection ─────────────────────────────
   Radzen icon buttons render their icon as a LIGATURE: the markup is literally
   <i class="rzi">edit</i>, turned into a glyph by `font-family: Material Symbols`.
   So selecting a region of the page that contains a button row and copying it
   puts the words edit / delete / description / history on the clipboard, with
   the font-family inlined by the browser. Pasted into the journal editor they
   render as icons again — a convincing fake button row inside a clinical note.
   That is how journal 919630 got one.

   The paste sanitizer strips the font-family so this cannot land any more, but
   the words still come along in the copied text. Excluding action rows from
   selection stops it at the source: dragging across a journal now selects the
   note, not the toolbar underneath it.

   Buttons stay fully clickable — user-select governs selection, not events. */
.no-select-actions {
    user-select: none;
    -webkit-user-select: none;
}

/* ===== UTILITIES ===== */
.text-primary { color: var(--rz-primary) !important; }
.text-secondary { color: var(--rz-text-secondary-color) !important; }
.text-success { color: var(--rz-success) !important; }
.text-warning { color: var(--rz-warning) !important; }
.text-danger { color: var(--rz-danger) !important; }
.text-muted { color: var(--rz-text-disabled-color) !important; }
.red-foreground { color: var(--rz-danger) !important; }

.bg-primary { background-color: var(--rz-primary) !important; }
.bg-secondary { background-color: var(--rz-secondary) !important; }
.bg-success { background-color: var(--rz-success) !important; }
.bg-warning { background-color: var(--rz-warning) !important; }
.bg-danger { background-color: var(--rz-danger) !important; }

.rounded { border-radius: 8px !important; }
.rounded-lg { border-radius: 12px !important; }
.shadow-sm { box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1) !important; }
.shadow { box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15) !important; }

.mb-0 { margin-bottom: 0 !important; }
.mb-1 { margin-bottom: 0.25rem !important; }
.mb-2 { margin-bottom: 0.5rem !important; }
.mb-3 { margin-bottom: 1rem !important; }
.mb-4 { margin-bottom: 1.5rem !important; }

.p-0 { padding: 0 !important; }
.p-1 { padding: 0.25rem !important; }

/* ===== DEVICE ITEM TEMPLATE (for autocomplete dialogs) ===== */
.device-item {
    padding: 0.75rem;
    border-bottom: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    cursor: pointer;
    transition: background-color 0.2s ease;
}

.device-item:hover {
    background-color: var(--rz-panel-menu-item-background-color-hover);
}

.device-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}

.device-id-section {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.device-id {
    font-weight: 600;
    font-size: 1rem;
    color: var(--rz-text-color);
}

.device-details {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
    font-size: 0.875rem;
    color: var(--rz-text-secondary-color);
    margin-bottom: 0.5rem;
}

.device-details i {
    margin-right: 0.25rem;
}

.capabilities {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-bottom: 0.5rem;
}

.latest-vitals {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    font-size: 0.8125rem;
    color: var(--rz-text-secondary-color);
    margin-top: 0.5rem;
}
.p-2 { padding: 0.5rem !important; }
.p-3 { padding: 1rem !important; }
.p-4 { padding: 1.5rem !important; }

/* ===== TAB CONTENT CONTAINERS ===== */
.tab-content-container {
    /* Remove default card margins for direct content display */
    margin-top: 0;
    width: 100%;
}

/* ===== RADZEN DROPDOWN THEME FIX ===== */
/* Fix for RadzenDropdown items not inheriting proper theme colors */
.rz-dropdown-items li,
.rz-multiselect-items li,
.rz-dropdown-item,
.rz-multiselect-item {
    color: var(--rz-text-color) !important;
}

/* Ensure selected and hover states maintain their proper theme colors */
.rz-dropdown-items li:hover,
.rz-multiselect-items li:hover,
.rz-dropdown-item:hover,
.rz-multiselect-item:hover {
    color: var(--rz-dropdown-item-hover-color) !important;
}

.rz-dropdown-items li.rz-state-highlight,
.rz-multiselect-items li.rz-state-highlight,
.rz-dropdown-item.rz-state-highlight,
.rz-multiselect-item.rz-state-highlight {
    color: var(--rz-dropdown-item-selected-color) !important;
}

/* Ensure tab content components don't add extra margins */
.tab-content-container > * {
    margin-top: 0;
}

/* ============================================================================
   Bulk Vitals Entry dialog — single internal scroll region
   ----------------------------------------------------------------------------
   Radzen's .rz-dialog-content defaults to `flex: 0 1 auto; overflow: auto`,
   so a tall dialog body scrolls as a whole. That second scrollbar means the
   sticky table header (which only sticks within its own scroll container)
   and a focused bottom-row input can be pushed out of the viewport. Make the
   content area fill the fixed-height dialog and stop it scrolling; the
   component's own .vitals-table-scroll then becomes the only scroll region.
   ============================================================================ */
.bulk-vitals-dialog .rz-dialog-content {
    flex: 1 1 auto;
    min-height: 0;
    overflow: hidden;
    display: flex;
    flex-direction: column;
}
/* ── Journal author chip ──────────────────────────────────────────────────
   Wraps JournalAuthorDisplay so it reads as a badge among the RadzenBadges it
   sits beside (journal editor header, audit history summary row).

   It borrows RADZEN'S OWN badge classes rather than reimplementing them —
   rz-badge rz-badge-light rz-variant-filled rz-shade-default — so it tracks the
   theme automatically. An earlier hand-rolled version used
   `border: 1px solid var(--rz-border-color)`, and that variable does not exist in
   this theme: the declaration was invalid, CSS dropped it, and no box rendered at
   all while padding and radius still applied. Hence: use the framework's classes,
   not guessed variable names.

   A RadzenBadge component cannot be used directly — it takes a plain Text string,
   and this content is an icon plus optional "authored by <consultant>" markup. */
.author-badge {
    display: inline-flex;
    align-items: center;
    text-transform: none;   /* badges uppercase by default; personal names must not */
}

/* JournalAuthorDisplay's root span sets display/gap as an INLINE style, which beats
   any class selector — re-assert the gap so the icon sits tight against the name. */
.author-badge .journal-author-display {
    gap: 0.3rem !important;
}

/* ── Metric strip ─────────────────────────────────────────────────────────
   One quiet surface for derived figures, replacing the per-tab "hero" cards
   (filled --rz-*-lighter backgrounds, 4px left borders, 2rem icons).

   The old design spent four saturated colours on figures that carried no
   status — longest-stay was rendered in danger red purely for variety, which
   erodes red where it has to mean attention. Here the hierarchy is carried by
   SIZE and CONTRAST alone: the number is large and full-contrast, the label
   small, secondary and letter-spaced. Colour is reserved for the trend arrow,
   the one element that is actually a signal.

   Theme-aware only: --rz-* variables, no hardcoded colours. */
.metric-strip {
    /* No horizontal padding: the strip sits inside the filter card and must align
       flush with the tab buttons above and the filters below it. Side padding
       indented it out of that column. */
    padding: 0.875rem 0;
}

.metric-row {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 2.5rem;
}

/* Hairline separators instead of five bordered boxes. Drawn as a left border on
   siblings so the first metric has none and wrapping never leaves a stray rule. */
.metric + .metric {
    padding-left: 2.5rem;
    border-left: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
}

.metric-value {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.2;
    color: var(--rz-text-color);
    white-space: nowrap;
}

.metric-label {
    margin-top: 0.125rem;
    font-size: 0.75rem;
    font-weight: 500;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--rz-text-secondary-color);
}

/* Secondary detail (this week / last week) — present for whoever wants it,
   recessive enough not to compete with the figure above it. */
.metric-sub {
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--rz-text-secondary-color);
    opacity: 0.85;
    white-space: nowrap;
}

.metric-trend {
    font-size: 0.8rem;
    margin-left: 0.35rem;
    vertical-align: middle;
}

/* Clinic split — proportional bars, one hue.
   Each bar is labelled by the clinic beside it, so there is no legend to decode,
   and lengths share a common baseline (easier to compare than a donut's arcs).
   Lives inside .metric-row as another .metric, so it wraps with the figures. */
.metric-clinics {
    /* Never let the bars stretch: they carry meaning by LENGTH. */
    flex: none;
}

.clinic-list {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-top: 0.3rem;
}

.clinic-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.8125rem;
    line-height: 1.3;
    white-space: nowrap;
}

.clinic-track {
    width: 56px;
    height: 5px;
    border-radius: 3px;
    background: var(--rz-border-color, rgba(128, 128, 128, 0.2));
    flex: none;
    overflow: hidden;
}

.clinic-fill {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--rz-primary);
}

.clinic-name { color: var(--rz-text-color); }

.clinic-count {
    color: var(--rz-text-secondary-color);
    font-variant-numeric: tabular-nums;
}

/* Narrow viewports: drop the rules and tighten the gaps rather than letting
   four metrics wrap into a ragged column with dangling separators. */
@media (max-width: 768px) {
    .metric-row {
        gap: 1.25rem;
    }

    .metric + .metric {
        padding-left: 0;
        border-left: none;
    }
}

/* ── Dashboard metric grid ────────────────────────────────────────────────
   One neutral row of figures, replacing six pastel "hero" cards that used
   filled --rz-*-lighter backgrounds with 4px left borders and 2rem icons.

   Two things the old cards got wrong beyond looking dated: two of the six
   NAVIGATED with nothing to say so, and six saturated colours competed so the
   one card that means "act on me" carried no more weight than a zero.

   Here colour is spent ONCE, on the alert. Everything else is carried by size
   and contrast, so the eye lands on what needs attention.

   Theme-aware only: --rz-* variables, no hardcoded colours. */
.metric-grid {
    display: grid;
    /* Explicit counts, not auto-fit. auto-fit picks the largest number of
       columns that fits, which lands on FIVE across a wide band of laptop
       widths (~860-1090px) and leaves the sixth cell orphaned on its own row
       beside a long empty gap. Six divides evenly only by 6, 3 and 2, so those
       are the only counts allowed to occur. */
    grid-template-columns: repeat(6, 1fr);

    /* The grid carries the PANEL colour, not the hairline colour, and each cell
       draws its own top/left rule (negated by the outer border via the -1px
       margins below). The obvious alternative — a 1px gap over a hairline-
       coloured background — is one line shorter but breaks on a partially
       filled last row: cells paint their own background, so any track without
       a cell showed as a solid grey band beside the orphan. */
    background: var(--rz-panel-background-color, #fff);
    border: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    border-radius: var(--rz-border-radius, 4px);
    overflow: hidden;
}

/* Embedded variant — the grid sits INSIDE a RadzenCard rather than standing alone.

   The card has no border of its own (just a soft shadow) and 20px of padding, so
   a grid that kept its own 1px border would put the only hard edge on the page a
   few pixels inside the card's soft one — a box drawn inside a box. Instead the
   grid drops its shell entirely and bleeds out to the card's edges, letting the
   card define the boundary and the cells' own top rules draw the single hairline
   that separates the hospital identity above from the figures below.

   The -20px side/bottom margins cancel the card's padding. They are tied to that
   20px: if the card's padding changes these must follow, which is why the value
   is stated here rather than hidden in a variable that reads as arbitrary. */
.metric-grid-embedded {
    border: 0;
    border-radius: 0;
    margin: 1rem -20px -20px -20px;

    /* The one edge kept — see the note on the divider below. */
    border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.28));
}

/* The bled grid runs to the card's square edges, so the card must clip it back
   to its own 4px radius — otherwise the bottom cells' corners poke past the
   rounded corner. */
.dashboard-header-card {
    overflow: hidden;
}

/* The divider between the hospital identity and the figures gets its OWN rule,
   rather than relying on the cells' border-top.

   Those cell borders do render — but at --rz-border-color's 20% alpha over a
   sub-pixel (0.667px) line they came out invisible in practice. The vertical
   dividers survive that because they are long enough for the faint colour to
   register; a single horizontal line surrounded by whitespace does not. This
   draws it at full pixel weight so the separation actually reads, which is the
   entire point of embedding the strip rather than stacking two cards.

   The rule itself lives in the .metric-grid-embedded block above. Because the
   grid now owns that line, the cells must NOT also draw their own top border —
   otherwise a second faint line stacks against it. */
.metric-grid-embedded .metric-cell {
    border-top: 0;
    margin-top: 0;
}

/* ...but rows BELOW the first still need a rule between them, or the 3-column
   and 2-column layouts lose their horizontal dividers entirely. Only the first
   row sits against the grid's own border-top, so restore it for the rest.
   Counts match the column counts at each breakpoint. */
.metric-grid-embedded .metric-cell:nth-child(n + 7) {
    border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
}

@media (max-width: 1090px) {
    .metric-grid-embedded .metric-cell:nth-child(n + 4) {
        border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    }
}

@media (max-width: 640px) {
    .metric-grid-embedded .metric-cell:nth-child(n + 3) {
        border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    }
}

/* Kill the leftmost column's left rule: with the grid bled to the card edge it
   would sit flush against the card's own edge as a stray vertical tick. */
.metric-grid-embedded .metric-cell:nth-child(6n + 1) {
    border-left: 0;
    margin-left: 0;
}

@media (max-width: 1090px) {
    .metric-grid-embedded .metric-cell:nth-child(6n + 1) {
        border-left: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
        margin-left: -1px;
    }
    .metric-grid-embedded .metric-cell:nth-child(3n + 1) {
        border-left: 0;
        margin-left: 0;
    }
}

@media (max-width: 640px) {
    .metric-grid-embedded .metric-cell:nth-child(3n + 1) {
        border-left: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
        margin-left: -1px;
    }
    .metric-grid-embedded .metric-cell:nth-child(2n + 1) {
        border-left: 0;
        margin-left: 0;
    }
}

/* 6 → 3 → 2. Never 5, 4 or 1: those leave a partly-filled final row.
   1090px is where six cells stop clearing ~150px of usable width inside the
   dashboard's content column; 640px is where three stop. */
@media (max-width: 1090px) {
    .metric-grid { grid-template-columns: repeat(3, 1fr); }
}

@media (max-width: 640px) {
    .metric-grid { grid-template-columns: repeat(2, 1fr); }
}

.metric-cell {
    background: var(--rz-panel-background-color, #fff);
    padding: 0.875rem 1rem;
    position: relative;

    /* Each cell draws its own top and left rule; the negative margins pull
       those rules onto the grid's own border so the outer edge stays 1px
       rather than doubling. Cells that wrap to a second row keep their top
       rule, which is what continues the hairline across a short final row. */
    border-top: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    border-left: 1px solid var(--rz-border-color, rgba(128, 128, 128, 0.2));
    margin-top: -1px;
    margin-left: -1px;
}

/* Clickable cells must LOOK clickable — the previous build navigated from two
   cards with no affordance at all. */
.metric-cell-link {
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    display: block;
    transition: background-color 0.12s ease;
}

.metric-cell-link::after {
    content: "\203A";                 /* › */
    position: absolute;
    top: 0.7rem;
    right: 0.85rem;
    font-size: 1rem;
    line-height: 1;
    color: var(--rz-text-secondary-color);
    opacity: 0;
    transition: opacity 0.12s ease, transform 0.12s ease;
}

/* --rz-base-200 is NOT theme-aware: Radzen ships it near-white in the dark themes
   too (software-dark and standard-dark are #e9edf0 / #e1e2e3, the same values as
   their light counterparts), so it painted a near-white tile on a dark panel.
   Mixing toward --rz-text-color inverts with the theme instead — darkens in light,
   lightens in dark — from one rule. */
.metric-cell-link:hover {
    background: color-mix(in srgb, var(--rz-panel-background-color) 92%, var(--rz-text-color) 8%);
}

.metric-cell-link:hover::after {
    opacity: 1;
    transform: translateX(2px);
}

.metric-cell-link:focus-visible {
    outline: 2px solid var(--rz-primary);
    outline-offset: -2px;
}

.metric-cell-value {
    font-size: 1.5rem;
    font-weight: 600;
    line-height: 1.15;
    color: var(--rz-text-color);
    font-variant-numeric: tabular-nums;
}

/* "Nothing happened today" should not read as loudly as "93 patients are here".

   Opacity rather than --rz-text-secondary-color: in the dark themes that token
   (#dadfe2) sits almost on top of the primary text (#f6f7fa), so a colour swap
   produced no visible de-emphasis at all. Fading the primary colour keeps the
   same relationship on both grounds. */
.metric-cell-value.is-zero {
    opacity: 0.55;
    font-weight: 500;
}

.metric-cell-label {
    margin-top: 0.1rem;
    font-size: 0.6875rem;
    font-weight: 500;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    color: var(--rz-text-secondary-color);
}

.metric-cell-sub {
    margin-top: 0.25rem;
    font-size: 0.75rem;
    color: var(--rz-text-secondary-color);
    opacity: 0.85;
    font-variant-numeric: tabular-nums;
}

/* The one cell allowed to carry colour. Applied only when the count is > 0, so
   an empty queue stays quiet rather than showing a permanent red panel.

   Deliberately the palest of the treatments we compared: the tint is a hint
   rather than a panel, and the number is pulled back off full danger red. It
   is still the ONLY colour in the grid, which is what makes it findable — it
   doesn't need saturation on top of that, and full red on a clinical dashboard
   reads as a patient alarm rather than an admin backlog.

   color-mix keeps both derived from --rz-danger rather than hardcoding a hex,
   so they track the active theme. The rgba() fallbacks apply only where
   color-mix is unsupported. */
.metric-cell-alert {
    background: rgba(224, 82, 82, 0.08);
    background: color-mix(in srgb, var(--rz-danger) 8%, transparent);
}

.metric-cell-alert .metric-cell-value,
.metric-cell-alert .metric-cell-label {
    color: var(--rz-danger);
    color: color-mix(in srgb, var(--rz-danger) 85%, var(--rz-text-color));
}

/* On the alert cell the chevron and hover tint follow the alert colour rather
   than the neutral grey, so the affordance doesn't fight the pink ground. */
.metric-cell-alert.metric-cell-link::after {
    color: var(--rz-danger);
    color: color-mix(in srgb, var(--rz-danger) 85%, var(--rz-text-color));
}

.metric-cell-alert.metric-cell-link:hover {
    background: rgba(224, 82, 82, 0.14);
    background: color-mix(in srgb, var(--rz-danger) 14%, transparent);
}

.metric-alert-dot {
    display: inline-block;
    width: 6px;
    height: 6px;
    border-radius: 50%;
    /* Matches the softened number rather than staying full-strength, so the
       dot doesn't end up the most saturated thing in the cell. */
    background: var(--rz-danger);
    background: color-mix(in srgb, var(--rz-danger) 85%, var(--rz-text-color));
    margin-right: 0.35rem;
    vertical-align: 0.28em;
}
