/* /Components/AppErrorBoundary.razor.rz.scp.css */
/* Error boundary surface.

   This was an inline <style> block in the component. Two problems with that:
   it declared bare `h2` and `p` rules, which are not scoped and restyled every
   heading and paragraph in the app the moment the boundary rendered; and it
   hard-coded a light palette (#f8fafc page, white card, #1e293b text), so the
   error screen was a white slab on a dark theme — at the exact moment the user
   most needs to read it. Both fixed by moving here and using the tokens. */

.error-container[b-p1xnf1glop] {
    display: flex;
    justify-content: center;
    align-items: center;
    min-height: 100vh;
    padding: var(--pt-space-8);
    background: var(--pt-bg-page);
}

.error-card[b-p1xnf1glop] {
    max-width: 800px;
    background: var(--pt-bg-surface);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-lg);
    padding: var(--pt-space-8);
    box-shadow: var(--pt-elev-3);
    text-align: center;
}

.error-icon[b-p1xnf1glop] {
    color: var(--pt-color-danger-on-surface);
    margin-bottom: var(--pt-space-4);
}

.error-card h2[b-p1xnf1glop] {
    color: var(--pt-fg-primary);
    margin-bottom: var(--pt-space-2);
}

.error-card p[b-p1xnf1glop] {
    color: var(--pt-fg-secondary);
    margin-bottom: var(--pt-space-6);
}

/* The dev detail panel stays dark in both themes — it is a console, and a
   console reads as a console. Its colours are pinned to the neutral ramp's
   fixed end rather than to the theme-dependent surface tokens. */
.dev-error-details[b-p1xnf1glop] {
    text-align: left;
    margin: var(--pt-space-6) 0;
    padding: var(--pt-space-4);
    background: var(--pt-color-neutral-800);
    border-radius: var(--pt-radius-md);
    color: var(--pt-color-neutral-200);
}

.dev-error-details h3[b-p1xnf1glop] {
    color: var(--pt-color-warning-on-surface);
    margin-bottom: var(--pt-space-4);
    font-size: var(--pt-text-base);
}

.error-section[b-p1xnf1glop] {
    margin-bottom: var(--pt-space-4);
}

.error-section code[b-p1xnf1glop],
.stack-trace[b-p1xnf1glop] {
    display: block;
    margin-top: var(--pt-space-1);
    padding: var(--pt-space-2);
    background: var(--pt-color-neutral-700);
    color: var(--pt-color-neutral-100);
    border-radius: var(--pt-radius-xs);
}

.error-section code[b-p1xnf1glop] {
    font-size: var(--pt-text-sm);
    word-break: break-word;
}

.stack-trace[b-p1xnf1glop] {
    font-size: var(--pt-text-xs);
    overflow-x: auto;
    white-space: pre-wrap;
    word-break: break-all;
    max-height: 300px;
    overflow-y: auto;
}

.retry-button[b-p1xnf1glop] {
    background: var(--pt-color-brand-600);
    color: var(--pt-fg-on-brand);
    border: none;
    padding: var(--pt-space-3) var(--pt-space-6);
    border-radius: var(--pt-radius-md);
    font-size: var(--pt-text-base);
    font-weight: var(--pt-weight-semibold);
    cursor: pointer;
    transition: background var(--pt-dur-fast) var(--pt-ease);
}

.retry-button:hover[b-p1xnf1glop] {
    background: var(--pt-color-brand-700);
}
/* /Components/LiveCountdown.razor.rz.scp.css */
/* #4 — self-ticking countdown with a draining ring. */

.pt-countdown[b-ufbdsq6ncx] {
    align-items: center;
    display: inline-flex;
    gap: 0.4rem;
}

.pt-countdown-text[b-ufbdsq6ncx] {
    font-variant-numeric: tabular-nums;
}

/* Conic ring drains anticlockwise as the remaining fraction falls.
   --pt-countdown-pct is 0–100 of the interval still to run. */
.pt-countdown-ring[b-ufbdsq6ncx] {
    background: conic-gradient(
        var(--pt-color-brand-500) calc(var(--pt-countdown-pct, 0) * 1%),
        var(--pt-bg-tint) 0);
    border-radius: var(--pt-radius-full);
    display: inline-block;
    flex-shrink: 0;
    height: 14px;
    position: relative;
    width: 14px;
}

/* Punch the middle out so it reads as a ring, not a pie. */
.pt-countdown-ring[b-ufbdsq6ncx]::after {
    background: var(--pt-bg-surface);
    border-radius: var(--pt-radius-full);
    content: "";
    inset: 3px;
    position: absolute;
}

.pt-countdown-due .pt-countdown-text[b-ufbdsq6ncx] {
    color: var(--pt-color-success-on-surface);
    font-weight: var(--pt-weight-semibold);
}

.pt-countdown-due .pt-countdown-ring[b-ufbdsq6ncx] {
    animation: pt-pulse 2s infinite var(--pt-ease);
    background: var(--pt-color-success);
}

@media (prefers-reduced-motion: reduce) {
    .pt-countdown-due .pt-countdown-ring[b-ufbdsq6ncx] { animation: none; }
}
/* /Components/PageHeader.razor.rz.scp.css */
/* Page header — the single title treatment for every route.

   Laid out as a grid rather than flex so the back link, the title block and the
   action slot each hold a column and the title never shifts horizontally
   between a page that has a back link and one that doesn't... except that it
   should: `auto 1fr auto` collapses the empty columns to zero width, which is
   exactly right here. */

.pt-page-header[b-3to2ao838p] {
    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--pt-space-3);
    margin-bottom: var(--pt-space-5);
    container-type: inline-size;
    container-name: pt-page-header;
}

.pt-page-header-text[b-3to2ao838p] {
    min-width: 0;
}

.pt-page-title[b-3to2ao838p] {
    font-size: var(--pt-text-2xl);
    font-weight: var(--pt-weight-bold);
    letter-spacing: -0.02em;
    line-height: var(--pt-leading-tight);
    color: var(--pt-fg-primary);
    margin: 0;
    text-wrap: balance;
}

.pt-page-subtitle[b-3to2ao838p] {
    font-size: var(--pt-text-sm);
    color: var(--pt-fg-secondary);
    margin: var(--pt-space-1) 0 0;
    text-wrap: pretty;
}

/* ── Back affordance ───────────────────────────────────────────────────── */

.pt-page-back[b-3to2ao838p] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: var(--pt-space-1);
    padding: var(--pt-space-2);
    margin-inline-start: calc(var(--pt-space-2) * -1);
    border-radius: var(--pt-radius-md);
    color: var(--pt-fg-secondary);
    text-decoration: none;
    font-size: var(--pt-text-sm);
    font-weight: var(--pt-weight-medium);
    transition: background var(--pt-dur-fast) var(--pt-ease),
                color var(--pt-dur-fast) var(--pt-ease);
}

@media (hover: hover) {
    .pt-page-back:hover[b-3to2ao838p] {
        background: var(--pt-bg-tint);
        color: var(--pt-fg-primary);
    }
}

.pt-page-header-actions[b-3to2ao838p] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-2);
    justify-self: end;
}

/* Narrow header: the back label is redundant next to an arrow that points at
   the only place it could go, and the actions drop to their own row rather
   than squeezing the title to a two-character column. */
@container pt-page-header (width < 30rem) {
    .pt-page-back-label[b-3to2ao838p] { display: none; }

    .pt-page-header[b-3to2ao838p] {
        grid-template-columns: auto 1fr;
    }

    .pt-page-header-actions[b-3to2ao838p] {
        grid-column: 1 / -1;
        justify-self: stretch;
    }

    .pt-page-title[b-3to2ao838p] { font-size: var(--pt-text-xl); }
}
/* /Components/PwaUpdateBar.razor.rz.scp.css */
/* The "a newer build is waiting" notice.

   Deliberately the same glass pill as UndoBar, and deliberately ABOVE it: both are
   fixed to the bottom of the viewport, and a delete undo — which expires in seconds —
   must never be the one that gets covered. An update can wait. */

.pt-update-bar[b-biagu7qnoj] {
    align-items: center;
    animation: pt-slide-up var(--pt-dur-base) var(--pt-ease);
    backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    background: var(--pt-glass-bg-strong);
    border: 1px solid var(--pt-glass-border);
    border-radius: var(--pt-radius-full);
    bottom: calc(env(safe-area-inset-bottom, 0px) + 9rem);
    box-shadow: var(--pt-elev-3);
    display: flex;
    gap: var(--pt-space-3);
    left: 50%;
    max-width: calc(100vw - 2rem);
    padding: 0.55rem 0.7rem 0.55rem 1rem;
    position: fixed;
    transform: translateX(-50%);
    z-index: var(--pt-z-toast);
}

