/* PlatinumMedic — base styles layered on top of MudBlazor.

   Everything here is expressed through MudBlazor's CSS custom properties
   (--mud-palette-*) so light and dark mode stay in sync automatically. Hard-coded
   hex outside the theme file is banned across the Platinum products; the two
   exceptions below (white on a filled brand surface) are called out where they sit.

   The class prefixes are deliberate and match the sibling products:
     --pm-*  design tokens for this product
     .pm-*   PlatinumMedic-specific components (odontogram, assistant, perio grid)
     .pw-*   the shared Platinum card treatment, identical to PlatinumWeigh
   ------------------------------------------------------------------------------ */

:root {
    /* Radius scale — one card standard everywhere; pills stay full-round. */
    --pm-radius-card: 16px;
    --pm-radius-control: 8px;
    --pm-radius-pill: 999px;

    /* Caption/metadata type scale — two steps below body (0.875rem). */
    --pm-font-caption: 0.75rem;
    --pm-font-micro: 0.6875rem;

    /* Semantic z-index scale. MudBlazor's own portaled overlays (menus, dialogs,
       snackbars) occupy roughly 1200–1400, so app-level fixed furniture stays below
       that band. No arbitrary 9999 one-offs. */
    --pm-z-app-banner: 1000;
    --pm-z-assistant: 1050;
}

html, body {
    margin: 0;
    font-family: Inter, 'Segoe UI', system-ui, Roboto, Helvetica, Arial, sans-serif;
}

h1:focus { outline: none; }
h1:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: 4px; }

@media (prefers-reduced-motion: reduce) {
    *, *::before, *::after {
        animation-duration: 0.01ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.01ms !important;
        scroll-behavior: auto !important;
    }
}

/* ── Shared content-card treatment ───────────────────────────────────────────────
   One flat, bordered surface for every static content card. Border at rest, no drop
   shadow — never both. Pairing a visible border with a wide drop shadow ("ghost card"
   double-framing) is banned across the Platinum products. Use with Elevation="0". */
.pw-card {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    border-radius: var(--pm-radius-card);
    overflow: hidden;
}

/* ── Page header ─────────────────────────────────────────────────────────────────
   Title block on the left, actions on the right, wrapping to two rows on a phone
   rather than pushing the action button off the screen. */
.pm-page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
    margin-bottom: 20px;
}

.pm-page-header-text { flex: 1 1 320px; min-width: 0; }

/* flex-basis auto with shrink allowed, not 0 0 auto. The header wraps, but this row did not:
   fixed at max-content it kept the diary's Back/Today/Next group and the Book button on one line,
   and on a 320px phone that pushed 48px of the page off the right edge. Shrinking lets the row
   wrap internally instead. */
.pm-page-header-actions {
    flex: 0 1 auto;
    min-width: 0;
    max-width: 100%;
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}

/* A long patient name must wrap inside its own column, never widen the row. */
.pm-page-title {
    overflow-wrap: anywhere;
    margin: 0;
}

/* ── KPI / summary stat cards ────────────────────────────────────────────────────
   A full-tint icon chip carries the status colour. No side stripe — border-left
   accents on cards are a banned pattern in this design system. */
.pm-stat {
    display: flex;
    align-items: center;
    gap: 14px;
    padding: 16px;
    height: 100%;
}

.pm-stat-icon {
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: var(--pm-radius-control);
    display: flex;
    align-items: center;
    justify-content: center;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, transparent);
    color: var(--mud-palette-primary);
}

.pm-stat-body { min-width: 0; }

/* A six-figure rand amount is eleven characters that must not break. At 1.75rem that is roughly
   190px, and a half-width stat tile on a 320px phone offers about 120px — so the figure hung out
   of its tile and took the whole page sideways with it. Clamped rather than wrapped: a currency
   amount split across two lines is worse than a smaller one, and tabular-nums keeps the columns
   of figures aligned at any size. */
