/* =====================================================================
   app.css — HarmonyPx brand tokens + shell + auth pages.
   Token prefix: --px-*. Radzen material-base.css loads first
   (see index.html); this layers on top. Design mirrors HarmonyRx's
   auth shell (split soft-oval card) rebranded for the PhilHealth
   YAKAP / Konsulta program.
   ===================================================================== */

:root {
    /* Brand palette — rose/red, from the official HarmonyPx mark
       (References/brand/harmony-px-stetho.svg: #e11d48 → #fb7185). */
    --px-primary: #e11d48; /* Buttons, links, spinners, active state — rose-600 */
    --px-accent:  #fb7185; /* Gradients, highlights — rose-400 */
    --px-deep:    #9f1239; /* Chrome — dense headings, sidebar, footer — rose-800 */
    --px-ink:     #263238; /* Body text */
    --px-surface: #fef2f4; /* Page background — faint rose */
    --px-border:  #f6dce1; /* Hairlines */

    --px-shadow:    0 1px 2px rgba(15, 23, 42, .04), 0 2px 4px rgba(15, 23, 42, .04);
    --px-shadow-lg: 0 4px 12px rgba(15, 23, 42, .08), 0 1px 2px rgba(15, 23, 42, .06);

    --px-gradient:       linear-gradient(90deg, var(--px-primary) 0%, var(--px-accent) 100%);
    --px-gradient-brand: linear-gradient(135deg, var(--px-deep) 0%, var(--px-primary) 55%, var(--px-accent) 100%);

    /* Raised surfaces that sit ON the page background: the auth card, the notification panel, the
       bell rows. These were hardcoded #fff, which is the one thing that cannot survive a dark theme,
       so they are tokens now and the [data-theme="dark"] block below is the only place that changes. */
    --px-panel:        #ffffff; /* card / panel background */
    --px-panel-ink:    var(--px-ink);
    --px-panel-border: #f0f0f0;
    --px-panel-muted:  #666666; /* secondary text inside a panel */
    --px-panel-faint:  #999999; /* tertiary text: timestamps, empty states */
    --px-warn-surface: #fff8e1; /* the unhandled-error bar */
}

/* Map Radzen's primary palette to the brand teal so ALL Radzen components
   (buttons, links, focus rings, active nav, spinners, checkboxes) follow the
   brand. app.css loads after material-base.css, so these :root values win. */
:root {
    --rz-primary:         #e11d48;
    --rz-primary-light:   #f43f5e;
    --rz-primary-lighter: #fecdd3;
    --rz-primary-dark:    #be123c;
    --rz-primary-darker:  #9f1239;
    --rz-on-primary:      #ffffff;
    --rz-body-background-color: var(--px-surface);
}

/* Muted caption / description text (tab intro lines, hints). Uses Radzen's secondary
   TEXT color so it reads as subtle grey. Deliberately NOT rz-color-secondary, which is
   the pink brand ACCENT color and was being misused for muted captions. */
.px-muted {
    color: var(--rz-text-secondary-color);
}

html, body {
    margin: 0;
    padding: 0;
}
body {
    background: var(--px-surface);
    color: var(--px-ink);
}

/* Blazor unhandled-error banner (#blazor-error-ui lives in index.html). It MUST
   be hidden by default — Blazor un-hides it (inline display:block) only on a real
   unhandled exception. Without this rule the banner shows permanently. */
#blazor-error-ui {
    display: none;
    position: fixed;
    bottom: 0;
    left: 0;
    width: 100%;
    z-index: 1000;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    background: var(--px-warn-surface);
    color: var(--px-panel-ink, #263238);
    box-shadow: 0 -1px 4px rgba(0, 0, 0, 0.2);
}
#blazor-error-ui .reload {
    color: var(--px-primary, #e11d48);
    margin-left: 0.5rem;
}
#blazor-error-ui .dismiss {
    cursor: pointer;
    position: absolute;
    right: 0.9rem;
    top: 0.55rem;
}

/* App-shell header uses the brand gradient. */
.rz-header {
    background: var(--px-gradient);
    color: #fff;
}
.rz-header .rz-label,
.rz-header .rz-button .rzi {
    color: #fff;
}

/* =====================================================================
   Auth pages (login / forgot-password / reset-password / select-org).
   One unified soft-oval card holds the split: gradient brand half (left)
   + form half (right), floating on a faint brand-tinted backdrop.
   Markup lives in Layout/LoginLayout.razor.
   ===================================================================== */