.pt-update-bar-text[b-biagu7qnoj] {
    color: var(--pt-fg-body);
    font-size: var(--pt-text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 640px) {
    .pt-update-bar[b-biagu7qnoj] {
        left: var(--pt-space-4);
        right: var(--pt-space-4);
        transform: none;
    }
}
/* /Components/UndoBar.razor.rz.scp.css */
/* #3 — the undo affordance for a deletion still inside its grace period. */

.pt-undo-bar[b-76iavek9t6] {
    align-items: center;
    animation: pt-slide-up var(--pt-dur-base) var(--pt-ease);
    backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    background: var(--pt-glass-bg-strong);
    border: 1px solid var(--pt-glass-border);
    border-radius: var(--pt-radius-full);
    bottom: calc(env(safe-area-inset-bottom, 0px) + 5rem);
    box-shadow: var(--pt-elev-3);
    display: flex;
    gap: var(--pt-space-3);
    left: 50%;
    max-width: calc(100vw - 2rem);
    padding: 0.55rem 0.7rem 0.55rem 1rem;
    position: fixed;
    transform: translateX(-50%);
    z-index: var(--pt-z-toast);
}

.pt-undo-icon[b-76iavek9t6] {
    flex-shrink: 0;
}

.pt-undo-text[b-76iavek9t6] {
    color: var(--pt-fg-body);
    font-size: var(--pt-text-sm);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pt-undo-action[b-76iavek9t6] {
    align-items: center;
    background: var(--pt-color-brand-600);
    border: none;
    border-radius: var(--pt-radius-full);
    color: var(--pt-fg-on-brand);
    cursor: pointer;
    display: inline-flex;
    flex-shrink: 0;
    font-size: var(--pt-text-sm);
    font-weight: var(--pt-weight-semibold);
    gap: 0.4rem;
    padding: 0.35rem 0.85rem;
    transition: background-color var(--pt-dur-fast) var(--pt-ease);
}

.pt-undo-action:hover[b-76iavek9t6] {
    background: var(--pt-color-brand-700);
}

/* Ring drains over the grace period. --pt-undo-pct is 0–100 remaining. */
.pt-undo-ring[b-76iavek9t6] {
    background: conic-gradient(
        var(--pt-fg-on-brand) calc(var(--pt-undo-pct, 0) * 1%),
        rgba(255, 255, 255, 0.3) 0);
    border-radius: var(--pt-radius-full);
    display: inline-block;
    height: 12px;
    width: 12px;
}

.pt-undo-secs[b-76iavek9t6] {
    font-variant-numeric: tabular-nums;
    opacity: 0.8;
}

@media (max-width: 640px) {
    .pt-undo-bar[b-76iavek9t6] {
        left: var(--pt-space-4);
        right: var(--pt-space-4);
        transform: none;
    }
}
/* /Features/Account/SettingsPage.razor.rz.scp.css */
/* SettingsPage — scoped styles replacing inline `Style="..."` on Radzen components. */
.pt-settings-full[b-tio816iprc] { width: 100%; }
.pt-settings-meta[b-tio816iprc] { font-size: var(--pt-text-sm); color: var(--pt-fg-tertiary); }

/* Sections replace what used to be four tabs. A rule between them is enough
   separation for six controls. */
.pt-settings-section + .pt-settings-section[b-tio816iprc] {
    margin-top: var(--pt-space-8);
    padding-top: var(--pt-space-6);
    border-top: 1px solid var(--pt-border-subtle);
}

.pt-settings-danger[b-tio816iprc] {
    /* The one section whose actions are irreversible reads as such before it is
       reached, rather than relying on the button colour alone. */
    --pt-settings-accent: var(--pt-color-danger);
}

.pt-settings-danger > :first-child[b-tio816iprc] {
    color: var(--pt-color-danger-on-surface);
}

/* ── Appearance pickers ─────────────────────────────────────────────────────
   The theme and density pickers were two hand-built segmented controls
   (.pt-choice-row / .pt-choice, ~50 lines each with their own hover, selected
   and aria-checked handling). They are RadzenSelectBars now; the shared
   corrections to Radzen's bar live in app.css, and all that is left here is
   capping the width so three items don't stretch across a desktop card. */
.pt-settings-section .rz-selectbar[b-tio816iprc] {
    max-width: 32rem;
}

/* The caption above each bar explains what the control does; it is a Radzen
   <span> and needs to be a block or it shares the bar's line. */
.pt-settings-section .rz-text-caption[b-tio816iprc] {
    display: block;
}

/* ── Section index ────────────────────────────────────────────────────────
   Six sections in one scroll. The index answers "what else is on this page"
   without scrolling and makes a jump one click, on screens wide enough to
   carry it. Below 1024px it does not render: a phone has no spare column, and
   an index that is itself as long as the content it indexes helps nobody. */

.pt-settings-layout[b-tio816iprc] {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--pt-space-5);
    align-items: start;
}

.pt-settings-index[b-tio816iprc] {
    display: none;
}

@media (min-width: 1024px) {
    .pt-settings-layout[b-tio816iprc] {
        grid-template-columns: 13rem minmax(0, 1fr);
    }

    .pt-settings-index[b-tio816iprc] {
        display: flex;
        flex-direction: column;
        gap: 2px;
        position: sticky;
        top: calc(var(--pt-space-5) + 4rem);
        padding: var(--pt-space-2);
        background: var(--pt-bg-surface);
        border: 1px solid var(--pt-border-subtle);
        border-radius: var(--pt-radius-lg);
        box-shadow: var(--pt-elev-1);
    }
}

.pt-settings-index a[b-tio816iprc] {
    padding: var(--pt-space-2) var(--pt-space-3);
    border-radius: var(--pt-radius-md);
    border-left: 3px solid transparent;
    color: var(--pt-fg-body);
    font-size: var(--pt-text-sm);
    text-decoration: none;
    transition: background-color var(--pt-dur-fast) var(--pt-ease);
}

.pt-settings-index a:hover[b-tio816iprc] {
    background: var(--pt-bg-tint);
    color: var(--pt-fg-primary);
}

/* :target marks the section the URL fragment points at, so the index shows
   where the last jump landed with no JavaScript and no scroll listener. */
.pt-settings-index a:has(+ *)[b-tio816iprc],
.pt-settings-index a:focus-visible[b-tio816iprc] {
    outline-offset: 2px;
}

.pt-settings-index-danger[b-tio816iprc] { color: var(--pt-color-danger-on-surface); }

/* The fixed header would otherwise cover the heading of whichever section was
   jumped to. scroll-margin-top reserves that space at the anchor itself. */
.pt-settings-section[b-tio816iprc] {
    scroll-margin-top: 5rem;
}

/* A brief tint on the section that was just jumped to, so the eye lands in the
   right place instead of hunting for what changed. */
.pt-settings-section:target[b-tio816iprc] {
    animation: pt-target-flash-b-tio816iprc 1.6s var(--pt-ease);
}

@keyframes pt-target-flash-b-tio816iprc {
    from { background: var(--pt-bg-tint); }
    to   { background: transparent; }
}

@media (prefers-reduced-motion: reduce) {
    .pt-settings-section:target[b-tio816iprc] { animation: none; }
}
/* /Features/Admin/AdminUsagePage.razor.rz.scp.css */
/* AdminUsagePage — scoped styles. */
.pt-admin-chart[b-brezeb67r9] { height: 280px; }
/* /Features/Alerts/NotificationBell.razor.rz.scp.css */
.pt-bell[b-g9qfpxlbm5] {
    position: relative;
    display: inline-flex;
}

.pt-bell-btn[b-g9qfpxlbm5] {
    position: relative;
    background: transparent;
    border: none;
    /* The bell sits on the dark app shell, where the inherited body foreground is
       the page's — near-black on light. It was an emoji before and carried its own
       colour; now it needs telling. */
    color: var(--pt-color-neutral-200);
    --pt-icon-size: 1.35rem;
    line-height: 1;
    cursor: pointer;
    padding: 0.35rem;
    border-radius: 50%;
    transition: background var(--pt-dur-fast, 120ms) var(--pt-ease-out, ease-out);
}

.pt-bell-btn:hover[b-g9qfpxlbm5] {
    background: var(--pt-bg-elev-1);
}

.pt-bell-badge[b-g9qfpxlbm5] {
    position: absolute;
    top: -0.1rem;
    right: -0.1rem;
    min-width: 1rem;
    height: 1rem;
    padding: 0 0.2rem;
    border-radius: 999px;
    background: var(--pt-color-danger, var(--pt-color-danger));
    color: var(--pt-fg-on-brand);
    font-size: 0.6rem;
    font-weight: 700;
    line-height: 1rem;
    text-align: center;
}

.pt-bell-panel[b-g9qfpxlbm5] {
    position: absolute;
    top: calc(100% + 0.5rem);
    right: 0;
    width: min(22rem, 90vw);
    max-height: 26rem;
    overflow-y: auto;
    background: var(--pt-bg-surface);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-md, 12px);
    box-shadow: var(--pt-elev-3, 0 8px 24px rgba(0, 0, 0, 0.18));
    z-index: 1000;
    padding: 0.5rem;
}

.pt-bell-head[b-g9qfpxlbm5] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.25rem 0.5rem 0.5rem;
    font-weight: 600;
    color: var(--pt-fg-primary);
}

.pt-bell-link[b-g9qfpxlbm5] {
    background: transparent;
    border: none;
    color: var(--pt-color-brand-on-surface);
    font-size: var(--pt-text-sm);
    cursor: pointer;
    padding: var(--pt-space-1) var(--pt-space-2);
}

/* Was declared twice — once alongside .pt-bell-link (transparent, no border,
   inline padding) and again immediately below with the opposite of nearly every
   one of those properties. Only the second ever applied. */