.pm-stat-value {
    font-size: clamp(1.05rem, 5vw, 1.75rem);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: -0.5px;
    font-variant-numeric: tabular-nums;
    min-width: 0;
}

.pm-stat-label {
    font-size: var(--pm-font-caption);
    color: var(--mud-palette-text-secondary);
    overflow-wrap: anywhere;
}

.pm-stat.success .pm-stat-icon { background: color-mix(in srgb, var(--mud-palette-success) 14%, transparent); color: var(--mud-palette-success); }
.pm-stat.info    .pm-stat-icon { background: color-mix(in srgb, var(--mud-palette-info) 14%, transparent);    color: var(--mud-palette-info); }
.pm-stat.warning .pm-stat-icon { background: color-mix(in srgb, var(--mud-palette-warning) 14%, transparent); color: var(--mud-palette-warning); }
.pm-stat.error   .pm-stat-icon { background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent);   color: var(--mud-palette-error); }

/* ── Action tiles ────────────────────────────────────────────────────────────────
   Identical motion curve and radius to the sibling products' dashboard tiles. */
.pm-tile {
    cursor: pointer;
    transition: transform .2s cubic-bezier(0.25, 1, 0.5, 1),
                box-shadow .2s cubic-bezier(0.25, 1, 0.5, 1);
    -webkit-user-select: none;
    user-select: none;
    -webkit-tap-highlight-color: transparent;
    border-radius: var(--pm-radius-card) !important;
    height: 100%;
}

.pm-tile:hover  { transform: translateY(-2px); box-shadow: 0 8px 20px rgba(0, 0, 0, .08) !important; }
.pm-tile:active { transform: translateY(0);    box-shadow: 0 4px 10px rgba(0, 0, 0, .05) !important; }
.pm-tile:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
    .pm-tile { transition: box-shadow .15s linear; }
    .pm-tile:hover, .pm-tile:active { transform: none; }
}

/* ── Selectable rows (patient pickers, recall lists) ─────────────────────────── */
.pm-select-item {
    cursor: pointer;
    min-height: 58px;
    transition: background .12s ease, transform .1s ease;
    -webkit-user-select: none;
    user-select: none;
}

.pm-select-item:hover { background: var(--mud-palette-action-default-hover) !important; transform: translateX(3px); }
.pm-select-item:active { transform: translateX(1px); }
.pm-select-item:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: -2px; }

/* ── Sign-in / change-password ──────────────────────────────────────────────── */
.pm-signin {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
    background: var(--mud-palette-background);
    padding: 24px 16px;
}