.px-auth {
    box-sizing: border-box;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    padding: 2rem 1.25rem;
    /* Faint brand-tinted wash so the card lifts off the page. */
    background:
        radial-gradient(circle at 22% 18%, rgba(225, 29, 72, .12), transparent 55%),
        radial-gradient(circle at 82% 88%, rgba(251, 113, 133, .16), transparent 52%),
        var(--px-surface);
}

/* The soft-oval shell — large radius, clips both halves to the curve. */
.px-auth__shell {
    display: grid;
    grid-template-columns: 1.05fr .95fr;
    width: 100%;
    max-width: 60rem;
    min-height: 33rem;
    background: var(--px-panel);
    border-radius: 2.75rem;
    overflow: hidden;
    box-shadow: 0 24px 60px rgba(15, 23, 42, .14), 0 4px 14px rgba(15, 23, 42, .08);
}

/* ---- Left: brand half ---- */
.px-auth__brand {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    padding: 3.25rem 3rem;
    color: #fff;
    background: var(--px-gradient-brand);
    overflow: hidden;
}
.px-auth__brand::before {
    content: "";
    position: absolute;
    inset: 0;
    background:
        radial-gradient(circle at 85% 12%, rgba(255, 255, 255, .12), transparent 42%),
        radial-gradient(circle at 8% 92%, rgba(255, 255, 255, .08), transparent 38%);
}
.px-auth__brand-content {
    position: relative;
    z-index: 1;
    max-width: 26rem;
}
.px-auth__logo {
    display: flex;
    align-items: center;
    gap: .65rem;
    margin-bottom: 2.5rem;
}
.px-auth__logo-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.75rem;
    height: 2.75rem;
    border-radius: .85rem;
    background: rgba(255, 255, 255, .15);
}
.px-auth__logo-mark svg {
    width: 1.75rem;
    height: 1.75rem;
}
/* When the mark holds the official app icon, drop the translucent chip and
   let the icon tile fill the square (its own rounded corners show through). */
.px-auth__logo-mark--icon {
    background: transparent;
    padding: 0;
    overflow: hidden;
}
.px-auth__logo-mark--icon img {
    width: 100%;
    height: 100%;
    display: block;
    border-radius: inherit;
}
.px-auth__logo-text {
    font-size: 1.4rem;
    font-weight: 700;
    letter-spacing: .01em;
}
.px-auth__headline {
    font-size: 2.1rem;
    line-height: 1.18;
    font-weight: 700;
    margin: 0 0 1rem;
}
.px-auth__tagline {
    font-size: 1rem;
    line-height: 1.6;
    opacity: .85;
    margin: 0 0 1.9rem;
}
.px-auth__features {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: .65rem;
}
.px-auth__features li {
    position: relative;
    padding-left: 1.7rem;
    opacity: .92;
    font-size: .95rem;
}
.px-auth__features li::before {
    content: "✓";
    position: absolute;
    left: 0;
    font-weight: 700;
}
.px-auth__brand-footer {
    position: relative;
    z-index: 1;
    font-size: .8rem;
    opacity: .7;
}

/* ---- Right: form half ---- */
.px-auth__panel {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem 2.75rem;
    background: var(--px-panel);
}
.px-auth__form {
    width: 100%;
    max-width: 21rem;
}
.px-auth__head {
    margin-bottom: 1.75rem;
}
.px-auth__title {
    font-weight: 700;
    margin: 0;
}
.px-auth__subtitle {
    color: #6c757d;
    margin-top: .35rem;
}

/* Stretch Radzen form controls to the form width. */
.px-auth__form .rz-form-field,
.px-auth__form .rz-textbox,
.px-auth__form .rz-password {
    width: 100%;
}
.px-auth__form .rz-button.px-auth__submit {
    width: 100%;
}

/* ---- Responsive: collapse to a single rounded card ---- */
@media (max-width: 900px) {
    .px-auth {
        padding: 1.25rem;
    }
    .px-auth__shell {
        grid-template-columns: 1fr;
        max-width: 26rem;
        min-height: 0;
        border-radius: 2rem;
    }
    .px-auth__brand {
        display: none;
    }
    .px-auth__panel {
        padding: 2.5rem 2rem;
    }
}

/* =====================================================================
   App boot loading screen (index.html #app placeholder, shown until
   Blazor WASM starts). Uses the official animated loading mark.
   ===================================================================== */
.px-loading {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
    font-family: "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
}
.px-loading__mark {
    width: 96px;
    height: 96px;
    filter: drop-shadow(0 6px 16px rgba(225, 29, 72, .25));
}
.px-loading__text {
    font-size: .95rem;
    font-weight: 600;
    letter-spacing: .01em;
    color: var(--px-deep);
}