.pt-bell-enable[b-g9qfpxlbm5] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--pt-space-2);
    width: 100%;
    text-align: center;
    cursor: pointer;
    color: var(--pt-color-brand-on-surface);
    background: transparent;
    font-size: var(--pt-text-sm);
    font-family: inherit;
    padding: var(--pt-space-2);
    margin-bottom: var(--pt-space-1);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-sm);
    font-weight: var(--pt-weight-semibold);
}

.pt-bell-error[b-g9qfpxlbm5] {
    color: var(--pt-color-danger-on-surface);
    font-size: var(--pt-text-xs);
    padding: 0 var(--pt-space-2) var(--pt-space-1);
}

.pt-bell-empty[b-g9qfpxlbm5] {
    color: var(--pt-fg-tertiary, var(--pt-fg-secondary));
    font-size: 0.85rem;
    padding: 0.75rem 0.5rem;
    text-align: center;
}

.pt-bell-list[b-g9qfpxlbm5] {
    list-style: none;
    margin: 0;
    padding: 0;
}

.pt-bell-item[b-g9qfpxlbm5] {
    display: flex;
    gap: 0.5rem;
    align-items: flex-start;
    padding: 0.5rem;
    border-radius: var(--pt-radius-sm, 8px);
    cursor: pointer;
    transition: background var(--pt-dur-fast, 120ms) var(--pt-ease-out, ease-out);
}

.pt-bell-item:hover[b-g9qfpxlbm5] {
    background: var(--pt-bg-elev-1);
}

.pt-bell-unread[b-g9qfpxlbm5] {
    background: var(--pt-color-brand-50, rgba(99, 102, 241, 0.08));
}

.pt-bell-text[b-g9qfpxlbm5] {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.pt-bell-msg[b-g9qfpxlbm5] {
    font-size: 0.85rem;
    color: var(--pt-fg-primary);
}

.pt-bell-time[b-g9qfpxlbm5] {
    font-size: 0.7rem;
    color: var(--pt-fg-secondary);
}
/* /Features/Auth/LoginPage.razor.rz.scp.css */
/* LoginPage — scoped styles. Replaces inline color="var(--rz-text-tertiary-color)" usages. */
.pt-fg-tertiary[b-1iqnb9g4y6] {
    color: var(--pt-fg-tertiary);
}
/* /Features/Dashboard/DashboardPage.razor.rz.scp.css */


/* .pt-empty-state* moved to app.css — the compare page (#8) renders the same block,
   and scoped styles here would only reach the dashboard's copy of it. */

/* Glass surface for the status bar — sits over the mesh background.
   Padding and radius are app.css's (they scale with --pt-density); restating
   them here only re-froze them at this file's higher specificity. */
.pt-status-bar[b-cusa0zb6pf] {
    background: var(--pt-glass-bg-strong);
    backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    -webkit-backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    border-color: var(--pt-glass-border);
}

/* The LAYOUT of .pt-route-cards is not here.

   It used to be: this file carried `display: flex; flex-direction: column`, and
   because scoped CSS compiles to `.pt-route-cards[b-scd66klctr]` it beat the
   app.css rule on specificity every time. So the two-column grid added to
   app.css was computed as `display: flex` and never appeared, and the same trap
   had been sitting here for as long as both copies existed. app.css owns the
   grid; this file owns only what is specific to the dashboard's mesh
   background — the translucent surface. */

.pt-route-card[b-cusa0zb6pf] {
    /* Glass instead of the flat --pt-bg-surface app.css gives the card, so the
       mesh shows through. Geometry, elevation, transition and the ambient left
       border all come from app.css and are deliberately NOT restated. */
    background: var(--pt-glass-bg-strong);
    backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    -webkit-backdrop-filter: blur(var(--pt-glass-blur)) saturate(var(--pt-glass-saturate));
    border-color: var(--pt-glass-border);
}
/* /Features/MonitoringWindows/WindowConfigPanel.razor.rz.scp.css */
/* WindowConfigPanel — scoped styles. */
.pt-wcp-day-label[b-ccoy2s8myv] { margin: 0; cursor: pointer; }
/* /Features/Routes/AddressAutocomplete.razor.rz.scp.css */
.pt-ac[b-lm1ti0uqm3] {
    position: relative;
    width: 100%;
}

.pt-ac-input[b-lm1ti0uqm3] {
    width: 100%;
    padding: 0.5rem 0.75rem;
    border: 1px solid var(--pt-border-strong, #c9ccd1);
    border-radius: var(--pt-radius-sm, 6px);
    background: var(--pt-bg-surface);
    color: var(--pt-fg-primary);
    font: inherit;
}

.pt-ac-input:focus[b-lm1ti0uqm3] {
    outline: none;
    border-color: var(--pt-color-brand-400);
    box-shadow: 0 0 0 2px var(--pt-color-brand-100, rgba(99, 102, 241, 0.25));
}

.pt-ac-list[b-lm1ti0uqm3] {
    position: absolute;
    top: calc(100% + 0.2rem);
    left: 0;
    right: 0;
    z-index: 1000;
    margin: 0;
    padding: 0.25rem;
    list-style: none;
    max-height: 16rem;
    overflow-y: auto;
    background: var(--pt-bg-surface);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-md, 10px);
    box-shadow: var(--pt-elev-3, 0 8px 24px rgba(0, 0, 0, 0.18));
}

.pt-ac-item[b-lm1ti0uqm3] {
    padding: 0.5rem 0.6rem;
    border-radius: var(--pt-radius-sm, 6px);
    font-size: 0.9rem;
    color: var(--pt-fg-primary);
    cursor: pointer;
}

.pt-ac-item:hover[b-lm1ti0uqm3] {
    background: var(--pt-bg-elev-1);
}
/* /Features/Routes/CreateRoutePage.razor.rz.scp.css */
/* ── CreateRoutePage — scoped styles (replaces inline style="" attributes) ── */

.pt-create-route-card[b-rvujjuiw33] {
    max-width: 35rem;
    margin-inline: auto;
}

/* Day-of-week selector. This used to be ~50 lines styling seven hand-built
   <label> pills, each with a visually-hidden checkbox inside, plus their own
   hover, selected and :focus-within rules — all of which RadzenSelectBar
   already provides. What is left is the wrap: seven items in one nowrap flex
   row overflow a phone. */
.pt-day-toggles[b-rvujjuiw33] {
    flex-wrap: wrap;
}

/* Muted helper hint shown under the address fields. */
.pt-field-hint[b-rvujjuiw33] {
    display: block;
    margin: 0 0 var(--pt-space-3);
    color: var(--pt-fg-tertiary);
    font-size: var(--pt-text-xs);
}

/* Field-level validation message; replaces the hint in place so the row height
   doesn't jump when a field goes invalid. */
.pt-field-error[b-rvujjuiw33] {
    display: block;
    margin: 0 0 var(--pt-space-3);
    color: var(--pt-color-danger-on-surface);
    font-size: var(--pt-text-xs);
    font-weight: var(--pt-weight-medium);
}

/* The two time pickers sit side by side when there is room and stack when there
   isn't. They were a fixed flex row, which overflowed the card on a phone. */
.pt-schedule-times[b-rvujjuiw33] {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: var(--pt-space-4);
}
/* /Features/Routes/RouteCard.razor.rz.scp.css */
/* ── RouteCard — scoped styles (replaces inline style="" attributes) ── */

.pt-route-card-status[b-6fxna9r0pd] {
    flex-shrink: 0;
}
/* /Features/Routes/RouteDetailPage.razor.rz.scp.css */
/* Route detail — two columns: the answer and its controls, then the evidence.

   The page used to be five full-width blocks stacked, with the controls last,
   behind a <details> disclosure. That disclosure is gone: the controls it hid
   are the left column now, beside the answer they act on, and the three
   evidence cards share the right. Nothing was dropped; it stopped scrolling. */

/* ── The two columns ────────────────────────────────────────────────────────
   Left: everything ABOUT this route — the answer, and every control that acts
   on it. Right: every piece of EVIDENCE. The page used to stack five
   full-width blocks, so the schedule controls sat two scrolls below the answer
   they configure; this puts the whole page on one screen at laptop width.

   Single column below 1200px, which is exactly what it was before. The width
   cap that lets the two columns sit side by side is in app.css, next to the
   one the old split used — `.content` belongs to MainLayout and never carries
   this component's scope attribute, so it cannot be reached from here. */
.pt-route-two[b-ce8u4yysx4] {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--pt-space-4);
    align-items: start;
}

/* Keyed off the CONTENT COLUMN, not the window. A viewport query at 1200px never
   fired inside an embedded browser pane roughly 1150px wide, so the page rendered
   as one column on exactly the screens this layout exists for. .content is the
   app's root query container, and it is the width that actually decides whether
   two columns fit. 62rem is where 21rem + a readable evidence column stop
   fighting each other. */
@container pt-content (min-width: 62rem) {
    .pt-route-two[b-ce8u4yysx4] {
        /* 21rem holds the answer headline on one line and keeps
           WindowConfigPanel's two time pickers side by side. */
        grid-template-columns: 21rem minmax(0, 1fr);
    }

    /* The answer and the controls stay put while the evidence scrolls past them.
       Works because .pt-route-two sets align-items: start, so this column is its
       own height rather than stretched to the row's. */
    .pt-route-side[b-ce8u4yysx4] {
        position: sticky;
        top: calc(var(--pt-space-5) + 4rem);
    }
}