.pm-signin-card {
    padding: 40px 40px 32px;
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

.pm-signin-logo {
    width: 84px;
    height: 84px;
    object-fit: contain;
    align-self: center;
    margin-bottom: 12px;
}

.pm-signin-footer { margin-top: 24px; text-align: center; }

@media (max-width: 480px) {
    .pm-signin-card { padding: 28px 20px 24px; }
    .pm-signin-logo { width: 64px; height: 64px; }
}

/* ── Nav drawer ──────────────────────────────────────────────────────────────────
   The drawer is a fixed column: header, scrolling nav region, pinned footer. It must
   never scroll sideways. `.mud-nav-link` is width:100%, so a horizontal margin on the
   links pushes them past the drawer's right edge and raises a horizontal scrollbar —
   which on Windows eats vertical height and raises a second, vertical scrollbar on a
   menu that otherwise fitted. So the inset lives on the container as padding
   (border-box), sub-items indent with padding only, and overflow-x is pinned hidden. */
.pm-drawer-header {
    flex: 0 0 auto;
    min-height: 0;
    padding: 14px 20px;
    display: flex;
    align-items: center;
    gap: 10px;
}

.pm-drawer-logo { width: 26px; height: 26px; flex: 0 0 auto; }

.pm-drawer-title {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: -0.3px;
    color: var(--mud-palette-text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.pm-drawer-nav {
    flex: 1 1 auto;
    min-height: 0;
    overflow-x: hidden;
    overflow-y: auto;
}

.pm-drawer-footer {
    flex: 0 0 auto;
    padding: 10px 12px 14px;
    font-size: var(--pm-font-micro);
    line-height: 1.35;
    text-align: center;
    color: var(--mud-palette-text-secondary);
    border-top: 1px solid var(--mud-palette-divider);
}

.mud-drawer { overflow: hidden; }

.pm-drawer-nav > .mud-navmenu { padding: 0 8px; }

.mud-drawer .mud-nav-link {
    border-radius: var(--pm-radius-control);
    margin: 1px 0;
    padding: 6px 12px;
    font-size: 0.85rem;
    line-height: 1.4;
    align-items: center;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.mud-drawer .mud-nav-link .mud-nav-link-text {
    margin-inline-start: 10px;
    overflow-wrap: anywhere;
}

.mud-drawer .mud-nav-link .mud-icon-root { font-size: 1.2rem; }

.mud-drawer .mud-nav-link:hover,
.mud-drawer .mud-nav-link:focus-visible {
    background-color: var(--mud-palette-action-default-hover) !important;
}

.mud-drawer .mud-nav-link:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -2px;
}

.mud-drawer .mud-nav-link.active {
    background-color: var(--mud-palette-primary-lighten) !important;
    color: var(--mud-palette-primary) !important;
    font-weight: 700;
}

.mud-drawer .mud-nav-link.active .mud-icon-root { color: var(--mud-palette-primary) !important; }

.mud-drawer .mud-nav-group .mud-nav-link {
    padding-inline-start: 30px;
    padding-inline-end: 12px;
}

/* Section labels. Tight, so each costs a row of height rather than the ~28px
   MudBlazor's overline line-height would spend. */
.pm-nav-section {
    display: block;
    padding: 10px 20px 2px;
    font-size: 0.62rem;
    font-weight: 700;
    line-height: 1.2;
    letter-spacing: 1.2px;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

/* ── Page content + footer ─────────────────────────────────────────────────── */
/* The assistant is a fixed button in the bottom-right corner, so the last rows of any page
   would sit underneath it. The reserve is its 56px diameter plus its 20px offset. */
/* Set here rather than with MudBlazor's pt-6/pb-4 utility classes, which emit !important and
   silently win: an earlier 88px bottom clearance written on this rule computed to 16px because
   .pb-4 overrode it. Nothing floats over the page any more (the assistant launcher moved into the
   app bar), so this is ordinary breathing room rather than clearance for an overlay. */
.pm-page-content {
    padding-top: 24px;
    padding-bottom: 40px;
}

/* MudGrid's default spacing is a 24px gutter, implemented as a -24px margin on the row and 24px
   of padding on each item. MudContainer's own gutter is 16px, so a grid placed straight into the
   page — rather than inside a padded card, which is where most of them sit — hangs 8px past the
   container on each side. On a desktop that is invisible; on a 320px phone the account summary
   dragged the whole page 44px sideways. Giving the page container the gutter the grid assumes
   fixes every such grid at once rather than one page at a time. */
.pm-page-content.mud-container--gutters {
    padding-left: 24px;
    padding-right: 24px;
}

.pm-page-footer {
    padding: 12px 16px 20px;
    border-top: 1px solid var(--mud-palette-divider);
    text-align: center;
}

/* ── Odontogram ──────────────────────────────────────────────────────────────────
   The chart is a fixed-aspect drawing of a whole mouth. On a phone it cannot shrink
   and stay legible, so it scrolls inside its own container rather than forcing the
   page body to scroll sideways.

   The max-width matters as much as the min: stretched edge-to-edge on a wide monitor
   the teeth become oversized empty boxes and the chart stops reading as a mouth. */
.pm-odontogram-scroll {
    overflow-x: auto;
    padding-bottom: 0.5rem;
}

/* min-width and max-width are set inline by the component, scaled to the tooth count —
   a 20-tooth child chart and a 32-tooth adult chart need different bounds. */
.pm-odontogram {
    width: 100%;
    height: auto;
    margin: 0 auto;
    display: block;
}

.pm-surface { transition: opacity 120ms ease-in-out; }
.pm-tooth:hover .pm-surface { opacity: 0.75; }

/* Absent teeth recede so the mouth reads as it is, not as it was. */
.pm-tooth-absent { opacity: 0.5; }

.pm-tooth:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: 2px; }

/* Condition colour swatch, used in the chart key and the condition picker. */
.pm-swatch {
    display: inline-block;
    width: 14px;
    height: 14px;
    border-radius: 3px;
    border: 1px solid var(--mud-palette-lines-default);
    margin-right: 8px;
    flex: 0 0 auto;
}

/* ── Perio chart grid ────────────────────────────────────────────────────────────
   Six probing sites per tooth across the arch. Digits must align in columns, hence
   tabular figures; the grid scrolls in its own container like the odontogram. */
.pm-perio-scroll { overflow-x: auto; padding-bottom: 0.5rem; }

.pm-perio {
    border-collapse: collapse;
    font-variant-numeric: tabular-nums;
    font-size: var(--pm-font-caption);
    min-width: 900px;
}

.pm-perio th,
.pm-perio td {
    border: 1px solid var(--mud-palette-divider);
    padding: 2px 4px;
    text-align: center;
    min-width: 26px;
}

.pm-perio th {
    font-weight: 700;
    background: var(--mud-palette-background-grey);
    white-space: nowrap;
}

.pm-perio-rowlabel {
    text-align: left !important;
    white-space: nowrap;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    position: sticky;
    left: 0;
    background: var(--mud-palette-surface);
    z-index: 1;
}

/* A pocket ≥ 4 mm is the clinical threshold for disease; ≥ 6 mm is severe. Colour is
   backed by weight so the reading survives a colour-vision deficiency. */
/* The capture grid reuses the read-back table, so its inputs have to sit inside a 2ch cell
   without widening it — a native number field's spinner alone is wider than the column. */
.pm-perio-input {
    width: 100%;
    min-width: 2.2rem;
    padding: 2px;
    border: 1px solid var(--mud-palette-lines-inputs);
    border-radius: 4px;
    background: var(--mud-palette-surface);
    color: inherit;
    font: inherit;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.pm-perio-input:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: -1px;
}

.pm-perio-warn   { color: var(--mud-palette-warning); font-weight: 700; }
.pm-perio-severe { color: var(--mud-palette-error);   font-weight: 800; }
.pm-perio-bop    { color: var(--mud-palette-error); }

/* ── Data density helpers ───────────────────────────────────────────────────── */
.pm-num { font-variant-numeric: tabular-nums; }

.pm-money {
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
    text-align: right;
}

/* A wide table scrolls inside its own container; the page body never goes sideways.

   min-width:0 is load-bearing, not defensive. A flex or grid child defaults to
   min-width:auto, which refuses to shrink below its content — so the scroll container
   grows to fit the table instead of scrolling it, and the overflow escapes to the page. */
.pm-table-scroll,
.pm-diary-scroll,
.pm-perio-scroll,
.pm-odontogram-scroll {
    overflow-x: auto;
    min-width: 0;
    max-width: 100%;
}

/* The patient sections and the recall bands are tab bars; on a phone they must scroll rather than
   push the page sideways. */
.mud-tabs-tabbar-wrapper { max-width: 100%; }

/* The patient section strip marks its active tab here rather than with MudTabs' sliding underline.
   The slider is positioned by measuring the strip, and once the strip scrolls — which it does at
   eleven sections — it settles under the wrong tab while the correct one is coloured as active. A
   static border cannot be measured wrong. */
.pm-patient-tabs .mud-tab-active {
    border-bottom: 2px solid var(--mud-palette-primary);
    font-weight: 600;
}

/* The minimum width itself is set on the component — MudTabs writes it inline, where a stylesheet
   cannot reach it. This is only the padding that goes with it. */
.pm-patient-tabs .mud-tab {
    padding-left: 12px;
    padding-right: 12px;
}

/* The icon is decoration next to a label that already says the same thing, and it costs about
   32px a tab — over the eleven sections, the difference between the whole record being on screen
   and three of it living behind a scroll arrow. The breakpoint is where the strip with icons stops
   fitting beside the drawer, which is a good deal wider than a laptop; measured, not guessed. */
@media (max-width: 1699.98px) {
    .pm-patient-tabs .mud-tab .mud-icon-root {
        display: none;
    }

    .pm-patient-tabs .mud-tab {
        padding-left: 10px;
        padding-right: 10px;
    }
}

/* ── Timeline (chart history, note history, contact log) ─────────────────────── */
.pm-timeline-item {
    display: flex;
    gap: 12px;
    padding: 10px 0;
    border-bottom: 1px solid var(--mud-palette-divider);
}

.pm-timeline-item:last-child { border-bottom: none; }

.pm-timeline-when {
    flex: 0 0 108px;
    font-size: var(--pm-font-caption);
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

.pm-timeline-body { flex: 1 1 auto; min-width: 0; overflow-wrap: anywhere; }

/* A superseded entry is kept and shown struck through — the clinical record is
   append-only, so a correction never erases what was originally recorded. */
.pm-superseded { text-decoration: line-through; opacity: 0.6; }

/* The medicines on a script. Tabular numerals so a column of doses and quantities lines up when
   a clinician scans down several scripts looking for a change. */
.pm-script-list {
    margin: 6px 0 0;
    padding-left: 18px;
    font-size: 0.875rem;
    font-variant-numeric: tabular-nums;
}

.pm-script-list li { padding: 2px 0; overflow-wrap: anywhere; }

@media (max-width: 600px) {
    .pm-timeline-item { flex-direction: column; gap: 2px; }
    .pm-timeline-when { flex: 0 0 auto; }
}

/* ── Diary / scheduler ───────────────────────────────────────────────────────── */
.pm-diary-scroll { overflow-x: auto; }

.pm-diary {
    display: grid;
    gap: 1px;
    background: var(--mud-palette-divider);
    border: 1px solid var(--mud-palette-divider);
    border-radius: var(--pm-radius-card);
    overflow: hidden;
    min-width: 640px;
}

.pm-diary-head {
    background: var(--mud-palette-background-grey);
    padding: 8px;
    font-weight: 700;
    font-size: var(--pm-font-caption);
    text-align: center;
    white-space: nowrap;
}

.pm-diary-time {
    background: var(--mud-palette-surface);
    padding: 4px 8px;
    font-size: var(--pm-font-micro);
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
    text-align: right;
    white-space: nowrap;
}

.pm-diary-cell {
    background: var(--mud-palette-surface);
    height: 26px;
    position: relative;
}

/* Absolutely positioned and sized by duration, so a 45-minute appointment is visibly half
   again as tall as a 30-minute one. Out of flow on purpose: that keeps every row exactly
   26px, which is what makes the height arithmetic below exact rather than approximate. */
.pm-diary-appt {
    position: absolute;
    inset: 1px 1px auto 1px;
    z-index: 1;
    border-radius: 6px;
    padding: 3px 6px;
    font-size: var(--pm-font-micro);
    line-height: 1.3;
    overflow: hidden;
    cursor: pointer;
    /* White on a saturated appointment-type colour. The type colour is chosen by the
       practice, so this is the one place a literal is correct — it is the contrast
       partner for an arbitrary hue, not a theme decision. */
    color: #fff;
    border: none;
    text-align: left;
    display: block;
}

.pm-diary-appt:focus-visible { outline: 2px solid var(--mud-palette-primary); outline-offset: 1px; }

/* display:block matters. These were inline spans, and text-overflow:ellipsis has no effect on an
   inline box — so neither line ever truncated: they wrapped instead, and the wrap is what got
   sliced by the block's overflow. */
.pm-diary-appt-name {
    display: block;
    font-weight: 700;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.pm-diary-appt-meta {
    display: block;
    opacity: 0.85;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* One half-hour slot is 24px of block, which holds exactly one line. Both facts go on that line,
   the procedure giving up its width first. */
.pm-diary-appt-compact {
    display: flex;
    align-items: baseline;
    gap: 4px;
    white-space: nowrap;
}

.pm-diary-appt-compact .pm-diary-appt-name {
    flex: 0 1 auto;
    min-width: 0;
}

.pm-diary-appt-compact .pm-diary-appt-meta {
    flex: 1 1 auto;
    min-width: 0;
}

/* A cancelled or failed appointment keeps its slot in the record but reads as spent. */
.pm-diary-appt-void { opacity: 0.45; text-decoration: line-through; }

/* ── AI assistant ────────────────────────────────────────────────────────────────
   Colours come from theme tokens throughout, so the panel follows the house theme and
   stays legible in both modes. The two literals are white-on-brand-gradient. */

.pm-ai-root {
    position: fixed;
    right: 1.25rem;
    bottom: 1.25rem;
    z-index: var(--pm-z-assistant);
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 0.75rem;
}

.pm-ai-panel {
    width: min(390px, calc(100vw - 2.5rem));
    max-height: min(560px, calc(100vh - 7rem));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    border-radius: var(--pm-radius-card);
}

.pm-ai-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.75rem 0.875rem;
    background: linear-gradient(135deg,
        var(--mud-palette-primary-darken),
        var(--mud-palette-primary));
    flex-shrink: 0;
}

.pm-ai-header-id { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }

.pm-ai-avatar {
    width: 32px;
    height: 32px;
    border-radius: var(--pm-radius-control);
    background: rgba(255, 255, 255, 0.16);
    border: 1px solid rgba(255, 255, 255, 0.28);
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.pm-ai-avatar-icon { color: #fff; font-size: 18px; }

.pm-ai-title    { font-size: 0.875rem; font-weight: 700; color: #fff; letter-spacing: -0.2px; }
.pm-ai-subtitle { font-size: var(--pm-font-micro); color: rgba(255, 255, 255, 0.78); }
.pm-ai-close    { color: rgba(255, 255, 255, 0.9) !important; }

.pm-ai-messages {
    flex: 1;
    overflow-y: auto;
    padding: 0.875rem;
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    background: var(--mud-palette-background);
}

/* The privacy note sits on a primary tint, so its text is primary — muted grey on a
   coloured surface routinely fails contrast, and grey-on-tint is banned outright. */
.pm-ai-banner {
    display: flex;
    gap: 0.45rem;
    align-items: flex-start;
    padding: 0.5rem 0.625rem;
    border-radius: var(--pm-radius-control);
    font-size: var(--pm-font-caption);
    line-height: 1.5;
    color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary) 24%, transparent);
}

.pm-ai-banner-icon { font-size: 15px; flex-shrink: 0; margin-top: 1px; }
.pm-ai-banner strong { color: var(--mud-palette-text-primary); }

.pm-ai-row { display: flex; align-items: flex-start; gap: 0.5rem; }
.pm-ai-row-user { justify-content: flex-end; }
.pm-ai-row-bot  { justify-content: flex-start; }

.pm-ai-badge {
    width: 26px;
    height: 26px;
    border-radius: var(--pm-radius-control);
    flex-shrink: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: var(--pm-font-micro);
    font-weight: 800;
    color: var(--mud-palette-text-secondary);
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
}

.pm-ai-bubble {
    max-width: 82%;
    padding: 0.55rem 0.75rem;
    border-radius: 12px;
    font-size: 0.8125rem;
    line-height: 1.55;
    overflow-wrap: anywhere;
}

.pm-ai-bubble-bot {
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-divider);
    color: var(--mud-palette-text-primary);
    border-top-left-radius: 3px;
}

.pm-ai-bubble-user {
    background: var(--mud-palette-primary);
    color: var(--mud-palette-primary-text);
    border-top-right-radius: 3px;
}

/* A setup instruction, not an answer — warning-tinted so it reads as an action. */
.pm-ai-bubble-notice {
    background: color-mix(in srgb, var(--mud-palette-warning) 12%, var(--mud-palette-surface));
    border-color: color-mix(in srgb, var(--mud-palette-warning) 40%, transparent);
}

.pm-ai-bubble p { margin: 0 0 0.35rem; }
.pm-ai-bubble p:last-of-type { margin-bottom: 0; }
.pm-ai-bubble .pm-ai-heading { font-weight: 700; margin-top: 0.4rem; }
.pm-ai-bubble .pm-ai-list { margin: 0.25rem 0 0.4rem; padding-left: 1.15rem; }
.pm-ai-bubble .pm-ai-list li { margin-bottom: 0.15rem; }

.pm-ai-bubble code {
    font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
    font-size: 0.9em;
    padding: 1px 4px;
    border-radius: 4px;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 12%, transparent);
}

.pm-ai-time {
    font-size: var(--pm-font-micro);
    text-align: right;
    margin-top: 3px;
    opacity: 0.65;
}

.pm-ai-typing { display: flex; gap: 5px; align-items: center; padding: 0.7rem 0.85rem; }

.pm-ai-dot {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    animation: pm-ai-bounce 1.2s infinite ease-in-out;
}

.pm-ai-dot:nth-child(2) { animation-delay: 0.18s; }
.pm-ai-dot:nth-child(3) { animation-delay: 0.36s; }

@keyframes pm-ai-bounce {
    0%, 60%, 100% { transform: translateY(0);    opacity: 0.55; }
    30%           { transform: translateY(-5px); opacity: 1; }
}

.pm-ai-suggestions {
    padding: 0.5rem 0.75rem;
    border-top: 1px solid var(--mud-palette-divider);
    background: var(--mud-palette-surface);
    flex-shrink: 0;
}

.pm-ai-suggestions-label {
    font-size: var(--pm-font-micro);
    text-transform: uppercase;
    letter-spacing: 0.07em;
    font-weight: 600;
    color: var(--mud-palette-text-secondary);
    margin-bottom: 0.375rem;
}

.pm-ai-suggestions-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0.35rem; }

.pm-ai-suggestion {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    padding: 0.375rem 0.5rem;
    border: 1px solid var(--mud-palette-divider);
    border-radius: var(--pm-radius-control);
    background: transparent;
    color: var(--mud-palette-text-secondary);
    font-family: inherit;
    font-size: var(--pm-font-caption);
    text-align: left;
    cursor: pointer;
    transition: background 0.12s, color 0.12s, border-color 0.12s;
}

.pm-ai-suggestion:hover {
    background: var(--mud-palette-action-default-hover);
    color: var(--mud-palette-text-primary);
    border-color: var(--mud-palette-primary);
}

.pm-ai-suggestion:focus-visible {
    outline: 2px solid var(--mud-palette-primary);
    outline-offset: 1px;
}

.pm-ai-suggestion-icon { font-size: 14px; color: var(--mud-palette-primary); flex-shrink: 0; }

.pm-ai-input {
    display: flex;
    gap: 0.5rem;
    align-items: center;
    padding: 0.625rem 0.75rem;
    border-top: 1px solid var(--mud-palette-divider);
    background: var(--mud-palette-surface);
    flex-shrink: 0;
}

@media (prefers-reduced-motion: reduce) {
    .pm-ai-dot { animation: none; }
}

/* ── Blazor error boundary ───────────────────────────────────────────────────── */
.blazor-error-boundary {
    background: #b32121;
    padding: 1rem;
    color: white;
}

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

#blazor-error-ui {
    color: #fff;
    background: #C62828;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: var(--pm-z-app-banner);
}

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

/* The catalogue's two panels carry their own padding; MudTabs' PanelClass is not a supported
   attribute in this version and the analyzer refuses it, so the padding is set here. */
.pm-catalogue-tabs .mud-tabs-panels {
    padding: 16px;
}

/* ── Body map ────────────────────────────────────────────────────────────────────────────────
   The injury figure. Severity colours are the MudBlazor palette's own error/warning/info-adjacent
   tones rather than literal reds and yellows, so the three bands stay legible in dark mode and
   against the same surfaces every other status chip in the product sits on. */
/* Literal hues rather than palette mixes. The three bands are a fixed vocabulary a clinician
   learns — red is a break, orange is a fracture or a tear, yellow is bruising — so they have to be
   the same three colours on both themes. Mixing the theme's amber towards transparent reads as
   yellow on a light ground and as brown on a dark one, which is a different word. */
:root {
    --pm-injury-severe: #e0342c;
    --pm-injury-severe-edge: #a81f19;
    --pm-injury-significant: #ef7215;
    --pm-injury-significant-edge: #b4520a;
    --pm-injury-superficial: #f2c14e;
    --pm-injury-superficial-edge: #c2952a;
}

.pm-bodymap {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    flex: 1 1 220px;
    min-width: 0;
}

.pm-bodymap svg {
    width: 100%;
    max-width: 190px;
    height: auto;
    /* Without this the figure keeps growing on a wide screen until one patient's arm needs a
       scroll to see, which is the opposite of a glance. */
    max-height: 420px;
}

.pm-bodymap-caption {
    font-size: 0.75rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--mud-palette-text-secondary);
}

.pm-body-region {
    fill: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    stroke: var(--mud-palette-divider);
    stroke-width: 1.2;
    transition: fill 120ms ease, stroke 120ms ease;
}

.pm-body-superficial { fill: var(--pm-injury-superficial); stroke: var(--pm-injury-superficial-edge); }
.pm-body-significant { fill: var(--pm-injury-significant); stroke: var(--pm-injury-significant-edge); }
.pm-body-severe      { fill: var(--pm-injury-severe);      stroke: var(--pm-injury-severe-edge); }

/* Healing keeps its band's colour and loses its solidity, rather than taking a fourth colour the
   legend would then have to explain. */
.pm-body-healing {
    fill-opacity: 0.45;
    stroke-dasharray: 3 2;
}

.pm-bodymap-interactive .pm-body-region {
    cursor: pointer;
}

.pm-bodymap-interactive .pm-body-region:hover {
    stroke: var(--mud-palette-primary);
    stroke-width: 2;
}

.pm-bodymap-views {
    display: flex;
    flex-wrap: wrap;
    gap: 24px;
    justify-content: center;
    /* Without a cap the two figures drift to opposite ends of a wide panel and stop reading as one
       diagram of one person. */
    max-width: 520px;
    margin: 0 auto;
}

.pm-bodymap-legend {
    display: flex;
    flex-wrap: wrap;
    gap: 14px;
    align-items: center;
    font-size: 0.8125rem;
    color: var(--mud-palette-text-secondary);
}

.pm-bodymap-legend span {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.pm-bodymap-swatch {
    width: 12px;
    height: 12px;
    border-radius: 3px;
    display: inline-block;
    flex: 0 0 auto;
}

/* The list beside the figure uses the same three colours, so a chip and the region it refers to
   are recognisably the same fact. */
.pm-injury-chip-severe      { background-color: var(--pm-injury-severe) !important;      color: #fff !important; }
.pm-injury-chip-significant { background-color: var(--pm-injury-significant) !important; color: #fff !important; }
.pm-injury-chip-superficial { background-color: var(--pm-injury-superficial) !important; color: #3a2c00 !important; }

.pm-injury-dot-severe .mud-timeline-item-dot-inner      { background-color: var(--pm-injury-severe) !important; }
.pm-injury-dot-significant .mud-timeline-item-dot-inner { background-color: var(--pm-injury-significant) !important; }
.pm-injury-dot-superficial .mud-timeline-item-dot-inner { background-color: var(--pm-injury-superficial) !important; }