/* In-app mini loader (HarmonyLoader.razor) — route gates, cards, dialogs. */
.px-loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    padding: 2rem 1rem;
}
.px-loader__mark {
    filter: drop-shadow(0 4px 10px rgba(225, 29, 72, .2));
}
.px-loader__text {
    font-size: .85rem;
    font-weight: 600;
    color: var(--px-deep, #9f1239);
}

/* =====================================================================
   Application header (MainLayout top nav)
   ===================================================================== */
.px-header {
    width: 100%;
}
.px-header__brand {
    font-weight: 600;
    letter-spacing: 0.2px;
    color: #fff;
}

/* Keep every header foreground element white over the brand gradient. */
.px-header a,
.px-header .rz-link,
.px-header .rz-navigation-item-link,
.px-header .rz-navigation-item-text,
.px-header .rz-navigation-item-icon,
.px-header .rzi,
.px-header .rz-button .rzi { color: #fff; }

/* Current-facility link (clickable → /select-organization). */
.px-header__org.rz-link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.25rem 0.7rem;
    border-radius: 999px;
    background: rgba(255, 255, 255, 0.16);
    font-weight: 600;
    max-width: 18rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    transition: background 0.15s ease;
}
.px-header__org.rz-link:hover { background: rgba(255, 255, 255, 0.28); }

/* User menu over the gradient — drop RadzenMenu's own panel chrome. */
.px-header__menu, .px-header__menu .rz-menu { background: transparent; }
.px-header__menu .rz-navigation-item-wrapper { font-weight: 600; }
/* The dropdown submenu floats on a white surface — restore dark text there. */
.px-header__menu .rz-navigation-menu .rz-navigation-item-link,
.px-header__menu .rz-navigation-menu .rz-navigation-item-text,
.px-header__menu .rz-navigation-menu .rzi { color: var(--px-ink, #263238); }

/* ---- Notification bell (NotificationBell.razor) ---- */
.px-bell-container { position: relative; display: inline-flex; align-items: center; }
.px-bell-btn { color: #fff; }
.px-bell__badge {
    position: absolute;
    top: -4px;
    right: -4px;
    min-width: 16px;
    height: 16px;
    padding: 0 4px;
    font-size: 10px;
    line-height: 16px;
    border-radius: 999px;
}
.px-bell-panel {
    position: absolute;
    top: 42px;
    right: 0;
    width: 360px;
    background: var(--px-panel);
    color: var(--px-panel-ink, #263238);
    border-radius: 8px;
    box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
    z-index: 9999;
    overflow: hidden;
}
.px-bell-panel__head {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 12px 16px;
    background: var(--px-primary, #e11d48);
    color: #fff;
    font-size: 14px;
}
.px-bell-panel__list { max-height: 400px; overflow-y: auto; }
.px-bell-panel__empty { padding: 20px; text-align: center; color: var(--px-panel-faint); font-size: 13px; }
.px-bell-item {
    display: flex;
    gap: 10px;
    align-items: flex-start;
    padding: 12px 16px;
    border-bottom: 1px solid var(--px-panel-border);
    cursor: pointer;
    background: var(--px-panel);
}
.px-bell-item.is-unread { background: var(--px-surface, #fef2f4); }
.px-bell-item__body { flex: 1; min-width: 0; }
.px-bell-item__title { font-weight: 600; font-size: 13px; color: var(--px-panel-ink); }
.px-bell-item.is-unread .px-bell-item__title { font-weight: 700; }
.px-bell-item__msg { font-size: 12px; color: var(--px-panel-muted); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.px-bell-item__time { font-size: 11px; color: var(--px-panel-faint); margin-top: 2px; }

/* NavBar menu search (mirrors HarmonyHR) */
.search-container {
    padding: 8px;
    background-color: #f9fafb;
    border-bottom: 1px solid #e5e7eb;
}
.search-box-wrapper {
    position: relative;
    width: 100%;
    display: flex;
    align-items: center;
}
.search-box-wrapper .rz-textbox {
    width: 100%;
    padding: 8px 32px 8px 12px;
    border-radius: 4px;
    border: 1px solid #d1d5db;
    background-color: #fff;
}
.search-box-wrapper .rz-button {
    background-color: transparent;
    border: none;
    padding: 4px;
    margin: 0;
}
.search-box-wrapper .rz-button:hover {
    background-color: #f3f4f6;
    border-radius: 4px;
}

/* Grid toolbar (HeaderTemplate) buttons: keep labels on one line.
   With the bulk-upload actions moved up to the page header title row, the grid
   header shares its flex row between the Add button, the grouping drop area and
   the column picker — long labels like "Add New Adjustment Category" otherwise
   wrap to two lines and the button grows to double height. */
.rz-datatable-header .rz-custom-header .rz-button,
.rz-data-grid .rz-custom-header .rz-button {
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── Visual fit (2026-09-15, .omc/plans/visual-fit-test-plan.md) ─────────────────────────────── */

/* Tab strips wrap onto a second line instead of running past the card edge, where the last tabs
   were unreachable without a horizontal scroll (Diagnostic Results has 16 tabs). */
.rz-tabview-nav { flex-wrap: wrap; }

/* Floating label over a dropdown that shows a value it did not load itself. PatientPicker (LoadData
   dropdown) is marked rz-state-empty when its Value is set programmatically before the matching item
   is loaded, so Radzen keeps the FormField label in the resting position, drawn over the value text
   ("Patient" overprinting "Mendoza, Carlos"). When the dropdown label is a real value (not the
   placeholder), float the label exactly as Radzen does for a non-empty input. */
.rz-form-field .rz-dropdown.rz-state-empty:has(.rz-dropdown-label:not(.rz-placeholder)) ~ .rz-form-field-label {
    inset-inline-start: var(--rz-form-field-label-inset-inline-start);
    inset-inline-end: auto;
    inset-block-start: var(--rz-form-field-label-floating-top);
    padding-block-start: 0;
    padding-block-end: 0;
    transform: translate(0, 0);
    color: var(--rz-input-placeholder-color);
    background-color: var(--rz-form-field-label-floating-background-color);
    font-size: .75rem;
    line-height: 1rem;
    max-width: calc(100% - 1.5rem);
}

/* A read-only input that merely has focus must not look like a validation error.

   A dialog focuses its first focusable control on open, and in a *view* dialog that control is a
   read-only field. Radzen's focus ring in this theme is literally drawn in the DANGER colour -
   `--rz-input-focus-shadow: inset 0 0 0 1px var(--rz-danger)` - and a floating label switches to
   `--rz-form-field-label-focus-color: var(--rz-primary)`, the same red. So the first field of a view
   dialog announces itself as "this one is wrong" (visual-fit run 3, recurring note N4).

   Neutralised by redefining the custom properties that those vendor rules read. The field stays
   focusable, so its value can still be selected and copied with the keyboard.

   STATUS: verified fixed for the DESIGN 10.5 view skeleton (a bare RadzenTextBox in a column, no
   .rz-form-field ancestor) - a computed-style probe of the Accreditation view dialog finds no danger
   or primary colour anywhere. NOT yet resolved for the clinical panel view dialogs, which wrap the
   field in a RadzenFormField: those still render the red ring. Ruled out so far - the served CSS is
   current, the crawler's Chromium (149) supports :has(), and these same rules DO neutralise an
   isolated copy of that exact FormField DOM. The remaining difference has to be in how Radzen renders
   the real component, and it needs the harness's synthetic-row injection to reproduce. */
input[readonly],
textarea[readonly] {
    --rz-input-focus-shadow: none;
    --rz-input-focus-outline: none;
    --rz-input-focus-border: var(--rz-input-border);
}
.rz-form-field:has(input[readonly]),
.rz-form-field:has(textarea[readonly]) {
    --rz-form-field-focus-shadow: none;
    --rz-form-field-label-focus-color: var(--rz-form-field-label-color);
}

/* ============================================================================
   DARK MODE
   Activated by `data-theme="dark"` on <html>. Two halves work together:
     * Radzen's own components follow its dark stylesheet - index.html swaps
       material-base.css for material-dark-base.css on the <link id="rz-theme">.
     * Everything in THIS file follows the tokens redefined below.
   Both are applied by js/theme.js before Blazor boots, so there is no flash of
   the light theme on load and it works on the pre-auth pages too.

   The brand rose is deliberately kept: it carries the product identity and has
   enough contrast on a dark surface. What changes is the page and panel
   surfaces, the ink, and the hairlines.
   ============================================================================ */
:root[data-theme="dark"] {
    --px-ink:     #e5e7eb; /* body text on dark */
    --px-surface: #16181d; /* page background */
    --px-border:  #2b2f37; /* hairlines */

    --px-panel:        #1e2129;
    --px-panel-ink:    #e5e7eb;
    --px-panel-border: #2b2f37;
    --px-panel-muted:  #a6adba;
    --px-panel-faint:  #8b93a1;
    --px-warn-surface: #3a3320; /* error bar: amber, darkened */

    /* Shadows need more weight on a dark surface to read at all. */
    --px-shadow:    0 1px 2px rgba(0, 0, 0, .40), 0 2px 4px rgba(0, 0, 0, .32);
    --px-shadow-lg: 0 4px 12px rgba(0, 0, 0, .50), 0 1px 2px rgba(0, 0, 0, .40);

    /* Keep the brand hue but lift it slightly - #e11d48 on near-black is dim. */
    --rz-primary:         #f43f5e;
    --rz-primary-light:   #fb7185;
    --rz-primary-lighter: #4c1d29;
    --rz-primary-dark:    #e11d48;
    --rz-primary-darker:  #be123c;
    --rz-body-background-color: var(--px-surface);

    /* Radzen's LIGHT theme happens to define secondary as brand pink (#e31c65), so the app leans on
       rz-secondary for its row actions (the view buttons). Its DARK theme defines secondary as TEAL,
       which turned those buttons teal and broke the brand the moment dark mode was switched on. Pin
       the secondary ramp to the same rose family, lifted for contrast exactly like primary above. */
    --rz-secondary:         #e94984;
    --rz-secondary-light:   #ef6f9d;
    --rz-secondary-lighter: rgba(233, 73, 132, .16);
    --rz-secondary-dark:    #e31c65;
    --rz-secondary-darker:  #b61651;
    --rz-on-secondary:      #ffffff;
}

/* The auth card's right half and the loading splash sit directly on the page. */
:root[data-theme="dark"] body { background: var(--px-surface); color: var(--px-ink); }
:root[data-theme="dark"] .px-loading { background: var(--px-surface); }
:root[data-theme="dark"] .px-loading__text,
:root[data-theme="dark"] .px-loader__text { color: var(--px-panel-muted); }

/* The auth shell keeps its brand gradient on the left half; only the form half flips. */
:root[data-theme="dark"] .px-auth__shell {
    box-shadow: 0 24px 60px rgba(0, 0, 0, .55), 0 4px 14px rgba(0, 0, 0, .40);
}

/* Radzen's dark sheet handles its own components, but the app overrides a few
   Radzen surfaces in this file; re-point those at the dark tokens. */
:root[data-theme="dark"] .search-box-wrapper .rz-textbox {
    background: var(--px-panel);
    color: var(--px-panel-ink);
}

/* ---- Theme toggle ---------------------------------------------------------
   Two placements: on the brand gradient in the app header, and floating over
   the auth backdrop where there is no header to sit in. */
.px-theme-toggle { color: var(--px-panel-muted); }
.px-theme-toggle .rzi { font-size: 1.25rem; }

/* On the header gradient every foreground element is white (see .px-header rules). */
.px-theme-toggle--on-brand,
.px-theme-toggle--on-brand .rzi { color: #fff; }
.px-theme-toggle--on-brand:hover { background: rgba(255, 255, 255, .16); }

/* Auth pages: top-right of the backdrop, clear of the card. */
.px-auth__theme {
    position: absolute;
    top: 1.25rem;
    right: 1.5rem;
    z-index: 2;
}
.px-auth { position: relative; }

/* A page-header title row that carries the Master Data Scope banner inline (the Patients profile
   page, which has no grid header to hang the bulk-upload toolbar on). The banner's own rz-my-2
   margins would add a row's worth of height to a page already sized to the 1366x768 gate viewport;
   the .master-scope-banner class exists so a host can do exactly this. */
.px-page-header .master-scope-banner {
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    flex: 1 1 auto;
    min-width: 0;
}

/* §9.5 detail template inside a grid that scrolls horizontally (e.g. the patient-profile Sponsors tab,
   ~670px wide while its table runs past 1000px): without this the expanded row's content is laid out
   at the full TABLE width and its right half sits off-screen until the user scrolls. The scroll
   viewport becomes a size container, the template is sized to it (100cqw = the visible width, minus
   the cell padding) and pinned to its left edge, so the Info tab is read at the grid's visible width
   wherever the columns are scrolled to. Opt in per grid with class="px-fit-detail". */
.px-fit-detail .rz-data-grid-data {
    container-type: inline-size;
}
/* Radzen clips every cell (overflow: hidden); on the expanded row's cell that would make the CELL the
   sticky element's scroll container, so the template could never follow the grid's horizontal scroll. */
.px-fit-detail .rz-expanded-row-content > td {
    overflow: visible;
}
.px-fit-detail .rz-expanded-row-content > td > .rz-expanded-row-template {
    position: sticky;
    left: 0;
    width: calc(100cqw - 16px);
    max-width: calc(100cqw - 16px);
    box-sizing: border-box;
}