.pt-route-side[b-ce8u4yysx4] {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--pt-space-4);
}

.pt-route-evidence[b-ce8u4yysx4] {
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: var(--pt-space-4);

    /* Keeps the query container the old .pt-split-main provided, so the map, the
       chart and the heatmap still size to the column they are in rather than to
       the window. Same name, so no child component's rules had to change. */
    container-type: inline-size;
    container-name: pt-main;
}

.pt-route-evidence-top[b-ce8u4yysx4] {
    display: grid;
    grid-template-columns: 1fr;
    gap: var(--pt-space-4);
}

/* The map and today's chart share a row once the evidence column can carry two
   readable cards. Today's chart gets the larger share: the map is a shape, the
   chart is a run of points that have to stay apart.

   44rem, not 48: beside a 21rem answer column the evidence column lands just
   under 48rem on a 1440px window, and the pair fits comfortably at 44. */
@container pt-main (min-width: 44rem) {
    .pt-route-evidence-top[b-ce8u4yysx4] {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1.25fr);
    }
}

/* ── The answer ─────────────────────────────────────────────────────────────
   The only thing above the fold. It gets the largest type in the app and a
   surface of its own, because everything below it exists to support this line. */
.pt-answer[b-ce8u4yysx4] {
    background: linear-gradient(135deg,
        color-mix(in oklab, var(--pt-color-brand-500) 14%, var(--pt-bg-surface)),
        var(--pt-bg-surface));
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-lg);
    padding: var(--pt-space-3) var(--pt-space-5);
    margin-bottom: var(--pt-space-3);
    box-shadow: var(--pt-elev-1);

    container-type: inline-size;
    container-name: pt-answer;
}

/* Narrow column: --pt-text-2xl at "Leave by 10:45 AM" wraps to three lines in a
   phone's width, and a headline that wraps three times stops reading as one
   answer. Keyed off the block's own width so it is also correct if the answer
   is ever placed in a sidebar. */
@container pt-answer (width < 22rem) {
    .pt-answer-headline[b-ce8u4yysx4] { font-size: var(--pt-text-xl); }
    .pt-answer-pending[b-ce8u4yysx4] { font-size: var(--pt-text-lg); }
    .pt-answer-duration[b-ce8u4yysx4] { font-size: var(--pt-text-base); }
}

.pt-answer-route[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-2);
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-tertiary);
    margin-bottom: var(--pt-space-1);
    min-width: 0;
}

.pt-answer-from[b-ce8u4yysx4],
.pt-answer-to[b-ce8u4yysx4] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pt-answer-arrow[b-ce8u4yysx4] {
    color: var(--pt-fg-faint);
    flex-shrink: 0;
}

.pt-answer-headline[b-ce8u4yysx4] {
    font-size: var(--pt-text-2xl);
    font-weight: var(--pt-weight-bold);
    line-height: var(--pt-leading-tight);
    letter-spacing: -0.01em;
    color: var(--pt-fg-primary);
    text-wrap: balance;
}

.pt-answer-pending[b-ce8u4yysx4] {
    font-size: var(--pt-text-lg);
    color: var(--pt-fg-secondary);
    font-weight: var(--pt-weight-medium);
}

.pt-answer-duration[b-ce8u4yysx4] {
    font-size: var(--pt-text-base);
    color: var(--pt-fg-body);
    margin-top: var(--pt-space-1);
}

/* How much to trust the number, in a sentence rather than a progress bar. */
.pt-answer-meta[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: var(--pt-space-2);
    margin-top: var(--pt-space-2);
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-tertiary);
}

.pt-answer-ics[b-ce8u4yysx4] {
    color: var(--pt-color-brand-on-surface);
    font-weight: var(--pt-weight-semibold);
    text-decoration: none;
    white-space: nowrap;
}

.pt-answer-ics:hover[b-ce8u4yysx4] { text-decoration: underline; }

.pt-answer-live[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-2);
    margin-top: var(--pt-space-2);
    padding-top: var(--pt-space-2);
    border-top: 1px solid var(--pt-border-subtle);
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-tertiary);
    font-variant-numeric: tabular-nums;
}

/* When the route is paused, the "Not monitoring — start it in Settings below"
   line becomes a button. Visual language matches a ghost link: same font-size
   and colour as the surrounding line so the page doesn't suddenly spring a
   brand-coloured control into the answer block, but the chevron gives the
   affordance away. */

.pt-callout-action[b-ce8u4yysx4] {
    display: inline-flex;
    align-items: center;
    gap: var(--pt-space-1);
    background: transparent;
    border: 0;
    padding: 0;
    font: inherit;
    color: var(--pt-color-brand-600);
    cursor: pointer;
    text-decoration: underline;
    text-underline-offset: 0.2em;
    text-decoration-thickness: 1px;
    transition: color var(--pt-dur-fast) var(--pt-ease);
}

.pt-callout-action:hover[b-ce8u4yysx4],
.pt-callout-action:focus-visible[b-ce8u4yysx4] {
    color: var(--pt-color-brand-700);
    outline: none;
}

.pt-callout-action-icon[b-ce8u4yysx4] {
    font-size: 0.9em;
}

/* ── Evidence ───────────────────────────────────────────────────────────── */
.pt-evidence-head[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pt-space-3);
    margin-bottom: var(--pt-space-3);
    flex-wrap: wrap;
}

/* Comparison, folded in from what used to be its own page with its own pickers.
   One picker, on the chart it modifies. This styled a bare <select> before; the
   control is a RadzenDropDown now, so the surface, border and focus ring come
   from the Radzen theme (which pt-tokens.css already maps to the brand) and all
   that is left to say is how wide it may get. */
.pt-compare-select[b-ce8u4yysx4] {
    max-width: 16rem;
    min-width: 11rem;
}

.pt-compare-legend[b-ce8u4yysx4] {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--pt-space-3);
    margin-bottom: var(--pt-space-2);
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-secondary);
}

.pt-compare-legend-item[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-2);
    min-width: 0;
}

/* Keys mirror pt-chart.js: series A is brand, series B is warning-amber.
   Changing one without the other decouples the legend from the lines. */
.pt-compare-key[b-ce8u4yysx4] {
    border-radius: var(--pt-radius-full);
    display: inline-block;
    height: 3px;
    width: 1.5rem;
    flex-shrink: 0;
}

.pt-compare-key-a[b-ce8u4yysx4] { background: var(--pt-color-brand-500); }
.pt-compare-key-b[b-ce8u4yysx4] { background: var(--pt-color-warning); }

.pt-compare-verdict-inline[b-ce8u4yysx4] {
    color: var(--pt-fg-primary);
    font-weight: var(--pt-weight-semibold);
}

/* ── Return-trip control (left column, under the answer) ───────────────── */
.pt-returntrip-bar[b-ce8u4yysx4] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-4);
    border-radius: var(--pt-radius-md);
    background: var(--pt-bg-tint);
}

.pt-returntrip-label[b-ce8u4yysx4] {
    font-size: var(--pt-text-sm);
    color: var(--pt-fg-secondary);
}

/* ── Sample clicked on the trend chart ──────────────────────────────────── */
.pt-trend-selection[b-ce8u4yysx4] {
    align-items: center;
    background: var(--pt-bg-tint);
    border-radius: var(--pt-radius-sm);
    display: flex;
    flex-wrap: wrap;
    gap: var(--pt-space-3);
    margin-top: var(--pt-space-3);
    padding: var(--pt-space-2) var(--pt-space-3);
}

.pt-trend-selection-time[b-ce8u4yysx4] {
    color: var(--pt-fg-primary);
    font-variant-numeric: tabular-nums;
    font-weight: var(--pt-weight-semibold);
}

.pt-trend-selection-value[b-ce8u4yysx4] {
    color: var(--pt-color-brand-on-surface);
    font-weight: var(--pt-weight-semibold);
}

.pt-trend-selection-meta[b-ce8u4yysx4] {
    color: var(--pt-fg-secondary);
    flex: 1;
    font-size: var(--pt-text-sm);
    min-width: 0;
}

.pt-trend-selection-flag[b-ce8u4yysx4] {
    color: var(--pt-color-danger-on-surface);
    font-weight: var(--pt-weight-semibold);
    margin-left: var(--pt-space-2);
}

.pt-trend-selection-clear[b-ce8u4yysx4] {
    align-items: center;
    background: none;
    border: none;
    border-radius: var(--pt-radius-sm);
    color: var(--pt-fg-tertiary);
    cursor: pointer;
    display: inline-flex;
    justify-content: center;
    padding: var(--pt-space-1);
}

.pt-trend-selection-clear:hover[b-ce8u4yysx4] {
    color: var(--pt-fg-body);
}
/* /Features/Routes/TrendChart.razor.rz.scp.css */
/* Positioning context for the tooltip pt-chart.js appends. Because that element is
   created in JS it carries no scope attribute, so its own rules live in app.css. */
.pt-trend-host[b-frcxo5ghe6] {
    position: relative;
}

.pt-trend-canvas[b-frcxo5ghe6] {
    display: block;
    width: 100%;
    height: 240px;
    border-radius: var(--pt-radius-md);
    background: var(--pt-bg-elev-1);
    cursor: crosshair;
    touch-action: pan-y;
}

.pt-trend-toolbar[b-frcxo5ghe6] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--pt-space-2);
    margin-top: var(--pt-space-2);
    min-height: 1.5rem;
}

.pt-trend-hint[b-frcxo5ghe6],
.pt-trend-zoom-label[b-frcxo5ghe6] {
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-tertiary);
}

.pt-trend-zoom-label[b-frcxo5ghe6] {
    color: var(--pt-fg-secondary);
    font-weight: var(--pt-weight-medium);
}

.pt-trend-zoom-reset[b-frcxo5ghe6] {
    background: var(--pt-bg-tint);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-full);
    color: var(--pt-fg-body);
    cursor: pointer;
    font-size: var(--pt-text-xs);
    padding: 0.15rem 0.6rem;
    transition: background-color var(--pt-dur-fast) var(--pt-ease);
}

.pt-trend-zoom-reset:hover[b-frcxo5ghe6] {
    background: var(--pt-bg-tint-strong);
}

.pt-trend-empty[b-frcxo5ghe6] {
    text-align: center;
    padding: var(--pt-space-8);
    background: var(--pt-bg-elev-1);
    border-radius: var(--pt-radius-md);
    border: 1px dashed var(--pt-border-subtle);
}

.pt-trend-empty-icon[b-frcxo5ghe6] {
    color: var(--pt-fg-faint);
    margin-bottom: var(--pt-space-2);
}

.pt-trend-empty-title[b-frcxo5ghe6] {
    font-size: var(--pt-text-lg);
    font-weight: var(--pt-weight-semibold);
    color: var(--pt-fg-primary);
    margin-bottom: var(--pt-space-1);
}

.pt-trend-empty-text[b-frcxo5ghe6] {
    font-size: var(--pt-text-sm);
    color: var(--pt-fg-secondary);
}
/* /Features/Routes/TrendSparkline.razor.rz.scp.css */
.pt-sparkline-wrap[b-fy5ijpo738] {
    display: flex;
    flex-direction: column;
    gap: var(--pt-space-1);
    margin-top: var(--pt-space-2);
    width: 100%;
}

.pt-sparkline-svg[b-fy5ijpo738] {
    display: block;
    width: 100%;
    height: 56px;
    overflow: visible;
}

.pt-sparkline-area[b-fy5ijpo738] {
    transition: opacity 200ms ease-out;
}

.pt-sparkline-line[b-fy5ijpo738] {
    transition: stroke 200ms ease-out;
}

.pt-sparkline-label[b-fy5ijpo738] {
    font-size: var(--pt-text-xs);
    color: var(--pt-fg-tertiary);
    font-variant-numeric: tabular-nums;
}
/* /Features/Routes/VolatilityHeatmap.razor.rz.scp.css */
/* #5 — day-of-week × hour congestion grid.

   The ramp is expressed as alpha over whatever the card sits on, so one set of
   rules reads correctly in both the light and dark themes instead of needing a
   second palette under [data-theme="dark"]. */

.pt-heatmap-summary[b-bvv7a9go75] {
    color: var(--pt-fg-secondary);
}

.pt-heatmap-scroll[b-bvv7a9go75] {
    /* 24 columns will not fit a phone. The grid scrolls inside its own card
       rather than pushing the page sideways. */
    overflow-x: auto;
    padding-bottom: var(--pt-space-1);
    overscroll-behavior-x: contain;

    /* Query container for the grid inside: cells size themselves from the room
       the card gives them, which is the only measurement that matters here —
       the same heatmap has to work in a full-width card and in a narrow one. */
    container-type: inline-size;
    container-name: pt-heatmap;
}

/* Tight card: drop the per-cell number and let colour carry the reading. The
   tooltip and the visually-hidden text still hold the full figures. */
@container pt-heatmap (width < 26rem) {
    .pt-heat-value[b-bvv7a9go75] { display: none; }

    .pt-heat[b-bvv7a9go75] {
        min-width: 1.5rem;
        height: 1.4rem;
    }

    .pt-heatmap-hour[b-bvv7a9go75] { min-width: 1.5rem; font-size: 0.65rem; }
}

.pt-heatmap[b-bvv7a9go75] {
    border-collapse: separate;
    border-spacing: 3px;
    table-layout: fixed;
}

.pt-heatmap-hour[b-bvv7a9go75],
.pt-heatmap-day[b-bvv7a9go75] {
    color: var(--pt-fg-tertiary);
    font-size: var(--pt-text-xs);
    font-variant-numeric: tabular-nums;
    font-weight: var(--pt-weight-medium);
}

.pt-heatmap-hour[b-bvv7a9go75] {
    text-align: center;
    min-width: 2.25rem;
}

.pt-heatmap-day[b-bvv7a9go75] {
    text-align: right;
    padding-right: var(--pt-space-2);
    white-space: nowrap;
}

.pt-heat[b-bvv7a9go75] {
    border-radius: var(--pt-radius-xs);
    height: 1.75rem;
    min-width: 2.25rem;
    position: relative;
    text-align: center;
    vertical-align: middle;
}

/* The cells are <td>. They must stay table-cells: `display: inline-block` here
   dropped them out of the table's own layout, and the rows stacked into a grid
   nearly three times taller than it should be on a narrow screen. */
td.pt-heat[b-bvv7a9go75] {
    cursor: default;
}

/* The legend swatches are <span> and DO need to be boxes. */
.pt-heatmap-legend .pt-heat[b-bvv7a9go75] {
    display: inline-block;
}

.pt-heat-value[b-bvv7a9go75] {
    color: var(--pt-fg-primary);
    font-size: var(--pt-text-xs);
    font-variant-numeric: tabular-nums;
    font-weight: var(--pt-weight-semibold);
    line-height: 1.75rem;
}

/* Congestion ramp — mean travel time relative to the route's median sample.

   These were literal rgba()s of --pt-color-success / -warning / -danger, so the
   grid was the one surface in the app that did NOT follow a palette change: the
   sparkline, the trend line and the badges would move to a new danger hue and
   the heatmap would stay rose. Mixed from the tokens now, at the same alphas.
   in oklab keeps the mid-ramp from going muddy the way sRGB interpolation does. */
.pt-heat-empty[b-bvv7a9go75] { background: var(--pt-bg-tint); }
.pt-heat-l0[b-bvv7a9go75] { background: color-mix(in oklab, var(--pt-color-success) 20%, transparent); }
.pt-heat-l1[b-bvv7a9go75] { background: color-mix(in oklab, var(--pt-color-success) 42%, transparent); }
.pt-heat-l2[b-bvv7a9go75] { background: color-mix(in oklab, var(--pt-color-warning) 48%, transparent); }
.pt-heat-l3[b-bvv7a9go75] { background: color-mix(in oklab, var(--pt-color-danger)  45%, transparent); }
.pt-heat-l4[b-bvv7a9go75] { background: color-mix(in oklab, var(--pt-color-danger)  80%, transparent); }

/* At full saturation the primary foreground loses contrast in the light theme. */
.pt-heat-l4 .pt-heat-value[b-bvv7a9go75] { color: var(--pt-fg-on-brand); }

/* Wide spread — the hour is unpredictable, not merely slow. */
.pt-heat-volatile[b-bvv7a9go75]::after {
    background: var(--pt-fg-primary);
    border-radius: var(--pt-radius-full);
    content: "";
    height: 4px;
    opacity: 0.55;
    position: absolute;
    right: 3px;
    top: 3px;
    width: 4px;
}

.pt-heatmap-legend[b-bvv7a9go75] {
    align-items: center;
    color: var(--pt-fg-tertiary);
    display: flex;
    flex-wrap: wrap;
    font-size: var(--pt-text-xs);
    gap: var(--pt-space-1);
    margin-top: var(--pt-space-3);
}

/* Legend swatches are decorative — they carry no number, so they shrink. */
.pt-heatmap-legend .pt-heat[b-bvv7a9go75] {
    height: 0.85rem;
    min-width: 1.25rem;
}

.pt-heatmap-legend-label[b-bvv7a9go75] {
    margin: 0 var(--pt-space-1);
}

.pt-heatmap-legend-sep[b-bvv7a9go75] {
    color: var(--pt-fg-faint);
}

.pt-heatmap-empty[b-bvv7a9go75] {
    align-items: center;
    color: var(--pt-fg-secondary);
    display: flex;
    font-size: var(--pt-text-sm);
    gap: var(--pt-space-3);
    padding: var(--pt-space-4) var(--pt-space-2);
}

.pt-heatmap-empty-icon[b-bvv7a9go75] {
    color: var(--pt-fg-faint);
}

.pt-visually-hidden[b-bvv7a9go75] {
    border: 0;
    clip-path: inset(50%);
    height: 1px;
    overflow: hidden;
    position: absolute;
    white-space: nowrap;
    width: 1px;
}
/* /Layout/AuthLayout.razor.rz.scp.css */
.auth-shell[b-yjonmjubab] {
    display: flex;
    min-height: 100vh;
}

/* The brand panel is a marketing hero that is always dark, in both themes — its
   white copy is painted directly on top. These stops are deliberately literal so
   a theme flip cannot invert them out from under the text. */
.auth-brand-panel[b-yjonmjubab] {
    flex: 1;
    background: linear-gradient(140deg, #0f172a 0%, #1e1b4b 60%, #0f172a 100%);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem 2.5rem;
}

.auth-brand-content[b-yjonmjubab] {
    color: white;
    max-width: 380px;
}

.auth-logo[b-yjonmjubab] {
    font-size: 2.75rem;
    font-weight: 800;
    letter-spacing: -0.04em;
    /* Clipped to the text, sitting on the always-dark brand panel — literal for
       the same reason as .auth-brand-panel above. */
    background: linear-gradient(135deg, #ffffff 0%, #818cf8 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
    margin-bottom: 0.75rem;
}

.auth-tagline[b-yjonmjubab] {
    font-size: 1.05rem;
    color: rgba(255, 255, 255, 0.6);
    margin-bottom: 2.5rem;
    line-height: 1.6;
}

.auth-features[b-yjonmjubab] {
    display: flex;
    flex-direction: column;
    gap: var(--pt-space-4);
    list-style: none;
    margin: 0;
    padding: 0;
}

.auth-feature[b-yjonmjubab] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-3);
    color: rgb(255 255 255 / 0.82);
    font-size: var(--pt-text-sm);
    line-height: var(--pt-leading-normal);
}

/* `.auth-feature .pt-icon` is in app.css — a scoped rule ending on .pt-icon
   would compile to `.pt-icon[b-…]` and the <PtIcon> span carries no scope. */

.auth-form-panel[b-yjonmjubab] {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: var(--pt-space-10) var(--pt-space-8);
    /* Was --pt-brand-surface, one of a block of legacy aliases that no longer
       exists; it resolved through the fallback. Named directly now. */
    background: var(--pt-bg-page);
}

.auth-form-container[b-yjonmjubab] {
    width: 100%;
    max-width: 460px;
}

/* Social auth button overrides.
   Microsoft's branding guidelines fix the sign-in button's palette (white face,
   grey border, near-black label), so these values stay literal and do NOT follow
   the theme — an inverted Microsoft button is an off-brand Microsoft button.

   The !important flags these carried are gone: Radzen now lives in the `vendor`
   cascade layer, so an ordinary declaration here already outranks it. */
.auth-social-btn[b-yjonmjubab] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--pt-space-2);
    width: 100%;
    margin-top: var(--pt-space-2);
    background: #ffffff;
    color: #374151;
    border: 1px solid #d1d5db;
    box-shadow: 0 1px 2px rgb(15 23 42 / 0.05);
}

.auth-social-btn:hover[b-yjonmjubab] {
    background: #f9fafb;
    border-color: #9ca3af;
}

/* Compact mobile brand — hidden on desktop (the left brand panel owns branding there). */
.auth-mobile-brand[b-yjonmjubab] {
    display: none;
    text-align: center;
    margin-bottom: 1.75rem;
}

.auth-mobile-logo[b-yjonmjubab] {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.04em;
    background: linear-gradient(135deg, var(--pt-fg-strong) 0%, #4f46e5 100%);
    -webkit-background-clip: text;
    -webkit-text-fill-color: transparent;
    background-clip: text;
}

.auth-mobile-tagline[b-yjonmjubab] {
    font-size: 0.9rem;
    color: var(--pt-fg-tertiary, #6b7280);
    margin-top: 0.25rem;
}

@media (max-width: 1024px) {
    .auth-brand-panel[b-yjonmjubab] {
        display: none;
    }

    .auth-form-panel[b-yjonmjubab] {
        padding: 2rem 1.25rem;
    }

    .auth-mobile-brand[b-yjonmjubab] {
        display: block;
    }
}
/* /Layout/BottomNav.razor.rz.scp.css */
/* Bottom navigation — mobile portrait only (≤640px).
   Glass surface with central FAB for the primary "Add Route" action.
   The third slot is a "Menu" / "Account" button that opens a bottom-sheet
   action sheet with the catch-all destinations — matching the desktop
   avatar-menu's options (settings, status, sign out) — so the two surfaces
   agree on what "Account" means. */

.pt-bottom-nav[b-oc85rz8m6b] {
    display: none;
}

@media (max-width: 640px) {
    .pt-bottom-nav[b-oc85rz8m6b] {
        display: flex;
        align-items: center;
        justify-content: space-around;
        position: fixed;
        left: 0;
        right: 0;
        bottom: 0;
        min-height: var(--pt-bottom-nav-h);
        padding: var(--pt-space-2) var(--pt-space-3) calc(var(--pt-space-2) + env(safe-area-inset-bottom, 0px));
        background: var(--pt-color-surface);
        border-top: 1px solid var(--pt-border-subtle);
        z-index: var(--pt-z-nav);
    }
}

/* ── Bottom-sheet action menu (mobile only) ──────────────────────── */

.pt-bottom-sheet[b-oc85rz8m6b] {
    position: fixed;
    left: var(--pt-space-3);
    right: var(--pt-space-3);
    /* Sit above the bottom-nav, below the header. Same elevation as
       .pt-user-dropdown on desktop so the two surfaces feel like the same
       control opened differently. */
    bottom: calc(var(--pt-bottom-nav-h) + var(--pt-space-2) + env(safe-area-inset-bottom, 0px));
    background: var(--pt-color-surface);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-lg);
    box-shadow: var(--pt-elev-4);
    padding: var(--pt-space-2);
    display: flex;
    flex-direction: column;
    gap: 2px;
    z-index: calc(var(--pt-z-nav) + 1);
    animation: pt-bottom-sheet-up-b-oc85rz8m6b var(--pt-dur-base) var(--pt-ease);
}

@keyframes pt-bottom-sheet-up-b-oc85rz8m6b {
    from { opacity: 0; transform: translateY(8px); }
    to   { opacity: 1; transform: translateY(0); }
}

.pt-bottom-sheet-item[b-oc85rz8m6b] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-3);
    padding: var(--pt-space-3) var(--pt-space-3);
    border: 0;
    background: transparent;
    border-radius: var(--pt-radius-md);
    color: var(--pt-color-fg);
    font-size: var(--pt-text-base);
    font-family: inherit;
    text-align: left;
    text-decoration: none;
    cursor: pointer;
    min-height: 2.75rem;
    transition: background var(--pt-dur-fast) var(--pt-ease);
}

.pt-bottom-sheet-item:hover[b-oc85rz8m6b],
.pt-bottom-sheet-item:focus-visible[b-oc85rz8m6b] {
    background: var(--pt-color-surface-hover);
    outline: none;
}

.pt-bottom-sheet-danger[b-oc85rz8m6b] {
    color: var(--pt-color-danger-fg);
}

.pt-bottom-sheet-divider[b-oc85rz8m6b] {
    height: 1px;
    background: var(--pt-border-subtle);
    margin: var(--pt-space-1) var(--pt-space-2);
}

/* FAB-style center button. This one IS a plain <a> in BottomNav.razor, so it
   keeps its styles here. */
.pt-bottom-nav-fab[b-oc85rz8m6b] {
    position: relative;
    margin-top: -1.75rem;
}

.pt-bottom-nav-fab-inner[b-oc85rz8m6b] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3.25rem;
    height: 3.25rem;
    border-radius: var(--pt-radius-full);
    background: linear-gradient(135deg, var(--pt-color-brand-500), var(--pt-color-brand-700));
    color: var(--pt-fg-on-brand);
    --pt-icon-size: 1.75rem;
    box-shadow: 0 6px 20px color-mix(in oklab, var(--pt-color-brand-600) 40%, transparent);
    transition: transform var(--pt-dur-fast) var(--pt-ease),
                box-shadow var(--pt-dur-fast) var(--pt-ease);
}

.pt-bottom-nav-fab:active .pt-bottom-nav-fab-inner[b-oc85rz8m6b] {
    transform: scale(0.95);
    box-shadow: 0 3px 10px color-mix(in oklab, var(--pt-color-brand-600) 50%, transparent);
}
/* Identity line, absorbed from the header's user chip when the two account menus
   were merged into this one. Mirrors .pt-user-dropdown-header in NavMenu so the
   phone and desktop menus still look like the same object. */
.pt-bottom-sheet-header[b-oc85rz8m6b] {
    padding: var(--pt-space-3) var(--pt-space-4);
    border-bottom: 1px solid var(--pt-border-subtle);
}

.pt-bottom-sheet-label[b-oc85rz8m6b] {
    color: var(--pt-fg-muted);
    font-size: var(--pt-text-xs);
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

.pt-bottom-sheet-email[b-oc85rz8m6b] {
    color: var(--pt-fg-strong);
    font-size: var(--pt-text-sm);
    font-weight: var(--pt-weight-semibold);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
/* /Layout/MainLayout.razor.rz.scp.css */
/* ── PoTraffic page layout (Phase 4 — top nav) ── */

.page[b-cxwbgah42j] {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    min-height: 100dvh;
}

main[b-cxwbgah42j] {
    flex: 1;
    padding: 0;
}

/* .content is styled entirely in app.css.

   This file used to set `max-width: 1280px; margin: 0 auto; width: 100%` while
   app.css set 1180px, and scoped CSS wins on specificity — so the measure cap
   documented in app.css was never the one in force. One owner now. */

/* ── Skip link (shared Po convention) ──────────────────────────────────────
   Visually hidden until focused, then pinned to the top of the viewport. Uses
   var() fallbacks so it renders correctly whatever this app's token set is. */
.skip-link[b-cxwbgah42j] {
    position: absolute;
    left: -9999px;
    top: auto;
    width: 1px;
    height: 1px;
    overflow: hidden;
}

.skip-link:focus[b-cxwbgah42j] {
    position: fixed;
    top: 0.5rem;
    left: 50%;
    transform: translateX(-50%);
    width: auto;
    height: auto;
    padding: 0.5rem 1rem;
    background: var(--po-skip-bg, #111);
    color: var(--po-skip-fg, #fff);
    border: 2px solid currentColor;
    border-radius: 0.25rem;
    font-weight: 700;
    z-index: 9999;
    text-decoration: none;
}
/* /Layout/NavMenu.razor.rz.scp.css */
/* ── PoTraffic top app shell (Rule 6 — Left=Brand / Center=Actions / Right=User) ──
   Tokens come from wwwroot/css/pt-tokens.css so the bar reskins with the theme.

   That claim was only half true: the gradient's top stop was a literal #142137
   and every hover, border and chip surface below was a raw rgba(255,255,255,…),
   so the one piece of chrome on every page was the one piece that could not be
   reskinned from the token file. The bar is intentionally dark in BOTH themes —
   that is a brand decision, not an oversight — so the fix is a local scale
   derived from the palette rather than a switch to the theme-dependent
   surfaces. Change --pt-color-neutral-900 and the bar follows. */

.app-shell[b-3tuhdsiolr] {
    /* Local scale: everything painted on the bar mixes from these two, so the
       whole shell moves together. */
    --shell-bg: var(--pt-color-neutral-900);
    --shell-fg: var(--pt-color-neutral-0);
    --shell-tint: color-mix(in oklab, var(--shell-fg) 8%, transparent);
    --shell-tint-strong: color-mix(in oklab, var(--shell-fg) 14%, transparent);
    --shell-border: color-mix(in oklab, var(--pt-color-neutral-400) 18%, transparent);

    display: grid;
    grid-template-columns: auto 1fr auto;
    align-items: center;
    gap: var(--pt-space-4);
    background: linear-gradient(180deg,
        color-mix(in oklab, var(--pt-color-brand-900) 22%, var(--shell-bg)) 0%,
        var(--shell-bg) 100%);
    color: var(--shell-fg);
    padding: 0 var(--pt-space-6);
    min-height: 3.75rem;
    position: sticky;
    top: 0;
    z-index: var(--pt-z-nav);
    border-bottom: 1px solid var(--shell-border);
    box-shadow: var(--pt-elev-2);
}

/* ── Brand (left) — wordmark with a small accent mark ── */

.app-shell-brand[b-3tuhdsiolr] {
    display: inline-flex;
    align-items: center;
    gap: var(--pt-space-2);
    font-weight: var(--pt-weight-bold);
    font-size: var(--pt-text-lg);
    letter-spacing: -0.01em;
    color: var(--shell-fg);
    text-decoration: none;
    white-space: nowrap;
    transition: opacity var(--pt-dur-fast) var(--pt-ease);
}

.app-shell-brand[b-3tuhdsiolr]::before {
    content: "";
    width: 0.6rem;
    height: 0.6rem;
    border-radius: var(--pt-radius-xs);
    background: linear-gradient(135deg, var(--pt-color-brand-400), var(--pt-color-info));
    box-shadow: 0 0 0 3px color-mix(in oklab, var(--pt-color-brand-500) 16%, transparent);
    flex-shrink: 0;
}

.app-shell-brand:hover[b-3tuhdsiolr] {
    opacity: 0.85;
}

/* ── Center actions ── */

.app-shell-actions[b-3tuhdsiolr] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-1);
    justify-content: center;
    min-width: 0;
}

/* On mobile the bottom-nav already covers Commutes / Add / Account —
   rendering the same destinations again in the top bar crowds the header
   into two collapsible icons and one avatar pill with no useful order.
   Hide the centre row entirely below 640px; the right-hand user chip
   remains because Sign out has no other home on phone.
   Account settings is reached from the bottom-nav action sheet. */
@media (max-width: 640px) {
    .app-shell-actions[b-3tuhdsiolr] {
        display: none;
    }
}

.app-shell-user[b-3tuhdsiolr] {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: var(--pt-space-2);
    position: relative;
}

/* ── Nav links — hover tint, filled pill on active ── */

/* The .app-nav-link rules are NOT here — see the note in app.css.

   They cannot live in this file. Blazor's CSS isolation stamps its scope
   attribute onto the plain HTML elements written in NavMenu.razor, but the nav
   links are <NavLink>, a COMPONENT: the <a> it renders belongs to NavLink's own
   markup and never receives `b-mhqeozcjir`. Every rule here targeting
   .app-nav-link compiled to `.app-nav-link[b-mhqeozcjir]`, matched nothing, and
   left the links falling through to the global `a { color: … }` — underlined
   brand-blue on the dark bar, with no padding and no active state. */

/* The chip IS a plain <button> in this file's markup, so it does get the scope. */
.pt-user-chip-btn:focus-visible[b-3tuhdsiolr] {
    outline: 2px solid var(--pt-color-brand-300);
    outline-offset: 2px;
}

/* ── User chip (top-right) ── */

.pt-user-chip-btn[b-3tuhdsiolr] {
    display: inline-flex;
    align-items: center;
    gap: var(--pt-space-2);
    background: var(--shell-tint);
    border: 1px solid var(--shell-border);
    color: var(--shell-fg);
    padding: var(--pt-space-1) var(--pt-space-3) var(--pt-space-1) var(--pt-space-1);
    border-radius: var(--pt-radius-full);
    cursor: pointer;
    font-size: var(--pt-text-sm);
    font-weight: var(--pt-weight-medium);
    line-height: 1;
    transition: background var(--pt-dur-fast) var(--pt-ease),
                border-color var(--pt-dur-fast) var(--pt-ease);
    max-width: 16rem;
}

.pt-user-chip-btn:hover[b-3tuhdsiolr] {
    background: var(--shell-tint-strong);
    border-color: color-mix(in oklab, var(--shell-fg) 24%, transparent);
}

.pt-user-avatar[b-3tuhdsiolr] {
    width: 1.75rem;
    height: 1.75rem;
    border-radius: var(--pt-radius-full);
    background: linear-gradient(135deg, var(--pt-color-brand-500), var(--pt-color-info));
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-weight: var(--pt-weight-bold);
    color: var(--pt-fg-on-brand);
    font-size: var(--pt-text-xs);
    flex-shrink: 0;
    box-shadow: 0 1px 2px rgb(0 0 0 / 0.30);
}

.pt-user-chip-label[b-3tuhdsiolr] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pt-user-caret[b-3tuhdsiolr] {
    font-size: 0.7rem;
    opacity: 0.6;
}

/* ── Dropdown menu ── */

/* Baseline: absolutely positioned inside the header, which is a stacking context
   of its own. That is what forces the overlay gymnastics documented at the
   bottom of this file. */
.pt-user-dropdown[b-3tuhdsiolr] {
    position: absolute;
    top: calc(100% + var(--pt-space-2));
    right: 0;
    min-width: 16rem;
    background: var(--pt-bg-surface);
    color: var(--pt-fg-primary);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-lg);
    box-shadow: var(--pt-elev-3);
    z-index: var(--pt-z-pop);
    padding: var(--pt-space-2) 0;
    overflow: hidden;
    animation: pt-slide-down var(--pt-dur-fast) var(--pt-ease-out);
}

.pt-user-dropdown-header[b-3tuhdsiolr] {
    padding: var(--pt-space-2) var(--pt-space-4);
    border-bottom: 1px solid var(--pt-border-subtle);
    margin-bottom: var(--pt-space-1);
}

.pt-user-dropdown-label[b-3tuhdsiolr] {
    font-size: var(--pt-text-xs);
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--pt-fg-secondary);
    margin-bottom: var(--pt-space-1);
}

.pt-user-dropdown-email[b-3tuhdsiolr] {
    font-size: var(--pt-text-sm);
    font-weight: var(--pt-weight-semibold);
    color: var(--pt-fg-primary);
    word-break: break-all;
}

.pt-dropdown-item[b-3tuhdsiolr] {
    display: flex;
    align-items: center;
    gap: var(--pt-space-3);
    width: 100%;
    text-align: left;
    background: transparent;
    border: 0;
    padding: var(--pt-space-3) var(--pt-space-4);
    font-size: var(--pt-text-sm);
    font-family: inherit;
    color: var(--pt-fg-primary);
    text-decoration: none;
    cursor: pointer;
    transition: background var(--pt-dur-fast) var(--pt-ease);
}

/* The dropdown items' icon colours are in app.css — see the note there. A rule
   ending on .pt-icon cannot be scoped. */

/* The admin destinations only appear in this menu at the width where the centre
   nav is gone. Above it they would be a second copy of links already in the bar. */
@media (min-width: 641px) {
    .pt-dropdown-mobile-only[b-3tuhdsiolr] { display: none; }
}

.pt-dropdown-item:hover[b-3tuhdsiolr] {
    /* Was --pt-color-neutral-100: a raw palette step, so the hover stayed pale
       grey on the dark dropdown surface. The tint washes with the theme. */
    background: var(--pt-bg-tint);
}

.pt-dropdown-item.danger[b-3tuhdsiolr] {
    color: var(--pt-color-danger-on-surface);
}

.pt-dropdown-item.danger:hover[b-3tuhdsiolr] {
    background: var(--pt-danger-bg);
}

.pt-dropdown-divider[b-3tuhdsiolr] {
    height: 1px;
    background: var(--pt-border-subtle);
    margin: var(--pt-space-1) 0;
}

/* ── Mock-data banner (top notice, full width) ── */

.pt-mock-banner[b-3tuhdsiolr] {
    align-items: center;
    background: linear-gradient(90deg,
        var(--pt-color-warning) 0%,
        color-mix(in oklab, var(--pt-color-warning) 70%, var(--pt-color-neutral-900)) 100%);
    /* Near-black on amber rather than the #422006 literal — the same reading at
       any warning hue, and it clears AA against both ends of the gradient. */
    color: color-mix(in oklab, var(--pt-color-warning) 12%, #000);
    display: flex;
    gap: var(--pt-space-2);
    justify-content: center;
    padding: var(--pt-space-2) var(--pt-space-4);
    font-weight: var(--pt-weight-bold);
    font-size: var(--pt-text-xs);
    letter-spacing: 0.06em;
}

/* ── Mobile portrait (≤640px): keep grid but compress padding ── */

@media (max-width: 640px) {
    .app-shell[b-3tuhdsiolr] {
        padding: 0 var(--pt-space-3);
        gap: var(--pt-space-2);
        min-height: 3.5rem;
    }

    .app-shell-brand[b-3tuhdsiolr] {
        font-size: var(--pt-text-base);
    }

    /* The centre links have nowhere to go on a phone: the brand and the user chip
       already claim the bar, and the links were overlapping the wordmark. The
       bottom nav carries these destinations at this width. */
    .app-shell-actions[b-3tuhdsiolr] {
        display: none;
    }

    /* NAV CONSOLIDATION. The chip's dropdown offered Account settings, System
       status and Sign out — the same three items, in the same order, as the
       bottom nav's action sheet. Two menus, one set of destinations, and the
       one in the top-right corner was the one a thumb could not reach.

       On a phone the header is now identity and alerts only; the bottom sheet
       is the single account menu, and it carries the "Signed in as" line that
       used to be this chip's only unique content. */
    .pt-user-chip-btn[b-3tuhdsiolr] {
        display: none;
    }
}

/* ── Overlay behind the user menu ──
   MUST stay below .app-shell (position:sticky; z-index:--pt-z-nav). The header is its own
   stacking context, so the dropdown's z-index only ranks *within* the header — at the root
   the whole header ranks at --pt-z-nav. A root-level overlay above that would paint over the
   dropdown and swallow its clicks (Sign Out looks dead, just closes the menu). Kept just
   below the nav so it still covers page content to catch outside clicks. */

.pt-overlay[b-3tuhdsiolr] {
    position: fixed;
    inset: 0;
    z-index: calc(var(--pt-z-nav) - 10);
    background: transparent;
}
/* /Pages/AccessDenied.razor.rz.scp.css */
.pt-access-denied[b-kf01c2wssj] {
    max-width: 32rem;
    margin: 4rem auto;
    padding: 2.5rem 2rem;
    text-align: center;
    background: var(--rz-card-background-color, var(--pt-bg-surface));
    border-radius: 12px;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}

.pt-access-denied-icon[b-kf01c2wssj] {
    color: var(--pt-fg-faint);
    margin-bottom: var(--pt-space-3);
}

.pt-access-denied h1[b-kf01c2wssj] {
    font-size: 1.5rem;
    font-weight: 700;
    margin-bottom: 0.75rem;
}

.pt-access-denied p[b-kf01c2wssj] {
    color: var(--rz-text-secondary-color, var(--pt-fg-muted));
    margin-bottom: 1.5rem;
    line-height: 1.5;
}
/* /Pages/Health.razor.rz.scp.css */
/* Health & Connections page. Status colour is driven entirely by the [data-status]
   attribute so the markup carries no inline styles (Rule 4). */

.pt-health[b-umddxzjcmb] {
    max-width: 56rem;
    margin-inline: auto;
    padding: var(--pt-space-6, 1.5rem) var(--pt-space-4, 1rem);
}

/* The page's own header rules (.pt-health-head / h1 / .pt-health-sub) are gone —
   the shared <PageHeader> renders that block for every page now. */

/* ── Status colour mapping ───────────────────────────────────────────────── */

.pt-health-summary[b-umddxzjcmb],
.pt-health-item[b-umddxzjcmb] {
    --status-colour: var(--pt-color-neutral-400);
}

[data-status="healthy"][b-umddxzjcmb] {
    --status-colour: var(--pt-color-success);
}

[data-status="degraded"][b-umddxzjcmb] {
    --status-colour: var(--pt-color-warning);
}

[data-status="unhealthy"][b-umddxzjcmb] {
    --status-colour: var(--pt-color-danger);
}

.pt-health-dot[b-umddxzjcmb] {
    flex: 0 0 auto;
    width: 0.75rem;
    height: 0.75rem;
    margin-top: 0.3rem;
    border-radius: var(--pt-radius-full, 999px);
    background: var(--status-colour);
}

/* ── Summary banner ──────────────────────────────────────────────────────── */

.pt-health-summary[b-umddxzjcmb] {
    display: flex;
    gap: var(--pt-space-3, 0.75rem);
    align-items: flex-start;
    padding: var(--pt-space-4, 1rem);
    margin-bottom: var(--pt-space-4, 1rem);
    background: var(--pt-bg-elev-1);
    border: 1px solid var(--pt-border-subtle);
    border-inline-start: 3px solid var(--status-colour);
    border-radius: var(--pt-radius-lg, 0.75rem);
    color: var(--pt-fg-primary);
}

.pt-health-meta[b-umddxzjcmb] {
    display: block;
    margin-top: var(--pt-space-1);
    font-size: var(--pt-text-sm);
    color: var(--pt-fg-secondary);
}

/* ── Connection list ─────────────────────────────────────────────────────── */

.pt-health-list[b-umddxzjcmb] {
    display: grid;
    gap: var(--pt-space-2);
    padding: 0;
    margin: 0;
    list-style: none;

    /* The rows reflow against the list's own width, not the window's. This page
       is anonymous and is the one people open on a phone while something is
       broken, but it is also embedded in the 1180px content column on a desktop —
       and a viewport query cannot tell those apart if the list is ever placed in
       a narrower slot. */
    container-type: inline-size;
    container-name: pt-health-list;
}

.pt-health-item[b-umddxzjcmb] {
    display: flex;
    gap: var(--pt-space-3, 0.75rem);
    align-items: flex-start;
    padding: var(--pt-space-3, 0.75rem) var(--pt-space-4, 1rem);
    background: var(--pt-bg-surface);
    border: 1px solid var(--pt-border-subtle);
    border-radius: var(--pt-radius-md, 0.5rem);
}

.pt-health-item-body[b-umddxzjcmb] {
    flex: 1 1 auto;
    min-width: 0;
}

.pt-health-item-head[b-umddxzjcmb] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: baseline;
    justify-content: space-between;
}

.pt-health-name[b-umddxzjcmb] {
    font-weight: 600;
    color: var(--pt-fg-primary);
    overflow-wrap: anywhere;
}

.pt-health-status[b-umddxzjcmb] {
    font-size: var(--pt-text-sm, 0.875rem);
    font-weight: 600;
    color: var(--status-colour);
}

.pt-health-desc[b-umddxzjcmb] {
    margin: 0.25rem 0 0;
    font-size: var(--pt-text-sm, 0.875rem);
    color: var(--pt-fg-secondary);
    overflow-wrap: anywhere;
}

.pt-health-duration[b-umddxzjcmb] {
    flex: 0 0 auto;
    font-size: var(--pt-text-sm, 0.875rem);
    font-variant-numeric: tabular-nums;
    color: var(--pt-fg-tertiary);
}

/* Below this the name, the status and the timing cannot share a row without the
   name truncating — and the name is the only one of the three that says which
   dependency you are looking at. */
@container pt-health-list (width < 30rem) {
    .pt-health-duration[b-umddxzjcmb] {
        display: none;
    }
}
/* /Pages/NotFound.razor.rz.scp.css */
/* Not-found page — centered, with a clear way back (no dead ends). */
.pt-notfound[b-fjyuge5zdz] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    min-height: 60vh;
    padding: var(--pt-space-8, 2rem) var(--pt-space-4, 1rem);
    gap: 0.5rem;
}

.pt-notfound-icon[b-fjyuge5zdz] {
    color: var(--pt-fg-faint);
    margin-bottom: var(--pt-space-2);
}

.pt-notfound-title[b-fjyuge5zdz] {
    font-size: var(--pt-text-2xl, 1.5rem);
    font-weight: 700;
    color: var(--pt-fg-primary, var(--pt-fg-primary));
    margin: 0;
}

.pt-notfound-text[b-fjyuge5zdz] {
    color: var(--pt-fg-secondary, #4b5563);
    max-width: 32rem;
    margin: 0 0 1rem;
}
