/* Brand typography. Poppins (Regular 400 and Medium 500) is the MCR brand font, and every
   white-label catalogue font is self-hosted alongside it. All @font-face rules live in the
   generated wwwroot/fonts/catalogue.css (see tools/fetch-fonts.py), so the content security policy
   keeps font-src 'self' with no third-party request. A system default stack is the fallback. */

:root {
    /* System default stack used as the fallback and available as a "System default" option. */
    --brand-system-family: system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    --mud-typography-default-family: 'Poppins', var(--brand-system-family);

    /* Chrome dimensions. MudBlazor derives the content offset and drawer clip from these, so the
       drawer, app bar and main content all resize together. Kept in sync with the MudDrawer Width. */
    --mud-drawer-width-left: 280px;
    --mud-drawer-width-right: 280px;
    --mud-appbar-height: 64px;

    /* Brand accents now derive from the tenant's chosen primary, so every hand-written surface that
       uses them (chips, pills, badges, bands, tints) follows the scheme: green for the MCR default and
       green tenants, blue for a blue tenant, and so on. The literal fallbacks cover the first paint
       before the theme variables resolve. Fixed brand colours (Sea Salt, Mimosa, Carbon Wing) stay
       literal because they are not the primary accent. */
    --brand-brunswick-green: var(--mud-palette-primary, #1C4E4F);
    --brand-brunswick-green-dark: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 80%, #000);
    --brand-cambridge-blue: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 68%, #fff);
    --brand-celadon: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 45%, #fff);
    --brand-mint-cream: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 16%, #fff);
    --brand-sea-salt: #F6FAF9;
    --brand-carbon-wing: #101418;
    --brand-mimosa: #F2B949;
    --brand-gunmetal: #142828;

    /* Spacing rhythm. --gap-lg is the between-cards gap the whole portal uses; --gap-md sits
       inside a card, --gap-sm between tight siblings (a breadcrumb and the title it belongs to).
       These were previously only ever referenced with a literal fallback, so the "token" was a
       fiction and each page picked its own number. They are real now: use them. */
    --gap-sm: 0.5rem;
    --gap-md: 1rem;
    --gap-lg: 1.5rem;

    /* Muted text and hairline borders follow the theme's text colour, not a fixed grey: a fixed
       dark grey (or a dark-on-dark hairline) vanishes on the dark surfaces. */
    --brand-muted: var(--mud-palette-text-secondary, #4a5a5a);
    --brand-hairline: color-mix(in srgb, var(--mud-palette-text-primary, #142828) 15%, transparent);

    /* The primary accent used AS TEXT on a card or panel. The tenant's primary does not flip
       between themes, so raw primary text sinks into a dark surface whenever the scheme is dark;
       mixing with the theme's text colour darkens it on a light card and lightens it on a dark
       one while keeping the brand hue. Use this (never the raw primary) for coloured words. */
    --brand-primary-ink: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 58%, var(--mud-palette-text-primary, #142828));

    /* A soft primary-tinted fill over the theme surface, for hovers and quiet panels, replacing
       fixed light washes (Sea Salt, Mint Cream) that glare in dark mode. */
    --brand-primary-wash: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 8%, var(--mud-palette-surface, #fff));

    /* Lozenge fill: a firmer primary tint than the quiet wash above, so an identity pill
       (a role tag, an attribute chip, a count) reads as a distinct branded object on a card,
       and carries the tenant's colour when they white-label. Paired with --brand-primary-ink text. */
    --brand-primary-lozenge: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 14%, var(--mud-palette-surface, #fff));

    /* One shared eyebrow (uppercase kicker) type system, so every section kicker and group header
       reads the same everywhere. Colour is applied per context: --brand-primary-ink on a light
       surface (a warm, branded kicker) or a light tint on the dark nav drawer. */
    --eyebrow-size: 0.72rem;
    --eyebrow-weight: 600;
    --eyebrow-tracking: 0.1em;

    /* One shared semantic status palette. Every status pill in the portal (booking, order, user,
       feedback, readiness, delivery, availability) draws its colour from these five states, so a
       "good" green and a "waiting" amber are identical on every screen and never drift into the old
       scatter of hardcoded hex. Ink mixes the status hue toward the theme text colour so it stays
       legible on both a light and a dark surface; wash is a translucent tint that sits on any surface. */
    --status-positive-ink: color-mix(in srgb, #1f7a4d 62%, var(--mud-palette-text-primary, #101418));
    --status-positive-wash: color-mix(in srgb, #2e9b63 22%, transparent);
    --status-warning-ink: color-mix(in srgb, #b57e12 64%, var(--mud-palette-text-primary, #101418));
    --status-warning-wash: color-mix(in srgb, #f2b949 28%, transparent);
    --status-negative-ink: color-mix(in srgb, #b23b40 62%, var(--mud-palette-text-primary, #101418));
    --status-negative-wash: color-mix(in srgb, #d1434b 18%, transparent);
    --status-info-ink: color-mix(in srgb, #2f6f95 62%, var(--mud-palette-text-primary, #101418));
    --status-info-wash: color-mix(in srgb, #4084af 20%, transparent);
    --status-neutral-ink: var(--mud-palette-text-secondary, #4a5a5a);
    --status-neutral-wash: color-mix(in srgb, var(--mud-palette-text-primary, #101418) 12%, transparent);

    /* Spacing scale (a 4px base) for a consistent rhythm across hand-written CSS. */
    --space-1: 0.25rem;
    --space-2: 0.5rem;
    --space-3: 0.75rem;
    --space-4: 1rem;
    --space-5: 1.5rem;
    --space-6: 2rem;

    /* Radii and elevation. */
    --radius-sm: 0.5rem;
    --radius-md: 0.75rem;
    --radius-lg: 14px;
    --shadow-card: 0 1px 3px rgba(16, 20, 24, 0.08);

    /* A comfortable reading and form width for admin surfaces. */
    --content-max: 46rem;
}

html, body {
    font-family: var(--mud-typography-default-family);
}

/* Blazor moves keyboard focus to the page heading after each navigation so screen readers announce
   the new page. Headings are not interactive, so the browser's focus ring on a programmatically
   focused heading reads as an error (it looks like selected text). Suppress it; interactive controls
   keep their focus indicator. */
h1:focus,
h1:focus-visible,
h2:focus,
h2:focus-visible,
[tabindex="-1"]:focus,
[tabindex="-1"]:focus-visible {
    outline: none !important;
    box-shadow: none !important;
}

/* Sign-in and other static-SSR forms use native inputs for reliable form-model binding. */
.form-field {
    display: flex;
    flex-direction: column;
    margin-bottom: 1rem;
}

.form-field label {
    font-weight: 500;
    margin-bottom: 0.25rem;
}

.form-field input {
    padding: 0.6rem 0.75rem;
    border: 1px solid var(--brand-cambridge-blue);
    border-radius: 6px;
    font-size: 1rem;
    font-family: inherit;
}

.form-field input:focus-visible {
    outline: 2px solid var(--brand-brunswick-green);
    outline-offset: 1px;
}

.validation-message {
    color: #b00020;
    font-size: 0.85rem;
    margin-top: 0.25rem;
}

/* Native selects and inputs used on the interactive filter bars (Book, Find, analytics and so on)
   carry the mud-input-root class as an ad-hoc control. Element-qualified selectors style only these
   native controls, never a real MudBlazor input (whose mud-input-root is on a div). One consistent,
   tidy control across every page. */
input.mud-input-root,
select.mud-input-root {
    height: 40px;
    padding: 0 0.7rem;
    font: inherit;
    color: var(--mud-palette-text-primary, #101418);
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-inputs, #C4D3CC);
    border-radius: 8px;
    min-width: 0;
    box-sizing: border-box;
}

select.mud-input-root {
    cursor: pointer;
}

input.mud-input-root:hover,
select.mud-input-root:hover {
    border-color: #9FB6AC;
}

input.mud-input-root:focus-visible,
select.mud-input-root:focus-visible {
    outline: none;
    border-color: var(--brand-brunswick-green); /* Brunswick Green */
    box-shadow: 0 0 0 3px rgba(28, 78, 79, 0.15);
}

/* Branded Blazor reconnection overlay. Hidden until the interactive circuit drops; Blazor toggles
   the components-reconnect-* classes on the modal to move between reconnecting, failed and rejected
   states. The mark loads under img-src 'self'; the buttons are wired from js/reconnect.js. */
#components-reconnect-modal {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 2000;
    align-items: center;
    justify-content: center;
    background: rgba(16, 20, 24, 0.55); /* Carbon Wing at 55% */
}

#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-rejected {
    display: flex;
}

.reconnect__card {
    max-width: 20rem;
    padding: 2rem 2.5rem;
    text-align: center;
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 8px 30px rgba(16, 20, 24, 0.25);
    font-family: 'Poppins', system-ui, sans-serif;
    color: #101418; /* Carbon Wing */
}

.reconnect__mark {
    display: block;
    height: 3rem;
    width: auto;
    max-width: 100%;
    margin: 0 auto 1rem;
}

.reconnect__spinner {
    display: block;
    width: 96px;
    height: 96px;
    margin: 0 auto 1rem;
}

.reconnect__msg {
    display: none;
    margin: 0;
}

#components-reconnect-modal.components-reconnect-show .reconnect__msg--show,
#components-reconnect-modal.components-reconnect-failed .reconnect__msg--failed,
#components-reconnect-modal.components-reconnect-rejected .reconnect__msg--rejected {
    display: block;
}

.reconnect__btn {
    margin-top: 0.75rem;
    padding: 0.5rem 1.25rem;
    font: inherit;
    font-weight: 500;
    color: #F6FAF9; /* Sea Salt */
    background: var(--brand-brunswick-green); /* Brunswick Green */
    border: none;
    border-radius: 999px;
    cursor: pointer;
}

.reconnect__btn:hover {
    background: var(--brand-brunswick-green-dark);
}

/* ---- Shared light-surface buttons (Home's scoped hero variants override on the home page) ---- */
.home-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.55rem 1.2rem;
    font-family: inherit;
    font-size: 0.95rem;
    font-weight: 500;
    border-radius: 999px;
    border: 1px solid transparent;
    cursor: pointer;
    text-decoration: none;
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

.home-btn:disabled {
    opacity: 0.62;
    cursor: not-allowed;
}

.home-btn--primary {
    color: var(--mud-palette-primary-text, #F6FAF9);
    background: var(--mud-palette-primary, #1C4E4F);
}

.home-btn--primary:hover:not(:disabled) {
    filter: brightness(0.92);
    transform: translateY(-1px);
}

/* The one bright call to action on a screen: the tenant's secondary scheme colour with its
   guaranteed-contrast on-secondary text, matching the "Order for a Space" pill in the drawer, so
   the same accent leads the user from the nav to the finishing action. A gentle top-highlight
   gradient plus a lighter shadow soften the fill so it reads as inviting on light surrounds
   (the drawer pill sits on the dark drawer and already reads light; the CTA on a light basket
   panel would otherwise feel heavier despite the same base). Use at most once per view. */
.home-btn--cta {
    color: var(--mud-palette-secondary-text, #2a1f00);
    background: linear-gradient(
        180deg,
        color-mix(in srgb, var(--mud-palette-secondary, var(--brand-mimosa, #F2B949)) 86%, #ffffff),
        var(--mud-palette-secondary, var(--brand-mimosa, #F2B949))
    );
    font-weight: 700;
    box-shadow: 0 2px 8px rgba(16, 20, 24, 0.16);
}

.home-btn--cta:hover:not(:disabled) {
    filter: brightness(1.06);
    box-shadow: 0 4px 14px rgba(16, 20, 24, 0.22);
    transform: translateY(-1px);
}

.home-btn--ghost {
    /* Blend the brand colour toward the theme's text colour so the label keeps a brand tint but stays
       legible in both light and dark (the tenant's primary colour does not flip between themes, so
       dark-green text on a dark row would otherwise vanish). */
    color: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 55%, var(--mud-palette-text-primary, #101418));
    background: transparent;
    border-color: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 40%, var(--mud-palette-lines-default, transparent));
}

.home-btn--ghost:hover:not(:disabled) {
    border-color: var(--mud-palette-primary, #1C4E4F);
    /* A subtle brand-tinted wash that works on a light or a dark surface, not a fixed light fill. */
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 12%, transparent);
}

/* Danger: destructive actions (cancel a booking, delete, deactivate). Outlined, not shouting. */
.home-btn--danger {
    /* Keep it clearly red, but lift the lightness toward the theme text colour so it reads on a dark
       row too (a fixed dark red would sink into a dark surface). */
    color: color-mix(in srgb, #e5484d 62%, var(--mud-palette-text-primary, #101418));
    background: transparent;
    border-color: rgba(179, 38, 30, 0.45);
}

.home-btn--danger:hover:not(:disabled) {
    border-color: #e5484d;
    background: color-mix(in srgb, #e5484d 16%, transparent);
}

/* Success: a positive confirm (confirm a hold). */
/* Positive actions (Confirm, Mark ready) follow the tenant's brand colour, so a blue-scheme tenant
   never sees a stray green button. Derives from the MudBlazor palette. */
.home-btn--success {
    color: var(--mud-palette-primary-text, #F6FAF9);
    background: var(--mud-palette-primary, #1C4E4F);
}

.home-btn--success:hover:not(:disabled) {
    filter: brightness(1.08);
    transform: translateY(-1px);
}

/* A compact size for row actions, so tables read as neat, consistent buttons not stray links. */
.home-btn--sm {
    padding: 0.3rem 0.8rem;
    font-size: 0.85rem;
}

/* A consistent right-aligned cluster of row actions. Fills the cell (not inline-flex) so the buttons
   actually anchor to the right edge rather than hugging their content on the left. */
.row-actions {
    display: flex;
    width: 100%;
    align-items: center;
    gap: 0.4rem;
    flex-wrap: wrap;
    justify-content: flex-end;
}

/* Booking row actions: a right-anchored group. Wraps when the cell is narrow so a busy row never
   pushes buttons off the edge of the table. Confirm and other leading buttons sit first (left),
   Amend and Cancel pin to the right edge; if the buttons wrap onto a second line they still
   right-align. The leading .cal-links sub-group is small and rides at the far left of the row. */
.booking-actions {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: 0.4rem;
    margin-left: auto;
}

.booking-actions .cal-links {
    margin-right: auto;
}

/* The Add-food-to-a-booking shortcut list on /order: each row names a booking and offers a
   one-click deep link to /order?booking=<id>. Compact and unobtrusive, so the standalone flow
   below still reads as the main path. */
.order-shortcut-list {
    list-style: none;
    padding: 0;
    margin: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.order-shortcut {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--brand-hairline);
    border-radius: 10px;
    background: var(--brand-sea-salt);
}

.order-shortcut__meta {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
}

/* Calendar column: small, tidy, rounded icon buttons (iCal and Google) in place of text links. */
.cal-links {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.35rem;
}

/* The .ics link reads as a calendar with a small download cue tucked into its corner, so it looks
   like "save this to my calendar" rather than a bare download arrow. */
.cal-link--download {
    position: relative;
}

.cal-link--download .cal-link__badge {
    position: absolute;
    right: 0;
    bottom: 0;
    width: 0.95rem;
    height: 0.95rem;
    background: var(--brand-sea-salt);
    border-radius: 50%;
}

.cal-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border-radius: 8px;
    color: var(--brand-brunswick-green);
    background: var(--brand-sea-salt);
    border: 1px solid var(--brand-hairline);
    transition: background 0.15s ease, border-color 0.15s ease;
}

.cal-link:hover {
    border-color: var(--brand-cambridge-blue);
    background: var(--brand-mint-cream, #D7E7E1);
}

.cal-link:focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
}

/* The user-menu "Show welcome guide" button, styled to read exactly like the other menu links
   (which are anchors padded 0.65rem 1.25rem at 0.95rem in the scoped layout CSS). */
.usermenu__link-btn {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.65rem 1.25rem;
    font: inherit;
    font-size: 0.95rem;
    color: inherit;
    background: none;
    border: none;
    cursor: pointer;
}

.usermenu__link-btn:hover {
    background: var(--brand-hairline);
}

/* The idle-timeout warning (idle-timeout.js). Same shape as the welcome overlay, theme-aware so it
   reads in light and dark. */
.idle-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1600;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(16, 20, 24, 0.55);
    /* Outside MudLayout, so set the brand font concretely (see .welcome-overlay). */
    font-family: 'Poppins', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

.idle-overlay--open {
    display: flex;
}

.idle-overlay__card {
    width: 100%;
    max-width: 28rem;
    padding: 2rem;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, #101418);
    border-radius: 14px;
    box-shadow: 0 12px 44px rgba(16, 20, 24, 0.3);
}

.idle-overlay__title {
    margin: 0 0 0.75rem;
    font-size: 1.35rem;
    font-weight: 500;
}

.idle-overlay__body {
    margin: 0 0 1.5rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.idle-overlay__actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

/* The welcome guide overlay. Hidden until the open class is added (on demand or on first sign-in).
   It renders outside MudLayout, so it sets the brand font as a concrete stack (not the MudBlazor
   typography variable, which the theme provider can leave empty, dropping the text to the browser
   serif). This is house onboarding content, so the brand Poppins is correct regardless of tenant. */
.welcome-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1500;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(16, 20, 24, 0.55);
    font-family: 'Poppins', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
}

.welcome-overlay--open {
    display: flex;
}

.welcome-overlay__card {
    position: relative;
    width: 100%;
    max-width: 30rem;
    padding: 2rem;
    background: #fff;
    border-radius: 14px;
    box-shadow: 0 12px 44px rgba(16, 20, 24, 0.3);
}

.welcome-overlay__close {
    position: absolute;
    top: 0.75rem;
    right: 0.75rem;
    display: inline-flex;
    padding: 0.35rem;
    color: #3f4b4a;
    background: none;
    border: none;
    border-radius: 8px;
    cursor: pointer;
}

.welcome-overlay__close:hover {
    background: rgba(20, 40, 40, 0.08);
}

.welcome-overlay__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: 0.5rem;
    color: var(--brand-brunswick-green);
    background: var(--brand-mint-cream, #D7E7E1);
    border-radius: 999px;
}

.welcome-overlay__title {
    margin: 0 0 1rem;
    font-size: 1.35rem;
    font-weight: 500;
    color: var(--brand-carbon-wing);
}

.welcome-overlay__list {
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.7rem;
}

.welcome-overlay__list li {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    font-size: 0.92rem;
    line-height: 1.45;
    color: #3f4b4a;
}

/* Tint the leading icon with the tenant accent, and hold it steady against the first line of text. */
.welcome-overlay__list li .mud-icon-root {
    flex: 0 0 auto;
    margin-top: 0.1rem;
    color: var(--brand-brunswick-green);
}

.welcome-overlay__actions {
    display: flex;
    justify-content: flex-end;
}

/* A room's description, shown to a booker when they pick a room. */
.book-room-desc {
    margin: 0;
    padding: 0.75rem 1rem;
    font-size: 0.9rem;
    line-height: 1.5;
    color: var(--brand-carbon-wing);
    background: var(--brand-sea-salt);
    border-left: 3px solid var(--brand-cambridge-blue);
    border-radius: 0 8px 8px 0;
}

/* ---- Appearance: visual colour-scheme picker ---- */
.scheme-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(8rem, 1fr));
    gap: 0.85rem;
    margin-bottom: 0.5rem;
}

.scheme-card {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.4rem;
    background: transparent;
    border: 2px solid transparent;
    border-radius: 12px;
    cursor: pointer;
    text-align: center;
}

.scheme-card:hover .scheme-card__swatch {
    box-shadow: 0 4px 14px rgba(16, 20, 24, 0.16);
}

.scheme-card--on {
    border-color: var(--brand-carbon-wing);
}

.scheme-card__swatch {
    position: relative;
    display: block;
    width: 100%;
    height: 3.4rem;
    border-radius: 10px;
    border: 1px solid rgba(16, 20, 24, 0.15);
    overflow: hidden;
}

/* A secondary-colour stripe down the right so each card reads as a two-tone scheme, not a flat block. */
.scheme-card__accent {
    position: absolute;
    top: 0;
    right: 0;
    bottom: 0;
    width: 34%;
}

.scheme-card__check {
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
}

.scheme-card__name {
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

/* ---- Estate (rooms and attributes) administration ---- */
.estate__toolbar {
    margin-bottom: 1rem;
}

.estate__grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4) var(--space-5);
    align-items: start;
    margin-bottom: var(--space-4);
}

/* A subtle in-label continuation for optional or explanatory copy, so a longer field label reads
   as one label rather than wrapping loudly against the primary word. Sits inline with the primary
   label text and takes the secondary text colour. */
.estate__label-hint {
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-weight: 400;
}

@media (max-width: 40rem) {
    .estate__grid {
        grid-template-columns: 1fr;
    }
}

/* Theme text colour, never fixed Gunmetal: a fixed dark label vanishes on the dark surfaces. */
.estate__field {
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.9rem;
    color: var(--mud-palette-text-primary, #142828);
}

/* Reserve a consistent vertical rhythm for the field label so a single-line and a wrapped label
   still line their inputs up across a row. Applies to the direct-child label span only, so nested
   spans (hints inside a hint, for example) do not inherit the min-height. */
.estate__field > span:first-child {
    min-height: 2.4em;
    display: block;
    line-height: 1.2;
}

.estate__field--check {
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    align-self: end;
}

/* A grouped set of related switches (feature flags, MFA methods). Legend is a small uppercase
   label that reads as a section header without stealing the eye. */
.estate__fieldset {
    border: 1px solid var(--mud-palette-lines-default, rgba(20, 40, 40, 0.12));
    border-radius: 8px;
    padding: 0.75rem 1rem 0.85rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.estate__fieldset legend {
    padding: 0 0.35rem;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    text-transform: uppercase;
    letter-spacing: 0.02em;
}

/* A scrollable list of checkboxes inside an estate field (for example the cost-centre picker on the
   invite dialog), so a long list does not stretch the modal. */
.estate__checks {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
    max-height: 12rem;
    overflow-y: auto;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--mud-palette-lines-inputs, #c9d6d1);
    border-radius: 8px;
}

.estate__check {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.9rem;
    font-weight: 400;
}

.estate__check input {
    flex: 0 0 auto;
}

/* The full-modal-width variant (the invite dialog's cost centres): the list uses the whole row and
   flows into two columns on wide screens, so a long catalogue is neither squashed nor a tall well. */
.estate__checks--wide {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(16rem, 1fr));
    gap: 0.35rem 1rem;
    max-height: 14rem;
}

/* A full-width row inside the two-column estate grid, for a checkbox whose explainer needs the
   whole line (the Edit menu service-window rule) rather than a skinny half column. */
.estate__field--full {
    grid-column: 1 / -1;
}

/* A footer action pushed to the left, away from the primary Cancel/Save cluster on the right, for a
   secondary or state-changing action (for example Deactivate site) inside a modal footer. */
.modal-footer__lead {
    margin-right: auto;
}

/* A cluster of left-aligned footer actions (for example Deactivate + Delete) sitting together. */
.modal-footer__group {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.estate__input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.5rem 0.65rem;
    font: inherit;
    border: 1px solid var(--mud-palette-lines-inputs, rgba(20, 40, 40, 0.25));
    border-radius: var(--radius-sm);
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
}

.estate__input:focus {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 1px;
    border-color: var(--brand-cambridge-blue);
}

/* ---- Branded checkbox, applied to every native checkbox across the app ----
   A single global restyle so every on/off box (working days, "Active", "Show cancelled", room
   select, quick-edit toggles, resource pills, diary and blackout) reads the same: a rounded box that
   fills Brunswick Green with a white tick when ticked. MudBlazor draws its own SVG checkbox from a
   hidden input carrying a mud- class, so that input is excluded and left to Mud. */
input[type="checkbox"]:not([class*="mud-"]) {
    appearance: none;
    -webkit-appearance: none;
    -moz-appearance: none;
    box-sizing: border-box;
    flex: 0 0 auto;
    width: 1.15rem;
    height: 1.15rem;
    margin: 0;
    padding: 0;
    border: 1.5px solid var(--mud-palette-lines-inputs, rgba(20, 40, 40, 0.4));
    border-radius: 5px;
    background-color: var(--mud-palette-surface, #fff);
    display: inline-grid;
    place-content: center;
    vertical-align: middle;
    cursor: pointer;
    transition: background-color 0.15s ease, border-color 0.15s ease;
}

input[type="checkbox"]:not([class*="mud-"])::before {
    content: "";
    width: 0.7rem;
    height: 0.7rem;
    transform: scale(0);
    transform-origin: center;
    transition: transform 0.12s ease-in-out;
    background-color: #fff;
    /* A tick drawn with clip-path, so there is no image dependency and it scales crisply. */
    clip-path: polygon(14% 44%, 0 65%, 43% 100%, 100% 16%, 80% 0%, 43% 62%);
}

input[type="checkbox"]:not([class*="mud-"]):checked {
    background-color: var(--brand-brunswick-green);
    border-color: var(--brand-brunswick-green);
}

input[type="checkbox"]:not([class*="mud-"]):checked::before {
    transform: scale(1);
}

input[type="checkbox"]:not([class*="mud-"]):hover:not(:disabled) {
    border-color: var(--brand-cambridge-blue);
}

input[type="checkbox"]:not([class*="mud-"]):focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
}

input[type="checkbox"]:not([class*="mud-"]):disabled {
    opacity: 0.5;
    cursor: default;
}

/* An inline checkbox-and-label pairing (for example the "Private meeting" toggle on the book and
   amend forms): the box and its label sit on one line, with the field hint beneath. */
.book-check {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-weight: 500;
}

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

.estate__form-title {
    margin: 0 0 0.75rem;
    font-size: 1.1rem;
    font-weight: 500;
    /* Keeps a green identity but stays legible in dark mode: mixing with the theme's text-primary
       (which flips dark to light) darkens it on a light card and lightens it on a dark one. */
    color: color-mix(in srgb, var(--brand-cambridge-blue) 45%, var(--mud-palette-text-primary, var(--brand-carbon-wing)));
}

.estate__sub {
    margin: 1rem 0 0.25rem;
    font-size: 1rem;
    color: color-mix(in srgb, var(--brand-cambridge-blue) 45%, var(--mud-palette-text-primary, var(--brand-carbon-wing)));
}

.estate__hint {
    margin: 0 0 0.5rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

/* Inline links inside a hint paragraph MUST stay visually distinct from the
   surrounding secondary text without relying on colour alone (WCAG 1.4.1). */
.estate__hint a {
    text-decoration: underline;
}

.estate__hint--warn {
    background: var(--status-warning-wash);
    color: var(--status-warning-ink);
    padding: 0.25rem 0.5rem;
    border-radius: 4px;
    margin-block-start: 0.5rem;
}

.estate__building-head {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    flex-wrap: wrap;
    margin-bottom: 0.75rem;
}

.estate__building-name {
    font-size: 1.1rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.estate__building-code {
    margin-left: 0.5rem;
    padding: 0.1rem 0.5rem;
    font-size: 0.75rem;
    border-radius: 999px;
    background: var(--brand-mint-cream);
    color: var(--brand-brunswick-green);
}

.estate__building-site {
    margin-left: 0.5rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.estate__table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
    /* Tabular figures so digits line up column to column and do not jitter as values change. */
    font-variant-numeric: tabular-nums;
}

.estate__table th,
.estate__table td {
    text-align: left;
    padding: 0.5rem 0.6rem;
    border-bottom: 1px solid rgba(20, 40, 40, 0.1);
}

.estate__table th {
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-weight: 500;
}

.estate__row-actions,
.estate__matrix-cell {
    white-space: nowrap;
}

.estate__empty {
    margin: 0.25rem 0;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-size: 0.9rem;
}

.estate__attr-add {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.estate__attr-add .estate__input {
    flex: 1;
}

.estate__attr-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.estate__attr-list li {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.4rem 0;
    border-bottom: 1px solid rgba(20, 40, 40, 0.1);
}

.estate__matrix-scroll {
    overflow-x: auto;
}

.estate__days {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1rem;
    margin-bottom: 1rem;
}

.estate__day {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.9rem;
    color: var(--mud-palette-text-primary, #142828);
}

.accept__totp {
    margin: 0.5rem 0 1rem;
    padding: 0.75rem 1rem;
    background: #F6FAF9;
    border: 1px solid rgba(20, 40, 40, 0.15);
    border-radius: 0.5rem;
    word-break: break-all;
}

/* ---- Booking improvements: hold countdown, overlap warning, diary notes ---- */
.hold-countdown {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.05rem 0.45rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
}

.hold-countdown--green { background: var(--status-positive-wash); color: var(--status-positive-ink); }
.hold-countdown--amber { background: var(--status-warning-wash); color: var(--status-warning-ink); }
.hold-countdown--red { background: var(--status-negative-wash); color: var(--status-negative-ink); }
.hold-countdown--expired { background: var(--status-neutral-wash); color: var(--status-neutral-ink); }

.book-overlap {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin-bottom: 1rem;
    padding: 0.6rem 0.9rem;
    background: #FDF3D9;
    border: 1px solid #F2B949;
    border-radius: 0.5rem;
    color: #142828;
    font-size: 0.9rem;
}

/* A red-tinted banner listing what must be completed before a booking can be placed. Theme-aware so it
   reads on a light or a dark form. */
.book-validation {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin-bottom: 1rem;
    padding: 0.65rem 0.9rem;
    background: color-mix(in srgb, #e5484d 12%, var(--mud-palette-surface));
    border: 1px solid color-mix(in srgb, #e5484d 45%, transparent);
    border-radius: 0.6rem;
    color: var(--mud-palette-text-primary);
    font-size: 0.9rem;
}

.book-validation .mud-icon-root {
    color: #e5484d;
    flex: 0 0 auto;
    margin-top: 0.1rem;
}

/* A field flagged as incomplete or invalid on a blocked submit: a clear red edge that clears the moment
   the field is put right. */
.estate__input--invalid {
    border-color: #e5484d !important;
    box-shadow: 0 0 0 2px color-mix(in srgb, #e5484d 22%, transparent);
}

/* ---- Searchable select ----
   The portal's selection control for a long list: the estate__input look on a button, with a search
   box and a list panel below it. Every colour comes from the theme (the Mud palette variables, and
   the --brand-muted and --brand-hairline tokens that follow the theme's text colour), so a tenant
   scheme and dark mode both reach it. No entry animation, so there is nothing to exempt under
   prefers-reduced-motion. */
.searchable-select {
    position: relative;
    width: 100%;
}

.searchable-select__trigger {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    text-align: left;
    cursor: pointer;
}

.searchable-select__trigger:disabled {
    cursor: not-allowed;
    opacity: 0.6;
}

.searchable-select__value {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.searchable-select__value--empty {
    color: var(--brand-muted);
}

/* The same downward triangle a native select shows, drawn in the theme's text colour. */
.searchable-select__caret {
    flex: 0 0 auto;
    width: 0;
    height: 0;
    border-left: 0.3rem solid transparent;
    border-right: 0.3rem solid transparent;
    border-top: 0.35rem solid currentColor;
    opacity: 0.7;
}

/* A transparent sheet catching the outside click. Below the panel, above the page. */
.searchable-select__sheet {
    position: fixed;
    inset: 0;
    z-index: 1800;
}

/* Above the sheet, and above the modal overlay (1400) so the panel works inside a ModalDialog. */
.searchable-select__panel {
    position: absolute;
    z-index: 1801;
    top: calc(100% + 0.25rem);
    left: 0;
    right: 0;
    display: flex;
    flex-direction: column;
    max-height: 20rem;
    overflow: hidden;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
    border: 1px solid var(--brand-hairline);
    border-radius: var(--radius-sm);
    box-shadow: 0 10px 32px rgba(16, 20, 24, 0.22);
}

.searchable-select__search {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.5rem;
    border-bottom: 1px solid var(--brand-hairline);
}

.searchable-select__search .mud-icon-root {
    flex: 0 0 auto;
    color: var(--brand-muted);
}

.searchable-select__search-input {
    flex: 1 1 auto;
    min-width: 0;
    font: inherit;
    padding: 0.35rem 0.5rem;
    border: 1px solid var(--mud-palette-lines-inputs, rgba(20, 40, 40, 0.25));
    border-radius: var(--radius-sm);
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
}

.searchable-select__search-input:focus {
    outline: 2px solid var(--mud-palette-primary, var(--brand-cambridge-blue));
    outline-offset: 1px;
}

.searchable-select__list {
    overflow-y: auto;
    padding: 0.25rem;
}

.searchable-select__option {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.45rem 0.6rem;
    border-radius: var(--radius-sm);
    cursor: pointer;
}

.searchable-select__option:hover,
.searchable-select__option--active {
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 12%, transparent);
}

.searchable-select__option--chosen {
    font-weight: 500;
}

.searchable-select__option--disabled {
    cursor: not-allowed;
    color: var(--brand-muted);
}

.searchable-select__option--disabled:hover {
    background: none;
}

/* The group heading, standing in for an optgroup label (a site's name above its buildings). */
.searchable-select__group {
    margin: 0.4rem 0 0.15rem;
    padding: 0 0.6rem;
    font-size: 0.78rem;
    font-weight: 500;
    letter-spacing: 0.03em;
    text-transform: uppercase;
    color: var(--brand-muted);
}

.searchable-select__empty {
    margin: 0;
    padding: 0.75rem 0.6rem;
    color: var(--brand-muted);
}

/* The multi-selection tick box. Decorative: aria-selected on the row carries the state. */
.searchable-select__box {
    flex: 0 0 auto;
    width: 1rem;
    height: 1rem;
    border: 1px solid var(--mud-palette-lines-inputs, rgba(20, 40, 40, 0.25));
    border-radius: 0.2rem;
}

.searchable-select__box--on {
    border-color: var(--mud-palette-primary, #1C4E4F);
    background: var(--mud-palette-primary, #1C4E4F);
    box-shadow: inset 0 0 0 2px var(--mud-palette-surface, #fff);
}

/* A quiet, non-alarming note under the date when the venue is closed that day (a closure, a
   non-working day, or the room out of use). Muted, not a red banner: it explains the greyed times. */
.book-closed-note {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.4rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.diary-note {
    display: inline-flex;
    align-items: center;
    gap: 0.2rem;
    max-width: 16rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    vertical-align: middle;
}

.grid-cell--outofuse {
    background: repeating-linear-gradient(45deg, #eee, #eee 8px, #e3e3e3 8px, #e3e3e3 16px);
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-size: 0.8rem;
    text-align: center;
    font-style: italic;
}

.book-resources {
    display: flex;
    flex-wrap: wrap;
    gap: 0.4rem 1rem;
}

.book-resource {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    font-size: 0.9rem;
}

/* The page behind an open provider-free dialog must not scroll. Applied by js/dialogs.js
   while any .modal-overlay, .held-overlay or .bugreport-overlay is open. */
body.dialog-open {
    overflow: hidden;
}

/* ---- Shared modal overlay (global copy so pages beyond Book can use it) ---- */
.held-overlay {
    position: fixed;
    inset: 0;
    z-index: 1400;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1rem;
    background: rgba(16, 20, 24, 0.55);
}

/* The theme surface, not fixed white: the title and ghost action follow the theme's text colour,
   so a fixed white card would render them invisibly in dark mode. */
.held-dialog {
    max-width: 28rem;
    width: 100%;
    padding: 1.75rem;
    background: var(--mud-palette-surface, #fff);
    border-radius: 14px;
    box-shadow: 0 12px 40px rgba(16, 20, 24, 0.28);
    text-align: center;
}

/* A wider variant of the held-dialog for content that reads as a list rather than a single
   sentence: the Order again modal shows a list of past orders and a two-column preview, both of
   which need horizontal room to breathe. */
.held-dialog--wide {
    max-width: 40rem;
    text-align: left;
}

.held-dialog__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: 0.5rem;
    border-radius: 999px;
    color: var(--brand-brunswick-green);
    background: var(--brand-mint-cream);
}

.held-dialog__title {
    margin: 0 0 0.5rem;
    font-size: 1.35rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.held-dialog__body {
    margin: 0 0 1rem;
    font-size: 0.95rem;
    color: var(--brand-muted, #3f4b4a);
    line-height: 1.45;
}

.held-dialog__actions {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.beg-dialog__message {
    width: 100%;
    padding: 0.6rem 0.75rem;
    font: inherit;
    border: 1px solid rgba(20, 40, 40, 0.25);
    border-radius: 0.5rem;
    resize: vertical;
}

.beg-dialog__message:focus {
    outline: 2px solid var(--brand-cambridge-blue);
    border-color: var(--brand-cambridge-blue);
}

.beg-dialog__error {
    margin: 0 0 0.5rem;
    color: #b3261e;
    font-size: 0.85rem;
}

.diary-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.75rem 1.25rem;
    margin-bottom: 1rem;
}

.diary-toolbar .estate__input {
    min-width: 16rem;
}

.diary-toolbar__check {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    color: var(--mud-palette-text-primary, #142828);
}

/* =====================================================================
   Frontend-design pass. Executes the pinned MCR / Symphony Spaces brand with
   craft: a Poppins type scale, one disciplined signature (a Brunswick
   Green accent rule at every page title), and the accessibility floor.
   Brand colours are load-bearing; white-labelled surfaces stay driven by
   the MudBlazor palette and are untouched here.
   ===================================================================== */

/* Headings honour the tenant's white-label font. The body uses --mud-typography-default-family (the
   tenant font); MudBlazor's per-scale families (h4-family and so on) do not always resolve to it, so
   pin every heading to the same variable. This keeps every page title and card heading on the tenant
   font, matching the content beneath it, whatever font the tenant has chosen. */
.mud-typography-h1,
.mud-typography-h2,
.mud-typography-h3,
.mud-typography-h4,
.mud-typography-h5,
.mud-typography-h6,
.mcr-page-header__text {
    font-family: var(--mud-typography-default-family);
}

/* Type scale for hand-written portal content. */
.mcr-page-header__text {
    position: relative;
    padding-left: 0.9rem;
    font-weight: 500;
    letter-spacing: -0.015em;
    line-height: 1.15;
}

/* The signature: a short accent rule beside every page title. */
.mcr-page-header__text::before {
    content: "";
    position: absolute;
    left: 0;
    top: 0.18em;
    bottom: 0.18em;
    width: 4px;
    border-radius: 2px;
    background: var(--brand-brunswick-green);
}

.mcr-page-header__description {
    /* Wide enough that a working intro (Catering orders, Users) sits in two or three lines
       rather than a tall stack that pushes the page content down. */
    max-width: 90ch;
    line-height: 1.5;
}

/* The header's action slot is a flex row so its controls sit inline and vertically centred,
   whether each is a <button> or an <a> styled as a button (an anchor and a button do not share a
   baseline, so without this they misalign). The phone rule below only reorders it. */
.mcr-page-header__actions {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Section titles stay quiet: weight and rhythm only, no competing accent. */
.home-heading,
.estate__form-title {
    letter-spacing: -0.005em;
}

/* Content cards: a soft, single-source elevation over the flat outline. */
.estate .mud-paper-outlined,
.mud-main-content .mud-paper-outlined {
    box-shadow: var(--shadow-card);
    border-color: var(--brand-hairline);
    border-radius: var(--radius-md);
}

/* Table headers read as small labels, not shouting caps. */
.estate__table th {
    font-size: 0.78rem;
    letter-spacing: 0.02em;
    text-transform: none;
    color: var(--brand-muted);
}

/* Buttons: a calm, consistent lift shared across the portal. */
.home-btn--primary:hover:not(:disabled) {
    box-shadow: 0 2px 10px rgba(28, 78, 79, 0.25);
}

/* Accessibility floor: a visible brand focus ring on every interactive
   control, and motion that respects the reader's preference. */
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
    border-radius: 3px;
}

/* Attribute chips: a tidy, wrapping set of large tap targets, used for room-attribute editing and
   the "must have" booking filter, so many attributes stay neat instead of a cramped checkbox row. */
.attr-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.6rem;
}

.attr-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-height: 44px;
    padding: 0.5rem 0.95rem;
    font-size: 0.92rem;
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 999px;
    cursor: pointer;
    user-select: none;
    transition: border-color 0.15s ease, background 0.15s ease;
}

.attr-chip:hover {
    border-color: var(--brand-cambridge-blue);
}

.attr-chip input {
    width: 1.15rem;
    height: 1.15rem;
    accent-color: var(--brand-brunswick-green);
}

.attr-chip--on {
    border-color: var(--mud-palette-primary, var(--brand-brunswick-green));
    /* A tint of the tenant primary over the theme surface, so the "on" state reads in both light and
       dark mode rather than staying a fixed pale green. */
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 18%, var(--mud-palette-surface, #fff));
}

/* A read-only summary chip (no tap target), for showing a room's current attributes. */
.attr-chip--static {
    min-height: 0;
    padding: 0.15rem 0.6rem;
    font-size: 0.8rem;
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 16%, var(--mud-palette-surface, #fff));
    border-color: transparent;
    cursor: default;
}

.attr-chips--summary {
    gap: 0.35rem;
}

.attr-room-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.attr-room {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.85rem 0;
    border-bottom: 1px solid var(--brand-hairline);
}

.attr-room:last-child {
    border-bottom: none;
}

.attr-room__main {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    min-width: 0;
}

.attr-room__name {
    font-weight: 500;
    color: var(--brand-carbon-wing);
}

/* Catalogue chip cloud: a compact wrapping set of attribute tags, each with a small close button,
   so the whole catalogue reads at a glance instead of a tall list of rows. */
.attr-catalogue {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.attr-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.3rem 0.35rem 0.3rem 0.75rem;
    font-size: 0.9rem;
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 14%, var(--mud-palette-surface, #fff));
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 999px;
}

.attr-tag__name {
    font-weight: 500;
}

.attr-tag__remove {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.4rem;
    height: 1.4rem;
    padding: 0;
    font-size: 1.15rem;
    line-height: 1;
    color: var(--brand-muted);
    background: none;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    transition: color 0.15s ease, background 0.15s ease;
}

.attr-tag__remove:hover:not(:disabled) {
    color: #b3261e;
    background: rgba(179, 38, 30, 0.1);
}

.attr-tag__remove:disabled {
    cursor: default;
    opacity: 0.5;
}

.attr-tag__remove:focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 1px;
}

/* Attribute usage: one drill-down row per attribute. Collapsed shows a usage count badge; expanded
   reveals the rooms, where ticking a room assigns this attribute to it. */
.attr-usage-list {
    list-style: none;
    margin: 0;
    padding: 0;
}

.attr-usage {
    border-bottom: 1px solid var(--brand-hairline);
}

.attr-usage:last-child {
    border-bottom: none;
}

.attr-usage__summary {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 0;
    cursor: pointer;
    list-style: none;
}

.attr-usage__summary::-webkit-details-marker {
    display: none;
}

/* A brand disclosure caret that rotates open. */
.attr-usage__summary::before {
    content: "";
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--brand-cambridge-blue);
    border-bottom: 2px solid var(--brand-cambridge-blue);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
}

.attr-usage__details[open] .attr-usage__summary::before {
    transform: rotate(45deg);
}

.attr-usage__summary:focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
    border-radius: 4px;
}

.attr-usage__name {
    font-weight: 500;
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
}

.attr-usage__badge {
    margin-left: auto;
    padding: 0.15rem 0.6rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
    /* A tint of the tenant primary over the theme surface, so it reads in light and dark. */
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 16%, var(--mud-palette-surface, #fff));
    border-radius: 999px;
    white-space: nowrap;
}

.attr-usage__badge--empty {
    color: var(--brand-muted);
    background: var(--brand-sea-salt);
    border: 1px solid var(--brand-hairline);
    font-weight: 400;
}

.attr-usage__body {
    padding: 0 0 0.9rem 1.25rem;
}

/* Rooms are grouped by site then building so identically named rooms are told apart by location. */
.attr-usage__site {
    margin-top: 0.75rem;
}

.attr-usage__site-name {
    display: block;
    font-weight: 500;
    font-size: 0.95rem;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
    padding-bottom: 0.35rem;
    border-bottom: 1px solid var(--brand-hairline);
}

.attr-usage__building {
    margin: 0.6rem 0 0 0.75rem;
}

.attr-usage__building-name {
    display: block;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    margin-bottom: 0.4rem;
}

/* Attribute groups: a heading per group in the catalogue, the usage list and the Space Finder
   filter. Groups sort A to Z, attributes A to Z within, ungrouped last. */
.attr-group {
    margin-bottom: 1rem;
}

.attr-group__head {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-bottom: 0.5rem;
}

.attr-group__name {
    font-weight: 500;
    font-size: 0.95rem;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
}

/* The named-group heading is an editable field (rename on blur); the ungrouped heading is plain. */
input.attr-group__name {
    padding: 0.3rem 0.6rem;
    border: 1px solid var(--brand-hairline);
    border-radius: 6px;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
}

.attr-group__name--ungrouped {
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.attr-tag__group {
    padding: 0.2rem 0.5rem;
    font-size: 0.8rem;
    border: 1px solid var(--brand-hairline);
    border-radius: 6px;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
}

.attr-usage-group__head {
    margin: 1rem 0 0.5rem;
    font-weight: 500;
    font-size: 1rem;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
}

/* A site shown as a label: its logo (when set) beside the name. Consistent wherever a site is a
   label (not in dropdowns). The logo scales to the line so it sits neatly next to the name. */
.site-label {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.site-label__logo {
    display: inline-flex;
    flex: 0 0 auto;
}

.site-label__logo img {
    height: 1.4em;
    width: auto;
    max-width: 2.4em;
    object-fit: contain;
    border-radius: 3px;
    vertical-align: middle;
}

.site-label__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Groups management list on the room-attributes page. */
.attr-grouplist {
    list-style: none;
    margin: 0.5rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.attr-grouprow {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Collapsible Groups and Attributes sections (collapsed by default), so the setup areas stay tucked
   away and the page opens on the everyday usage section. */
.attr-section__summary {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    cursor: pointer;
    list-style: none;
    padding: 0.15rem 0;
}

.attr-section__summary::-webkit-details-marker {
    display: none;
}

.attr-section__summary::before {
    content: "";
    flex: 0 0 auto;
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid var(--brand-cambridge-blue);
    border-bottom: 2px solid var(--brand-cambridge-blue);
    transform: rotate(-45deg);
    transition: transform 0.15s ease;
}

.attr-section[open] .attr-section__summary::before {
    transform: rotate(45deg);
}

.attr-section__summary:focus-visible {
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
    border-radius: 4px;
}

.attr-section__count {
    margin-left: auto;
    padding: 0.1rem 0.55rem;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 14%, var(--mud-palette-surface, #fff));
    border-radius: 999px;
}

.attr-section__body {
    padding-top: 0.85rem;
}

/* The By attribute / By room toggle and the site/building filters above the usage list. */
.attr-usage-controls {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 0.75rem 1rem;
    margin-bottom: 1rem;
}

.attr-viewtoggle {
    display: inline-flex;
    gap: 0.35rem;
}

.attr-usage-filter {
    min-width: 12rem;
}

.attr-filter-group {
    margin-bottom: 0.6rem;
}

.attr-filter-group__head {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    margin-bottom: 0.3rem;
}

/* Keyboard users can jump straight to the page content, past the app bar and nav. Hidden until
   focused, then it slides into the top-left. */
.skip-link {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 2000;
    transform: translateY(-120%);
    padding: 0.6rem 1rem;
    background: var(--brand-brunswick-green);
    color: #F6FAF9;
    font-weight: 500;
    text-decoration: none;
    border-radius: 0 0 6px 0;
    transition: transform 0.15s ease;
}

.skip-link:focus,
.skip-link:focus-visible {
    transform: translateY(0);
    outline: 2px solid var(--brand-cambridge-blue);
    outline-offset: 2px;
}

/* No focus ring on the content region when the skip link sends focus to it. */
#main-content:focus {
    outline: none;
}

/* The page body never scrolls sideways; wide content scrolls in its own box. */
body {
    overflow-x: hidden;
}

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

/* ---- Shared date navigator ---- */
.datenav {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    flex-wrap: wrap;
}

.datenav__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.1rem;
    height: 40px;
    padding: 0 0.7rem;
    font: inherit;
    font-weight: 500;
    color: var(--mud-palette-text-primary, var(--brand-brunswick-green));
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #C4D3CC);
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.datenav__btn--text {
    min-width: auto;
}

/* "Today" is a jump-to-today action. When you are already on today it is disabled and quiet, so it
   never reads as a label for the selected date. When you are elsewhere it is offered as an accent. */
.datenav__btn--today:not(:disabled) {
    color: var(--mud-palette-primary, var(--brand-brunswick-green));
    border-color: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 45%, transparent);
    font-weight: 500;
}

/* Quiet but present in both themes: muted text and a hairline border, not an opacity fade that
   sinks the label into a dark background. */
.datenav__btn--today:disabled {
    color: var(--brand-muted);
    border-color: var(--brand-hairline);
    cursor: default;
    background: transparent;
}

.datenav__btn--today:disabled:hover {
    border-color: var(--brand-hairline, rgba(20, 40, 40, 0.14));
    background: transparent;
}

.datenav__btn:hover {
    border-color: var(--mud-palette-primary, var(--brand-brunswick-green));
    background: color-mix(in srgb, var(--mud-palette-text-primary, #101418) 7%, var(--mud-palette-surface, #fff));
}

.datenav__input {
    height: 40px;
    padding: 0 0.7rem;
    font: inherit;
    color: var(--mud-palette-text-primary, var(--brand-carbon-wing));
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #C4D3CC);
    border-radius: 8px;
    box-sizing: border-box;
}

.datenav__input:focus-visible {
    outline: none;
    border-color: var(--brand-brunswick-green);
    box-shadow: 0 0 0 3px rgba(28, 78, 79, 0.15);
}

/* The MudDatePicker used where dates can be disabled must sit at the same compact size as the plain
   date input, not stretch to the full row width (which read as a huge box). */
.datenav__picker {
    width: 11rem;
    flex: 0 0 auto;
    margin: 0;
}

.datenav__picker .mud-input {
    margin-top: 0;
}

.datenav__picker .mud-input-slot {
    height: 40px;
}

.find-organiser {
    font-size: 0.85rem;
    color: var(--brand-muted);
}

/* Availability & beg cards. A free room reads as a single compact row so the eye can scan down the
   available rooms quickly; a busy room lists its taken times as a wrapping row of chips. */
.find-room__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}

.find-room__id {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    min-width: 0;
    flex-wrap: wrap;
}

.find-room__name {
    margin: 0;
}

/* "Available all day" in green, with a dot, so open rooms jump out when scanning. */
.find-free {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    font-weight: 500;
    color: #1f7a4d;
}

.find-free__dot {
    width: 0.6rem;
    height: 0.6rem;
    border-radius: 50%;
    background: #1f7a4d;
}

.find-busycount {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.find-slots {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.45rem;
    margin-top: 0.75rem;
}

/* A busy time as a centred pill. Beggable future slots are buttons that carry a "Need the room? Ask
   {name}" prompt with a waving hand, so what to do is obvious. */
.find-slot {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.35rem 0.9rem;
    border-radius: 999px;
    background: var(--brand-mint-cream, #D7E7E1);
    color: #142828;
    font-size: 0.85rem;
    font-weight: 500;
    border: 1px solid transparent;
    font-family: inherit;
    line-height: 1.25;
    text-align: center;
}

.find-slot__who {
    font-weight: 400;
    color: #43585a;
}

.find-slot__cta {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-weight: 400;
    color: #43585a;
}

.find-slot__cta .mud-icon-root {
    color: #8a5e00;
}

.find-slot--beggable {
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.find-slot--beggable:hover {
    background: #FDF3D9; /* pale Mimosa */
    border-color: #F2B949; /* Mimosa */
}

.find-slot--beggable:focus-visible {
    outline: 2px solid #F2B949;
    outline-offset: 2px;
}

.mybookings-past,
.collapsed-section {
    margin-top: 1.5rem;
}

/* Pages that repeat a table per section (My bookings) or per menu (Food menus) give every table the
   same <colgroup>; fixed layout makes the browser honour those widths exactly, so the columns line
   up from table to table. Below MudBlazor's Sm breakpoint the tables reflow to stacked rows, where
   fixed column widths would only fight the stacking. */
/* My bookings joins the same rule as the food admin table: between MudBlazor's Sm breakpoint and
   ~900px its percentage columns cannot hold the row actions (Rate the catering, Record, Details),
   so fixed layout would clip them; auto layout with a scroll fallback keeps every action reachable. */
@media (min-width: 600px) and (max-width: 899.98px) {
    .mybookings-table .mud-table-container {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }
}

@media (min-width: 900px) {
    .mybookings-table table {
        table-layout: fixed;
    }
}

/* The food admin table only pins its columns once there is genuinely room for them: between
   MudBlazor's Sm breakpoint and ~900px the percentage columns cannot hold the action buttons
   (three icon buttons need ~108px), so fixed layout would spill them out of their cells. */
@media (min-width: 900px) {
    .food-admin-table table {
        table-layout: fixed;
    }
}

/* A keyed wrapper for each choose-N option row: display contents keeps the children laid out by
   the parent grid while giving Blazor a single keyed element per row. */
.food-option-grid__row {
    display: contents;
}

.mybookings-past > summary,
.collapsed-section > summary {
    cursor: pointer;
    font-weight: 500;
    color: var(--brand-primary-ink, var(--brand-brunswick-green));
    padding: 0.4rem 0;
    list-style: none;
}

.mybookings-past > summary::before,
.collapsed-section > summary::before {
    content: "▸ ";
}

.mybookings-past[open] > summary::before,
.collapsed-section[open] > summary::before {
    content: "▾ ";
}

/* ---- Collapsible navigation drawer (static-SSR, toggled by js/nav.js) ---- */
.nav-hamburger {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.4rem;
    margin-right: 1rem;
    background: none;
    border: none;
    color: inherit;
    cursor: pointer;
    border-radius: 8px;
}

.nav-hamburger:hover {
    background: rgba(255, 255, 255, 0.12);
}

.mud-drawer {
    transition: transform 0.2s ease;
    /* The app bar and drawer share the same green, so a hairline separates the two surfaces. */
    border-right: 1px solid rgba(255, 255, 255, 0.08);
}

/* Use more of the screen: a wider content column (ExtraLarge) with tighter side padding, so pages
   are not squeezed into the middle on a large monitor. */
#main-content.mud-container {
    padding-left: 1.75rem;
    padding-right: 1.75rem;
}

/* Give the drawer navigation room to breathe (issue: items felt squished). */
.mud-drawer .mud-nav-menu {
    padding-top: 0.35rem;
}

.mud-drawer .mud-nav-link {
    padding-top: 0.6rem;
    padding-bottom: 0.6rem;
    font-size: 0.95rem;
}

.mud-drawer .mud-nav-group > .mud-nav-link,
.mud-drawer .mud-nav-group .mud-nav-group-title {
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
}

.mud-drawer .mud-nav-link .mud-nav-link-icon {
    margin-right: 0.85rem;
}

/* Desktop: collapsing hides the drawer and reclaims the content width. */
html.nav-collapsed .mud-drawer {
    transform: translateX(-105%);
}

html.nav-collapsed .mud-drawer-open ~ .mud-main-content,
html.nav-collapsed .mud-main-content {
    margin-left: 0 !important;
}

/* Phones and tablets (up to 1264px): the content is always full width; the drawer is an off-canvas
   overlay that slides in over the content when opened, with a dimmed backdrop behind it. */
@media (max-width: 1264px) {
    .mud-main-content {
        margin-left: 0 !important;
    }

    /* The drawer is off-canvas and closed by default here (no dependency on script having run, so it
       never flashes open on load or navigation); it slides in only when the menu is opened. */
    .mud-drawer {
        position: fixed;
        top: 64px;
        bottom: 0;
        left: 0;
        z-index: 1300;
        transform: translateX(-105%);
        transition: transform 0.2s ease;
    }

    html.nav-open .mud-drawer {
        transform: translateX(0);
        box-shadow: 0 8px 40px rgba(16, 20, 24, 0.35);
    }

    html.nav-open .nav-backdrop {
        display: block;
    }
}

/* The dimmed backdrop behind the off-canvas drawer. Hidden by default (and on wide screens where the
   drawer is persistent); shown only when the overlay drawer is open. Tapping it closes the drawer. */
.nav-backdrop {
    display: none;
    position: fixed;
    inset: 64px 0 0 0;
    z-index: 1299;
    background: rgba(16, 20, 24, 0.42);
    border: none;
    padding: 0;
    margin: 0;
    cursor: pointer;
}

/* ---- Coloured sidebar (dark drawer) navigation legibility ---- */
.mud-drawer .mud-nav-link:hover {
    background: rgba(255, 255, 255, 0.06) !important;
}

/* Book a room is why most people are here, so it is the one bright call to action in the drawer: a
   filled Mimosa pill with dark text, standing clear of the white-on-brand links around it. Mimosa is a
   brand colour, so it reads on the platform green and on any tenant brand colour alike. */
.mud-drawer .mud-nav-link[href="/book"],
.mud-drawer .mud-nav-link[href="/order"] {
    margin: 0.5rem 0.6rem 0.75rem;
    padding-top: 0.7rem;
    padding-bottom: 0.7rem;
    border-radius: 12px;
    /* The tenant's secondary scheme colour, so the primary action fits whatever palette they pick
       (with its guaranteed-contrast on-secondary text), rather than a fixed Mimosa. */
    background: var(--mud-palette-secondary, var(--brand-mimosa, #F2B949)) !important;
    color: var(--mud-palette-secondary-text, #2a1f00) !important;
    font-weight: 700;
    font-size: 1.02rem;
    letter-spacing: 0.01em;
    box-shadow: 0 3px 12px rgba(16, 20, 24, 0.28);
    transition: transform 0.15s ease, box-shadow 0.2s ease, filter 0.15s ease;
    /* A gentle neutral lift pulse so the primary action catches the eye without a coloured haze. */
    animation: book-cta-pulse 3.2s ease-in-out infinite;
}

/* The link's icon and text take the on-secondary colour so the whole pill reads as one button; the
   icon is a touch larger to give the primary action more presence. */
.mud-drawer .mud-nav-link[href="/book"] .mud-nav-link-text,
.mud-drawer .mud-nav-link[href="/book"] .mud-nav-link-icon,
.mud-drawer .mud-nav-link[href="/book"] .mud-icon-root,
.mud-drawer .mud-nav-link[href="/order"] .mud-nav-link-text,
.mud-drawer .mud-nav-link[href="/order"] .mud-nav-link-icon,
.mud-drawer .mud-nav-link[href="/order"] .mud-icon-root {
    color: var(--mud-palette-secondary-text, #2a1f00) !important;
}

.mud-drawer .mud-nav-link[href="/book"] .mud-nav-link-icon,
.mud-drawer .mud-nav-link[href="/book"] .mud-icon-root,
.mud-drawer .mud-nav-link[href="/order"] .mud-nav-link-icon,
.mud-drawer .mud-nav-link[href="/order"] .mud-icon-root {
    font-size: 1.4rem;
}

.mud-drawer .mud-nav-link[href="/book"]:hover,
.mud-drawer .mud-nav-link[href="/order"]:hover {
    background: var(--mud-palette-secondary, var(--brand-mimosa, #F2B949)) !important;
    filter: brightness(1.08);
    box-shadow: 0 5px 18px rgba(16, 20, 24, 0.34);
    transform: translateY(-1px);
    animation: none; /* settle the pulse while the user is interacting */
}

.mud-drawer .mud-nav-link[href="/book"].active,
.mud-drawer .mud-nav-link[href="/order"].active {
    background: var(--mud-palette-secondary, var(--brand-mimosa, #F2B949)) !important;
}

@keyframes book-cta-pulse {
    0%, 100% { box-shadow: 0 3px 12px rgba(16, 20, 24, 0.28); }
    50% { box-shadow: 0 5px 18px rgba(16, 20, 24, 0.4); }
}

/* Respect a reduced-motion preference: keep the button prominent, drop the pulse. */
@media (prefers-reduced-motion: reduce) {
    .mud-drawer .mud-nav-link[href="/book"],
    .mud-drawer .mud-nav-link[href="/order"] {
        animation: none;
    }
}

/* Active and group states use white-alpha, not a fixed green, so the drawer reads correctly on any
   tenant brand colour as well as the platform Brunswick Green. */
.mud-drawer .mud-nav-link.active {
    color: #FFFFFF !important;
    background: rgba(255, 255, 255, 0.16) !important;
    border-left: 3px solid rgba(255, 255, 255, 0.75);
}

.mud-drawer .mud-nav-group-title {
    color: rgba(255, 255, 255, 0.6);
}

/* The theme-toggle sits in the user menu and should read like the other links. */
.usermenu__form {
    margin: 0;
}

.usermenu__form button {
    display: block;
    width: 100%;
    text-align: left;
    padding: 0.65rem 1.25rem;
    background: none;
    border: none;
    font: inherit;
    font-size: 0.95rem;
    color: inherit;
    cursor: pointer;
}

.usermenu__form button:hover {
    background: var(--brand-hairline);
}

/* ---- Platform status cards ---- */
.status-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: var(--space-4);
}

@media (max-width: 52rem) {
    .status-grid { grid-template-columns: 1fr; }
}

.status-card {
    padding: 1.25rem 1.4rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

/* Inline integration keys within their card, so each integration is configured in place. */
.status-card__keys {
    margin-top: 1rem;
    padding-top: 1rem;
    border-top: 1px solid var(--brand-hairline);
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.status-card--wide { grid-column: 1 / -1; }

.status-card__title {
    margin: 0 0 0.9rem;
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--brand-primary-ink, var(--brand-brunswick-green));
}

.status-card__facts {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
}

.status-card__facts > div {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.status-fact__label {
    font-size: 0.75rem;
    color: var(--brand-muted);
}

.status-fact__value {
    font-weight: 500;
    color: var(--brand-carbon-wing);
    font-variant-numeric: tabular-nums;
}

.status-fact__value--ok { color: var(--status-positive-ink); }
.status-fact__value--bad { color: var(--status-negative-ink); }

.status-card__warn {
    margin: 0.9rem 0;
    padding: 0.7rem 0.9rem;
    font-size: 0.85rem;
    line-height: 1.45;
    color: #6a4a12;
    background: #FDF3D9;
    border: 1px solid var(--brand-mimosa);
    border-radius: var(--radius-sm);
}

/* Pending EF Core migrations banner. Louder than the amber .status-card__warn because it is a
   red condition (the DLL and the schema disagree). Text stays legible on both themes. */
.status-migrations {
    border-color: #8a2b2b !important;
    background: #f7e3e2;
    color: #4a1010;
}
.status-migrations__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.95rem;
    color: #8a2b2b;
}
.status-migrations__hint {
    margin: 0.35rem 0 0.5rem;
    font-size: 0.9rem;
    line-height: 1.5;
    color: #4a1010;
}
.status-migrations__hint code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.85em;
    padding: 0 0.3em;
    border-radius: 3px;
    background: rgba(255, 255, 255, 0.6);
}
.status-migrations__list {
    margin: 0;
    padding-left: 1.2rem;
    font-size: 0.88rem;
}
.status-migrations__list li {
    margin: 0.1rem 0;
}
.status-migrations__list code {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.9em;
    color: #4a1010;
}
@media (prefers-color-scheme: dark) {
    .status-migrations {
        background: rgba(163, 46, 46, 0.16);
        color: #f4c2c2;
    }
    .status-migrations__head { color: #e88a8a; }
    .status-migrations__hint { color: #f4c2c2; }
    .status-migrations__hint code { background: rgba(0, 0, 0, 0.3); }
    .status-migrations__list code { color: #f4c2c2; }
}

.status-switch {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.9rem;
    font-size: 0.9rem;
    color: var(--brand-carbon-wing);
    cursor: pointer;
}

/* ---- Menu search box in the drawer ---- */
.nav-search {
    padding: 0.75rem 0.75rem 1rem;
    margin-bottom: 0.5rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.nav-search input {
    width: 100%;
    box-sizing: border-box;
    padding: 0.5rem 0.75rem;
    font: inherit;
    font-size: 0.9rem;
    color: #F6FAF9;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.15);
    border-radius: 8px;
}

.nav-search input::placeholder {
    color: rgba(214, 231, 225, 0.65);
}

.nav-search input:focus-visible {
    outline: none;
    border-color: var(--brand-celadon);
    background: rgba(255, 255, 255, 0.12);
}

/* Identity provider editor: a two-column layout, form on the left, supporting panels
   (status, test, IT team details) on the right, stacking to one column on narrow screens. */
.idp-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 1.5rem;
    align-items: start;
}

.idp-main {
    min-width: 0;
}

.idp-side {
    display: grid;
    gap: 1.5rem;
    position: sticky;
    top: 1rem;
}

@media (max-width: 960px) {
    .idp-layout {
        grid-template-columns: 1fr;
    }

    .idp-side {
        position: static;
    }
}

.idp-card {
    padding: 1.5rem;
}

.idp-card--side {
    padding: 1.25rem;
}

.idp-editor__lead {
    margin: 0 0 0.75rem;
    color: var(--mud-palette-text-primary, #101418);
}

.idp-editor__lead--muted {
    font-size: 0.9rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.idp-step {
    margin-top: 1.75rem;
}

.idp-step:first-of-type {
    margin-top: 1rem;
}

.idp-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.idp-side__title {
    margin: 0 0 0.5rem;
    font-size: 1rem;
    font-weight: 500;
    color: color-mix(in srgb, var(--brand-cambridge-blue) 45%, var(--mud-palette-text-primary, var(--brand-brunswick-green)));
}

.idp-side__hint {
    margin: 0.5rem 0 0;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

/* Status pill: a coloured dot plus label, meaning never carried by colour alone. */
.idp-statusline {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.idp-status {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.2rem 0.65rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 500;
}

.idp-status::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: currentColor;
}

.idp-status--off {
    background: var(--status-neutral-wash);
    color: var(--status-neutral-ink);
}

.idp-status--paused {
    background: var(--status-warning-wash);
    color: var(--status-warning-ink);
}

.idp-status--on {
    background: var(--status-positive-wash);
    color: var(--status-positive-ink);
}

/* "Details for your IT team" handoff, shown as a panel on the right. */
.idp-handoff__title {
    margin: 0 0 0.35rem;
    font-size: 1rem;
    font-weight: 500;
    color: var(--brand-primary-ink, var(--brand-brunswick-green));
}

.idp-handoff__intro {
    margin: 0 0 0.85rem;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.idp-handoff__list {
    margin: 0;
    display: grid;
    gap: 0.7rem;
}

.idp-handoff__list dt {
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.idp-handoff__list dd {
    margin: 0.15rem 0 0;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.idp-handoff__list code {
    display: inline-block;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8rem;
    background: var(--mud-palette-background-grey, #f6faf9);
    border: 1px solid var(--mud-palette-lines-default, rgba(20, 40, 40, 0.14));
    border-radius: 6px;
    padding: 0.15rem 0.4rem;
    word-break: break-all;
}

/* Identity provider "Test connection" result, shown below the test button. */
.idp-test {
    margin: 0.7rem 0 0;
    font-size: 0.85rem;
    font-weight: 500;
}

.idp-test--ok {
    color: var(--brand-brunswick-green, #1C4E4F);
}

.idp-test--bad {
    color: var(--mud-palette-error, #b00020);
}

/* Recurrence interval: the number and its unit (day/week/month) sit on one line so "Every 1 day" reads naturally. */
.book-interval {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.book-interval__unit {
    font-size: 0.9rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

/* The amendment callout on the food order details dialog: what the catering team changed, as a
   gentle accent-tinted panel, so "Amended" is never a mystery chip. */
.food-amend-note {
    margin: 0 0 0.9rem;
    padding: 0.6rem 0.85rem;
    border-left: 3px solid var(--mud-palette-secondary, var(--brand-mimosa, #F2B949));
    border-radius: 0 8px 8px 0;
    background: color-mix(in srgb, var(--mud-palette-secondary, #F2B949) 10%, var(--mud-palette-surface, #fff));
    font-size: 0.9rem;
    line-height: 1.5;
}

.food-amend-note ul {
    margin: 0.35rem 0 0;
    padding-left: 1.1rem;
}

/* Screen-reader-only text: visually hidden, still announced (a header cell whose meaning is
   obvious visually but not audibly). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* Stat tiles (the headline numbers on Home, My spend and the department statement). These lived in
   Home.razor.css, but scoped CSS never reached the other pages that render the same tiles. */
.home-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
    gap: 1rem;
    margin-bottom: 1.5rem;
}

.home-stat {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    padding: 1.25rem 1.35rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #E2ECE7);
    border-radius: 12px;
}

.home-stat__value {
    font-size: 2rem;
    font-weight: 500;
    line-height: 1.1;
    color: var(--mud-palette-primary, #1C4E4F);
    font-variant-numeric: tabular-nums;
}

.home-stat__label {
    font-size: 0.95rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.home-stat__sub {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #5b6b6b);
}

.home-stat__sub a {
    color: var(--mud-palette-primary, #1C4E4F);
    font-weight: 500;
    text-decoration: none;
}

.home-stat__sub a:hover {
    text-decoration: underline;
}

/* A wider tile for a short line of text (the next booking's room and time) rather than a number. */
.home-stat--wide {
    grid-column: span 2;
}

.home-stat__value--sm {
    font-size: 1.25rem;
    font-weight: 500;
    margin-top: 0.1rem;
}

@media (max-width: 640px) {
    .home-stat--wide {
        grid-column: auto;
    }
}

/* My spend filters: the cost code, the date range and the action share one row, wrapping on
   narrow screens. Bottom-aligned so the button lines up with the inputs, not the labels. */
.spend-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 1rem;
}

.spend-filters__field {
    flex: 1 1 16rem;
    max-width: 26rem;
}

/* Toolbar above a data table: a search box and optional toggles. Shared by the list pages. */
.table-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem;
    margin-bottom: 0.85rem;
}

.table-toolbar__search {
    flex: 1 1 16rem;
    max-width: 24rem;
}

.table-toolbar__check {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.9rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    white-space: nowrap;
}

/* Decided-approval history: a small outcome badge. */
.decided-history summary {
    cursor: pointer;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.decided-badge {
    display: inline-block;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 500;
}

.decided-badge--approved {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.decided-badge--rejected {
    color: var(--status-negative-ink);
    background: var(--status-negative-wash);
}

/* Book screen: future bookings on the chosen room that a colleague can beg for. */
.book-taken__list {
    list-style: none;
    margin: 0.35rem 0 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.book-taken__list li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.4rem 0.6rem;
    background: var(--mud-palette-surface, #F6FAF9);
    border: 1px solid var(--mud-palette-lines-default, #E2ECE7);
    border-radius: 8px;
    font-size: 0.88rem;
}

/* Find by need: the "next available time with everything you need" panel. */
.next-available {
    padding: 1rem 1.15rem;
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 8%, transparent);
    border: 1px solid color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 25%, transparent);
    border-radius: 12px;
}

.next-available__head {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    margin: 0 0 0.75rem;
    font-size: 0.95rem;
    color: var(--mud-palette-text-primary, #101418);
}

/* ---- Collapsible nav groups (native <details>, works in the static-SSR drawer) ---- */
.nav-group {
    border: none;
}

.nav-group__summary {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 1rem;
    margin-top: 0.35rem;
    cursor: pointer;
    list-style: none;
    color: rgba(246, 250, 249, 0.92); /* Sea Salt on the dark drawer */
    font-weight: 500;
    user-select: none;
    /* A hairline above each group so the sections read as distinct blocks in the drawer. */
    border-top: 1px solid rgba(246, 250, 249, 0.12);
}

.nav-group__summary::-webkit-details-marker {
    display: none;
}

.nav-group__summary:hover {
    background: rgba(246, 250, 249, 0.08);
}

.nav-group__title {
    flex: 1 1 auto;
    /* One shared eyebrow type system (see :root). On the dark brand drawer the branded ink would sink,
       so this is the one eyebrow that keeps a light tint for contrast; the metrics match every other
       kicker so they read as one family. */
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: rgba(246, 250, 249, 0.72);
}

.nav-group__chevron {
    transition: transform 0.15s ease;
    opacity: 0.75;
}

.nav-group[open] > .nav-group__summary .nav-group__chevron {
    transform: rotate(180deg);
}

/* Slightly indent the group's items so the hierarchy reads. */
.nav-group__items .mud-nav-link {
    padding-left: 2.25rem;
}

/* ---- Themed scrollbars ---- */
* {
    scrollbar-width: thin;
    scrollbar-color: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 45%, transparent) transparent;
}

::-webkit-scrollbar {
    width: 10px;
    height: 10px;
}

::-webkit-scrollbar-track {
    background: transparent;
}

::-webkit-scrollbar-thumb {
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 40%, transparent);
    border-radius: 999px;
    border: 2px solid transparent;
    background-clip: content-box;
}

::-webkit-scrollbar-thumb:hover {
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 65%, transparent);
    background-clip: content-box;
}

/* On the dark drawer, a light thumb reads better than a dark one. */
.mud-drawer {
    scrollbar-color: rgba(246, 250, 249, 0.35) transparent;
}

.mud-drawer ::-webkit-scrollbar-thumb {
    background: rgba(246, 250, 249, 0.3);
    background-clip: content-box;
}

.mud-drawer ::-webkit-scrollbar-thumb:hover {
    background: rgba(246, 250, 249, 0.5);
    background-clip: content-box;
}

/* ---- Room diary as an FM job sheet ---- */
.diary-progress {
    margin-left: auto;
    font-size: 0.88rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.jobsheet__building {
    margin: 1.5rem 0 0.75rem;
    font-size: 1.05rem;
    font-weight: 500;
    color: var(--mud-palette-primary, #1C4E4F);
}

.jobsheet {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(18rem, 1fr));
    gap: 1rem;
}

.job-card {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1.1rem 1.2rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #E2ECE7);
    border-left: 4px solid var(--mud-palette-primary, #1C4E4F);
    border-radius: 12px;
    box-shadow: var(--shadow-card);
}

.job-card--ready {
    border-left-color: #1f7a4d;
}

.job-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.job-card__time {
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.job-card__badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 500;
}

.job-card__badge--ready {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.job-card__badge--todo {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

.job-card__room {
    font-size: 1.15rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.job-card__meta {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.job-card__section {
    margin-top: 0.15rem;
}

.job-card__label {
    display: block;
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    text-transform: uppercase;
    letter-spacing: var(--eyebrow-tracking);
    color: var(--brand-muted);
    margin-bottom: 0.3rem;
}

.job-card__none {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.job-card__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
}

.job-chip {
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 500;
    color: var(--brand-primary-ink);
    background: var(--brand-primary-lozenge);
}

.job-card__notes {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    padding: 0.5rem 0.65rem;
    background: rgba(242, 185, 73, 0.14); /* Mimosa wash */
    border-radius: 8px;
    font-size: 0.85rem;
    color: var(--mud-palette-text-primary, #101418);
}

.job-card__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-top: auto;
    padding-top: 0.4rem;
}

/* ---- Estate hierarchy (site > building > room tree) ---- */
.estate-tree__site {
    margin-bottom: 1rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #E2ECE7);
    border-radius: 12px;
    overflow: hidden;
}

.estate-tree__summary {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.9rem 1.1rem;
    cursor: pointer;
    list-style: none;
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 6%, transparent);
    user-select: none;
}

.estate-tree__summary::-webkit-details-marker {
    display: none;
}

.estate-tree__icon {
    color: var(--mud-palette-primary, #1C4E4F);
}

.estate-tree__name {
    font-size: 1.1rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.estate-tree__meta {
    flex: 1 1 auto;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.estate-tree__chevron {
    transition: transform 0.15s ease;
    opacity: 0.7;
}

.estate-tree__site[open] > .estate-tree__summary .estate-tree__chevron {
    transform: rotate(180deg);
}

.estate-tree__body {
    padding: 1rem 1.1rem 1.2rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.estate-tree__rowactions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

.estate-tree__closures {
    padding: 0.75rem 0.9rem;
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 4%, transparent);
    border-radius: 10px;
}

.estate-tree__building {
    padding: 0.85rem 0.95rem;
    border: 1px solid var(--mud-palette-lines-default, #E2ECE7);
    border-left: 3px solid color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 50%, transparent);
    border-radius: 10px;
}

@media (max-width: 640px) {
    .estate-tree__meta {
        display: none;
    }
}

/* ---- Users list: person-focused cells and status chips ---- */
.user-cell {
    display: flex;
    align-items: center;
    gap: 0.65rem;
}

.user-cell__avatar {
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.85rem;
    font-weight: 500;
    color: var(--mud-palette-primary, #1C4E4F);
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 14%, transparent);
}

.user-cell__id {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
}

.user-cell__name {
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.user-cell__email {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.user-cell__you {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-style: italic;
}

.user-status {
    display: inline-block;
    padding: 0.1rem 0.6rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 500;
}

.user-status--active {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.user-status--invited {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

.user-status--inactive {
    color: var(--status-neutral-ink);
    background: var(--status-neutral-wash);
}

/* Queued: invited while invitation emails are paused (or the tenant is a draft), so the link
   has not been sent yet. Reads deliberately cooler than the amber Invited, so it borrows the
   branded primary tint rather than a status colour. */
.user-status--queued {
    color: var(--brand-primary-ink);
    background: var(--brand-primary-lozenge);
}

/* Booking status badge: friendly status text in a subtle, brand-tinted pill. */
.status-badge {
    display: inline-flex;
    align-items: center;
    gap: 0.25rem;
    padding: 0.1rem 0.6rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 500;
    white-space: nowrap;
}

/* Confirmed reads calm and positive (green). The text mixes the accent with the theme's text colour
   so it stays legible on both the light and the dark surface (dark green on light, light green on
   dark), rather than a fixed dark green that washes out in dark mode. */
.status-badge--confirmed {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

/* Pending approval and Held wait on the booker: a warm amber. */
.status-badge--pending,
.status-badge--held {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

/* Food order statuses read as a clear progression, each drawing from the shared status palette so
   they never blur together and never drift from the same states used elsewhere: Approved (accepted,
   awaiting delivery) is the calm info blue; Partially delivered (some slots out, more to come) is the
   warning amber; Delivered (all slots done) is the positive green; Rejected is the negative red. */
.status-badge--approved {
    color: var(--status-info-ink);
    background: var(--status-info-wash);
}

.status-badge--partial {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

.status-badge--delivered {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.status-badge--rejected {
    color: var(--status-negative-ink);
    background: var(--status-negative-wash);
}

/* Cancelled and Lapsed are done with: a muted grey, never a shouty red. */
.status-badge--cancelled,
.status-badge--lapsed,
.status-badge--muted {
    color: var(--status-neutral-ink);
    background: var(--status-neutral-wash);
}

/* The tenant font is set on the layout root; make the app bar and drawer inherit it so the whole
   portal, chrome included, uses the tenant's chosen font (not just the content area). */
.mud-appbar,
.mud-appbar .mud-typography,
.mud-drawer,
.mud-drawer .mud-nav-link,
.mud-drawer .mud-nav-group-title,
.mud-drawer .mud-typography {
    font-family: inherit;
}

/* Room feedback: booker "My messages" and facilities "Room feedback". Cards and a reply thread,
   theme-aware through the MudBlazor palette variables so they read in light and dark. */
.feedback-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* The live clock in the top bar, to the left of the user menu. Sits on the app-bar primary, so it
   inherits the app-bar's light text; tabular figures stop it jiggling as the seconds change. */
.topbar-clock {
    margin-right: 1rem;
    font-size: 0.9rem;
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    color: inherit;
    opacity: 0.92;
    white-space: nowrap;
}

/* Clock size scale, shared by the top-bar clock and the account preview. Declared after .topbar-clock
   so the chosen size wins over its base size. size0 matches the original default. */
.clock-face--size0 { font-size: 0.9rem; }
.clock-face--size1 { font-size: 1.15rem; }
.clock-face--size2 { font-size: 1.45rem; }

/* The live clock preview on the My account Display card: shows the clock exactly as the top bar will,
   ticking and following the choices as they change. */
.clock-preview {
    display: flex;
    align-items: baseline;
    gap: 0.6rem;
    margin: 0.25rem 0 1rem;
    padding: 0.75rem 1rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    background: color-mix(in srgb, var(--mud-palette-surface) 88%, var(--mud-palette-text-primary) 6%);
}

.clock-preview__label {
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    text-transform: uppercase;
    letter-spacing: var(--eyebrow-tracking);
    color: var(--brand-muted);
}

.clock-face {
    font-weight: 500;
    font-variant-numeric: tabular-nums;
    letter-spacing: 0.01em;
    white-space: nowrap;
    color: var(--mud-palette-text-primary);
}

/* Segmented tabs for the My messages page (facilities feedback vs room requests). Theme-aware, so a
   dark portal reads the same. */
.msg-tabs {
    display: inline-flex;
    gap: 0.25rem;
    padding: 0.25rem;
    margin-bottom: 1.25rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 999px;
    background: color-mix(in srgb, var(--mud-palette-surface) 88%, var(--mud-palette-text-primary) 12%);
    flex-wrap: wrap;
}

.msg-tab {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    padding: 0.45rem 1.1rem;
    font: inherit;
    font-size: 0.9rem;
    font-weight: 500;
    color: var(--mud-palette-text-secondary);
    background: transparent;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease;
}

.msg-tab:hover {
    color: var(--mud-palette-text-primary);
}

.msg-tab--on,
.msg-tab--on:hover {
    color: var(--mud-palette-primary-text, #F6FAF9); /* the scheme's guaranteed on-primary, kept on hover too */
    background: var(--mud-palette-primary, #1C4E4F);
}

/* A count of items that still need the user in this section, so the tabs read like an inbox. */
.msg-tab__count {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.35rem;
    height: 1.35rem;
    padding: 0 0.4rem;
    border-radius: 999px;
    font-size: 0.78rem;
    font-weight: 600;
    line-height: 1;
    color: #fff;
    /* Deeper than the alert red used for outlines: white on it must meet 4.5:1 (this is text). */
    background: #C62828;
    box-shadow: 0 0 0 2px var(--mud-palette-surface, #fff);
}

/* On the active tab the badge sits on the primary fill, so ring it in the primary instead. */
.msg-tab--on .msg-tab__count {
    box-shadow: 0 0 0 2px var(--mud-palette-primary, #1C4E4F);
}

.feedback-card {
    padding: 1.1rem 1.25rem;
    border-radius: 14px;
}

.feedback-card__head {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.6rem 0.9rem;
    margin-bottom: 0.6rem;
}

.feedback-card__kind {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.feedback-card__kind--problem {
    color: color-mix(in srgb, #c0392b 70%, var(--mud-palette-text-primary, #101418));
}

.feedback-card__room {
    font-weight: 500;
    color: var(--mud-palette-primary, #1C4E4F);
}

.feedback-card__who,
.feedback-card__when {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.feedback-card__head .status-badge {
    margin-left: auto;
}

.feedback-card__message {
    margin: 0.2rem 0 0.4rem;
    color: var(--mud-palette-text-primary, #101418);
    white-space: pre-wrap;
}

.feedback-card__item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.88rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    margin: 0 0 0.5rem;
}

.feedback-thread {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin: 0.6rem 0;
    padding-left: 0.75rem;
    border-left: 3px solid var(--mud-palette-lines-default, #e0e6e5);
}

.feedback-reply {
    padding: 0.5rem 0.75rem;
    border-radius: 10px;
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 6%, var(--mud-palette-surface, #fff));
}

.feedback-reply--fm {
    background: color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 14%, var(--mud-palette-surface, #fff));
}

.feedback-reply__who {
    display: block;
    font-size: 0.8rem;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
    margin-bottom: 0.15rem;
}

.feedback-reply__when {
    font-weight: 400;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    margin-left: 0.4rem;
}

.feedback-reply__body {
    margin: 0;
    color: var(--mud-palette-text-primary, #101418);
    white-space: pre-wrap;
}

.feedback-card__actions {
    margin: 0.5rem 0;
}

.feedback-card__reply {
    display: flex;
    align-items: flex-end;
    gap: 0.6rem;
    margin-top: 0.6rem;
}

.feedback-card__reply textarea {
    flex: 1 1 auto;
}

/* An inline label + control pair (for example the status selector and the view filter). */
.estate__field--inline {
    flex-direction: row;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
}

.estate__field--inline > span {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    white-space: nowrap;
}

/* Room readiness chip on the booker's My bookings, shown near a meeting so a booker knows whether the
   facilities team has prepared the room. Theme-aware through the palette variables. */
.ready-chip {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    margin-left: 0.4rem;
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.1rem 0.55rem;
    border-radius: 999px;
    white-space: nowrap;
}

.ready-chip .mud-icon-root {
    font-size: 0.95rem;
}

.ready-chip--ready {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.ready-chip--preparing {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

/* Room feedback accordion (booker "My messages" and facilities "Room feedback"). Collapsed bars that
   open to a chat thread. Theme-aware through the palette variables. */
.fbk {
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 12px;
    background: var(--mud-palette-surface, #fff);
    margin-bottom: 0.75rem;
    overflow: hidden;
}

.fbk--closed {
    opacity: 0.72;
}

.fbk__bar {
    display: flex;
    align-items: center;
    gap: 0.7rem;
    width: 100%;
    padding: 0.85rem 1rem;
    background: none;
    border: 0;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.fbk__kind {
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.fbk__room {
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
    flex: 0 0 auto;
    white-space: nowrap;
}

.fbk__from,
.fbk__when {
    font-size: 0.83rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    white-space: nowrap;
}

/* The booker name (facilities view only) is the one variable-width cell, so let it be the part that
   shrinks and truncates. Without this a long name pushes the status badge out of its right-hand
   column and past the chevron; the times and badges never shrink. */
.fbk__from {
    flex: 0 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

.fbk__when {
    flex: 0 0 auto;
}

.fbk__newpill {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--status-negative-ink);
    background: var(--status-negative-wash);
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
}

.fbk__chevron {
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

/* Push the status (or the New reply pill when present) to the right, so the status badges line up in
   a column across rows instead of floating after the variable-length time. The chevron then sits
   right after the badge rather than being flung to the far edge with a gap in between. */
.fbk__bar .feedback-tag {
    margin-left: auto;
    flex: 0 0 auto;
}

.fbk__bar .fbk__newpill {
    margin-left: auto;
    flex: 0 0 auto;
}

.fbk__bar .fbk__newpill + .feedback-tag {
    margin-left: 0;
}

.fbk__bar .fbk__chevron {
    flex: 0 0 auto;
}

.fbk__body {
    padding: 0 1rem 1rem;
    border-top: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
}

.fbk__item {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.88rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    margin: 0.5rem 0 0;
}

.fbk__actions {
    margin: 0.5rem 0;
}

.fbk__reply {
    display: flex;
    align-items: flex-end;
    gap: 0.6rem;
    margin-top: 0.6rem;
}

.fbk__reply textarea {
    flex: 1 1 auto;
}

.fbk-pager {
    display: flex;
    justify-content: center;
    margin-top: 1rem;
}

/* Status tag colours. Open states carry an age; closed states read greyed. */
.feedback-tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.78rem;
    font-weight: 500;
    padding: 0.15rem 0.6rem;
    border-radius: 999px;
    white-space: nowrap;
}

.feedback-tag__age {
    font-weight: 400;
    opacity: 0.85;
}

/* Feedback lifecycle draws from the shared status palette: New needs attention (negative red), Acked
   is in hand (info blue), With customer is waiting on them (a distinct violet, its own state), Resolved
   is done well (positive green), Won't fix is closed off (neutral grey). */
.feedback-tag--new { color: var(--status-negative-ink); background: var(--status-negative-wash); }
.feedback-tag--ack { color: var(--status-info-ink); background: var(--status-info-wash); }
.feedback-tag--withcustomer { color: color-mix(in srgb, #7a5cc0 72%, var(--mud-palette-text-primary, #101418)); background: color-mix(in srgb, #7a5cc0 18%, transparent); }
.feedback-tag--resolved { color: var(--status-positive-ink); background: var(--status-positive-wash); }
.feedback-tag--wontfix { color: var(--status-neutral-ink); background: var(--status-neutral-wash); }

/* Red unread-count badge on nav items. */
.nav-badge {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 1.35rem;
    height: 1.35rem;
    padding: 0 0.35rem;
    margin-left: 0.4rem;
    font-size: 0.78rem;
    font-weight: 700;
    line-height: 1;
    color: #fff;
    /* Deeper than the alert red used for outlines: white on it must meet 4.5:1 (this is text). */
    background: #C62828;
    border-radius: 999px;
    /* A soft light ring so the count pops off the dark brand drawer. */
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.22);
}

/* ---- Contact support ---- */
.contact {
    display: grid;
    grid-template-columns: minmax(0, 22rem) minmax(0, 32rem);
    gap: 1.5rem;
    align-items: start;
}

.contact__info-title {
    margin: 0 0 0.5rem;
    font-size: 1.1rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.contact__info-lead {
    margin: 0 0 0.6rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.5;
}

.contact__tips {
    margin: 0 0 1.25rem;
    padding-left: 1.1rem;
    color: var(--mud-palette-text-secondary);
    line-height: 1.6;
}

.contact__meta {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin: 0;
    padding-top: 1rem;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.contact__meta div { margin: 0; }
.contact__meta dt { font-size: var(--eyebrow-size); font-weight: var(--eyebrow-weight); text-transform: uppercase; letter-spacing: var(--eyebrow-tracking); color: var(--brand-muted); }
.contact__meta dd { margin: 0.1rem 0 0; font-weight: 500; color: var(--mud-palette-text-primary); word-break: break-word; }

.contact__done {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.4rem;
    padding: 1.5rem 1rem;
}

.contact__done-icon { width: 3rem; height: 3rem; color: var(--mud-palette-success); }
.contact__done-title { margin: 0.25rem 0 0; font-size: 1.15rem; font-weight: 600; color: var(--mud-palette-text-primary); }
.contact__done-text { margin: 0 0 1rem; color: var(--mud-palette-text-secondary); max-width: 28rem; }

@media (max-width: 900px) {
    .contact {
        grid-template-columns: 1fr;
    }
}
/* ---- Room requests (beg) message centre ---- */
.beg-section__title {
    font-size: 1.05rem;
    font-weight: 600;
    margin: 0.5rem 0 0.75rem;
    color: var(--mud-palette-text-primary);
}

.beg-card {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 0.6rem;
    margin-bottom: 0.6rem;
    overflow: hidden;
    background: var(--mud-palette-surface);
}

.beg-card--unread {
    border-color: var(--brand-cambridge-blue, #79A682);
    box-shadow: 0 0 0 1px var(--brand-cambridge-blue, #79A682);
}

.beg-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: 0.75rem 1rem;
    background: none;
    border: 0;
    cursor: pointer;
    text-align: left;
    color: inherit;
    font: inherit;
}

.beg-card__main { display: flex; align-items: center; gap: 0.6rem; min-width: 0; }
.beg-card__room { font-weight: 600; }
.beg-card__when { color: var(--mud-palette-text-secondary); font-size: 0.85rem; }
.beg-card__meta { display: flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }
.beg-card__with { color: var(--mud-palette-text-secondary); font-size: 0.8rem; }

.beg-unread-dot {
    width: 0.55rem;
    height: 0.55rem;
    border-radius: 999px;
    background: #d1434b;
    flex-shrink: 0;
}

.beg-thread {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    padding: 0.75rem 1rem;
    border-top: 1px solid var(--mud-palette-lines-default);
}

.beg-bubble {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    max-width: 80%;
    padding: 0.5rem 0.7rem;
    border-radius: 0.6rem;
    background: color-mix(in srgb, var(--mud-palette-text-primary) 7%, var(--mud-palette-surface));
    align-self: flex-start;
}

.beg-bubble--mine {
    align-self: flex-end;
    background: color-mix(in srgb, var(--brand-cambridge-blue, #79A682) 22%, var(--mud-palette-surface));
}

.beg-bubble__who { font-size: 0.72rem; font-weight: 600; color: var(--mud-palette-text-secondary); }
.beg-bubble__body { white-space: pre-wrap; }
.beg-bubble__when { font-size: 0.68rem; color: var(--mud-palette-text-secondary); align-self: flex-end; }

.beg-reply { display: flex; gap: 0.5rem; align-items: flex-end; padding: 0 1rem 0.75rem; }
.beg-reply textarea { flex: 1; }

.beg-alts { padding: 0 1rem 0.5rem; }
.beg-alts__title { font-size: 0.9rem; font-weight: 600; margin: 0.25rem 0 0.4rem; }

.beg-alt {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    padding: 0.45rem 0.6rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 0.5rem;
    margin-bottom: 0.4rem;
}

.beg-alt__room { flex: 1 1 12rem; min-width: 0; }
.beg-alt__facts { color: var(--mud-palette-text-secondary); font-size: 0.82rem; flex: 1 1 12rem; }
.beg-actions { padding: 0 1rem 0.85rem; display: flex; gap: 0.5rem; flex-wrap: wrap; }

/* ---- Small-screen (phone) refinements ---- */
@media (max-width: 640px) {
    /* Stack the page header so the title and its actions no longer squeeze side by side. */
    .mcr-page-header {
        flex-direction: column;
        align-items: stretch;
        gap: 0.75rem;
    }

    .mcr-page-header__actions {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
    }

    /* Tighter page gutters so content is not pinched on a narrow screen. */
    .mud-main-content .mud-container {
        padding-left: 0.9rem;
        padding-right: 0.9rem;
    }

    /* Common filter and toolbar rows wrap instead of overflowing. */
    .fmd-toolbar,
    .table-toolbar,
    .search-filters,
    .datenav {
        flex-wrap: wrap;
    }

    /* Reply rows (feedback, messages) stack the box above its button. */
    .fbk__reply,
    .feedback-card__reply {
        flex-direction: column;
        align-items: stretch;
    }
}

/* A last-resort guard so no page can force the whole document to scroll sideways on a phone. */
@media (max-width: 900px) {
    body {
        overflow-x: hidden;
    }
}

/* ------------------------------------------------------------------------------------------------
   Booking journey: a "trainline" timeline of a booking from request to feedback closed. Reached
   stations are lit in the brand colour, the current one carries a ring, stations still ahead are
   dim, and an off-happy-path outcome (cancelled, rejected, no-show) shows in red. Theme-aware. The
   line scrolls horizontally on a narrow screen, like a tube map.
   ------------------------------------------------------------------------------------------------ */
.journey-dialog {
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, #101418);
    border-radius: 16px;
    padding: 1.5rem;
    width: min(62rem, 94vw);
    max-height: 88vh;
    overflow: auto;
    box-shadow: 0 20px 60px rgba(16, 20, 24, 0.35);
}

.journey-dialog__head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 1rem;
    margin-bottom: 1.25rem;
}

.journey-dialog__title {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0;
    font-size: 1.25rem;
    font-weight: 500;
}

.journey-dialog__sub {
    margin: 0.35rem 0 0;
    color: var(--mud-palette-text-secondary, #4a5a5a);
    font-size: 0.9rem;
}

.journey-dialog__loading,
.journey-dialog__empty {
    padding: 2rem;
    text-align: center;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.trainline {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    row-gap: 1.5rem;
    padding: 0.5rem 0 1rem;
}

/* A longer journey lays out as two balanced rows: the top row is --journey-cols wide, and the rest
   flow onto a second row beneath it (5 over 3 for eight stations, 6 over 4 for ten). */
.trainline--two-rows {
    display: grid;
    grid-template-columns: repeat(var(--journey-cols), minmax(0, 1fr));
    grid-auto-flow: row;
    align-items: start;
    row-gap: 1.5rem;
}

.trainline--two-rows .station {
    flex: none;
}

.station {
    /* Grow to fill each row evenly and wrap onto the next line rather than scrolling, so the line runs
       edge to edge and carries on below. A minimum basis keeps roughly six or seven stations per row. */
    flex: 1 1 8rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
}

.station__track {
    display: flex;
    align-items: center;
    width: 100%;
}

.station__line {
    flex: 1;
    height: 4px;
    background: var(--mud-palette-lines-default, #d5dede);
}

.station__line.is-filled {
    background: var(--mud-palette-primary, #1C4E4F);
}

.station__line--hidden {
    visibility: hidden;
}

.station__dot {
    flex: 0 0 auto;
    width: 2.6rem;
    height: 2.6rem;
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    background: var(--mud-palette-surface, #fff);
    border: 3px solid var(--mud-palette-lines-default, #d5dede);
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.station__label {
    margin-top: 0.5rem;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    padding: 0 0.35rem;
}

.station__title {
    font-weight: 500;
    font-size: 0.9rem;
    color: var(--mud-palette-text-primary, #101418);
}

.station__detail {
    font-size: 0.78rem;
    line-height: 1.25;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.station__when {
    margin-top: 0.15rem;
    font-size: 0.75rem;
    color: var(--mud-palette-text-disabled, #8a9a9a);
}

.station--done .station__dot {
    background: var(--mud-palette-primary, #1C4E4F);
    border-color: var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary-text, #F6FAF9);
}

.station--current .station__dot {
    border-color: var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary, #1C4E4F);
    box-shadow: 0 0 0 4px color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 22%, transparent);
}

.station--current .station__title {
    color: var(--mud-palette-primary, #1C4E4F);
}

.station--upcoming .station__dot {
    opacity: 0.6;
}

.station--upcoming .station__title,
.station--upcoming .station__detail {
    opacity: 0.7;
}

.station--alert .station__dot {
    background: #e5484d;
    border-color: #e5484d;
    color: #fff;
}

.station--alert .station__title {
    color: #e5484d;
}

.journey-dialog__legend {
    display: flex;
    gap: 1rem;
    flex-wrap: wrap;
    margin: 1rem 0 0;
    font-size: 0.78rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.journey-key {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.journey-key::before {
    content: "";
    width: 0.7rem;
    height: 0.7rem;
    border-radius: 50%;
}

.journey-key--done::before {
    background: var(--mud-palette-primary, #1C4E4F);
}

.journey-key--current::before {
    background: var(--mud-palette-surface, #fff);
    border: 2px solid var(--mud-palette-primary, #1C4E4F);
}

.journey-key--upcoming::before {
    background: var(--mud-palette-lines-default, #d5dede);
}

/* ---- Notification centre: a per-user event x channel grid ---- */
.notif-centre {
    max-width: 52rem;
}

.notif-group {
    margin-bottom: 1.75rem;
}

.notif-group__title {
    margin: 0 0 0.6rem;
    /* Branded section kicker: shared eyebrow metrics, in --brand-primary-ink (legible on light and
       dark), so it matches the Home hero and other section kickers rather than using the raw primary. */
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: var(--brand-primary-ink);
}

.notif-table {
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 12px;
    overflow: hidden;
    background: var(--mud-palette-surface, #fff);
}

.notif-row {
    display: grid;
    grid-template-columns: minmax(12rem, 1fr) repeat(3, 6.5rem);
    align-items: center;
    gap: 0.5rem;
    padding: 0.7rem 1rem;
    border-top: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
}

.notif-row:first-child {
    border-top: none;
}

.notif-row--head {
    background: color-mix(in srgb, var(--mud-palette-surface) 90%, var(--mud-palette-text-primary) 10%);
    font-size: 0.78rem;
    font-weight: 600;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

.notif-cell--channel {
    text-align: center;
}

.notif-row--head .notif-cell--channel {
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.notif-event__label {
    display: block;
    font-weight: 500;
    color: var(--mud-palette-text-primary, #101418);
}

.notif-event__help {
    display: block;
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #5b6b6b);
}

/* The channel toggle: the box shows the state; the text label is hidden on wide screens (the column
   header names the channel) and shown when the grid collapses on narrow screens. */
.notif-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    cursor: pointer;
}

.notif-toggle input {
    accent-color: var(--mud-palette-primary, #1C4E4F);
    width: 1.15rem;
    height: 1.15rem;
    cursor: pointer;
}

.notif-toggle__box { display: none; }

.notif-toggle__text {
    display: none;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #4a5a5a);
}

/* On narrow screens the grid stacks: the channel columns wrap under the event and each toggle shows
   its own label so it still reads. */
@media (max-width: 40rem) {
    .notif-row {
        grid-template-columns: 1fr;
        gap: 0.4rem;
    }

    .notif-row--head {
        display: none;
    }

    .notif-cell--channel {
        text-align: left;
    }

    .notif-toggle {
        justify-content: flex-start;
    }

    .notif-toggle__text {
        display: inline;
    }
}

/* Collapsible "what IT needs" help inside a locked integration card. */
.idp-help {
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 10px;
    padding: 0.35rem 0.75rem;
    background: var(--mud-palette-surface, #fff);
}

.idp-help__summary {
    cursor: pointer;
    font-weight: 500;
    color: var(--mud-palette-primary, #1C4E4F);
    padding: 0.35rem 0;
}

.idp-help__body {
    padding-top: 0.5rem;
}

.idp-help__body .teams-help {
    margin: 0.25rem 0 0;
    padding-left: 1.25rem;
    line-height: 1.6;
}

/* ---- Unified message-centre "All" list ---- */
.inbox-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 3rem 1rem;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

.inbox-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.inbox-item {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
    overflow: hidden;
}

.inbox-item--unread {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 7%, var(--mud-palette-surface));
}

.inbox-item__btn {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    width: 100%;
    padding: 0.75rem 1rem;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}

.inbox-item__btn:hover {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 5%, transparent);
}

.inbox-item__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-primary);
}

.inbox-item__icon--request { background: color-mix(in srgb, var(--mud-palette-secondary) 16%, var(--mud-palette-surface)); color: var(--mud-palette-secondary); }
.inbox-item__icon--approval { background: color-mix(in srgb, var(--mud-palette-warning) 16%, var(--mud-palette-surface)); color: var(--mud-palette-warning); }
.inbox-item__icon--notification { background: color-mix(in srgb, var(--mud-palette-info) 16%, var(--mud-palette-surface)); color: var(--mud-palette-info); }

.inbox-item__body {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
    flex: 1 1 auto;
}

.inbox-item__title {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.inbox-item__dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    flex: 0 0 auto;
}

.inbox-item__sub {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.inbox-item__meta {
    flex: 0 0 auto;
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    text-transform: uppercase;
    letter-spacing: var(--eyebrow-tracking);
    /* Real content, so it must meet AA: the disabled tone (38% black) is for disabled controls,
       which WCAG exempts; on an unread row it read at 2.6:1. */
    color: var(--mud-palette-text-secondary);
    align-self: center;
}

.inbox-item--pinned {
    border-color: var(--mud-palette-secondary);
    background: color-mix(in srgb, var(--mud-palette-secondary) 8%, var(--mud-palette-surface));
}

.inbox-item__pin { color: var(--mud-palette-secondary); }
.inbox-item__flag { color: var(--mud-palette-warning); }

/* ---- Inbox rules editor ---- */
.rule-form {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.rule-form__word {
    color: var(--mud-palette-text-secondary);
}

.rule-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.rule-item {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.7rem 1rem;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
}

.rule-item--off {
    opacity: 0.55;
}

.rule-item__order {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.6rem;
    height: 1.6rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-primary);
    font-size: 0.8rem;
    font-weight: 600;
    flex: 0 0 auto;
}

.rule-item__text {
    flex: 1 1 auto;
    color: var(--mud-palette-text-primary);
}

.rule-item__actions {
    display: flex;
    gap: 0.15rem;
    flex: 0 0 auto;
}

.icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    border: none;
    border-radius: 8px;
    background: none;
    color: var(--mud-palette-text-secondary);
    cursor: pointer;
}

.icon-btn:hover:not(:disabled) {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 8%, transparent);
    color: var(--mud-palette-text-primary);
}

.icon-btn:disabled {
    opacity: 0.4;
    cursor: default;
}

.icon-btn--danger:hover:not(:disabled) {
    background: color-mix(in srgb, var(--mud-palette-error) 14%, transparent);
    color: var(--mud-palette-error);
}

/* ---- Notifications inbox list (global so it applies wherever NotificationsList renders) ---- */
/* The notifications inbox. Colours derive from the MudBlazor palette variables so the list survives
   white-labelling and adapts to dark mode without a second rule set. */

.notif-empty {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.75rem;
    padding: 3rem 1rem;
    text-align: center;
    color: var(--mud-palette-text-secondary);
}

.notif-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.notif-item {
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 10px;
    background: var(--mud-palette-surface);
    overflow: hidden;
}

/* An unread item is tinted with the primary colour and carries a leading accent bar. */
.notif-item--unread {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 7%, var(--mud-palette-surface));
}

.notif-item__btn {
    display: flex;
    align-items: flex-start;
    gap: 0.85rem;
    width: 100%;
    padding: 0.85rem 1rem;
    background: none;
    border: none;
    text-align: left;
    cursor: pointer;
    color: inherit;
    font: inherit;
}

.notif-item__btn:hover {
    background: color-mix(in srgb, var(--mud-palette-text-primary) 5%, transparent);
}

.notif-item__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex: 0 0 auto;
    width: 2rem;
    height: 2rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--mud-palette-primary) 14%, var(--mud-palette-surface));
    color: var(--mud-palette-primary);
    margin-top: 0.1rem;
}

.notif-item__body {
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
    min-width: 0;
    flex: 1 1 auto;
}

.notif-item__subject {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

/* The venue chip on a tenantless recipient's notification row. The headline is the row's own
   weight, so the chip stays quiet beside it rather than competing with it. */
.notif-item__venue {
    flex: 0 0 auto;
    margin: 0;
    font-weight: 400;
}

.notif-item__dot {
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: var(--mud-palette-primary);
    flex: 0 0 auto;
}

.notif-item__text {
    color: var(--mud-palette-text-secondary);
    word-break: break-word;
}

.notif-item__when {
    font-size: 0.78rem;
    color: var(--mud-palette-text-disabled);
}

.notif-item__go {
    display: inline-flex;
    align-items: center;
    color: var(--mud-palette-text-disabled);
    flex: 0 0 auto;
    align-self: center;
}

.notif-toolbar {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 0.75rem;
}

/* Consent banner for the portal's optional Google Analytics (portal-analytics.js). Fixed to the
   bottom, brand colours, keyboard reachable. Shown only until the visitor accepts or declines. */
.cookie-consent {
    position: fixed;
    left: 1rem;
    right: 1rem;
    bottom: 1rem;
    z-index: 1400;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem 1.5rem;
    max-width: 60rem;
    margin: 0 auto;
    padding: 0.9rem 1.15rem;
    border-radius: 0.75rem;
    background: var(--brand-carbon-wing, #101418);
    color: var(--brand-sea-salt, #F6FAF9);
    box-shadow: 0 8px 30px rgba(16, 20, 24, 0.35);
}

.cookie-consent__text {
    margin: 0;
    font-size: 0.9rem;
    flex: 1 1 22rem;
}

.cookie-consent__actions {
    display: flex;
    gap: 0.5rem;
}

.cookie-consent__btn {
    font: inherit;
    font-weight: 500;
    padding: 0.5rem 1.1rem;
    border-radius: 999px;
    border: 1px solid transparent;
    cursor: pointer;
}

.cookie-consent__btn--accept {
    background: var(--brand-cambridge-blue, #79A682);
    color: var(--brand-carbon-wing, #101418);
}

.cookie-consent__btn--decline {
    background: transparent;
    color: var(--brand-sea-salt, #F6FAF9);
    border-color: color-mix(in srgb, var(--brand-sea-salt, #F6FAF9) 45%, transparent);
}

/* Food feedback star rating: interactive in the booker's dialog, static in the catering list. */
.food-rating {
    display: inline-flex;
    gap: 0.15rem;
    align-items: center;
}

.food-rating__star {
    background: none;
    border: none;
    padding: 0.1rem;
    cursor: pointer;
    color: var(--mud-palette-text-secondary, #5A6B68);
    line-height: 0;
}

.food-rating__star--on {
    color: var(--brand-mimosa, #F2B949);
}

.food-rating--static {
    gap: 0;
}

/* Notifications: per-item selection, select-all and paging. The checkbox is centred against the
   row so it lines up with the message, not floating near the top. */
.notif-item {
    display: flex;
    align-items: center;
}

.notif-item__check {
    display: flex;
    align-items: center;
    padding: 0.85rem 0 0.85rem 0.85rem;
}

.notif-item__btn {
    flex: 1 1 auto;
    min-width: 0;
}

.notif-item--selected {
    border-color: var(--mud-palette-primary);
    background: color-mix(in srgb, var(--mud-palette-primary) 10%, var(--mud-palette-surface));
}

/* The notification a notification email deep-linked to: blinks a couple of times on arrival, then
   keeps a primary edge so it stays unmistakable after the animation ends. Palette-derived, so a
   white-labelled tenant flashes in their own colour. */
.notif-item--flash {
    border-color: var(--mud-palette-primary);
    box-shadow: 0 0 0 1px var(--mud-palette-primary);
    animation: notif-flash 2.4s ease-out 1;
}

@keyframes notif-flash {
    0%, 40%, 80% {
        background: color-mix(in srgb, var(--mud-palette-primary) 28%, var(--mud-palette-surface));
    }

    20%, 60%, 100% {
        background: var(--mud-palette-surface);
    }
}

/* Motion-sensitive readers get the steady edge without the blinking. */
@media (prefers-reduced-motion: reduce) {
    .notif-item--flash {
        animation: none;
        background: color-mix(in srgb, var(--mud-palette-primary) 12%, var(--mud-palette-surface));
    }
}

.notif-selectall {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-right: auto;
    cursor: pointer;
}

.notif-pager {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    margin-top: 1rem;
}

.notif-pager__label {
    color: var(--mud-palette-text-secondary);
    font-size: 0.9rem;
}

/* ---------- Bug reporting ---------- */

/* The floating report-a-problem button. Kept small and low-contrast so it is present on every
   page without competing with the page's own actions. */
.bugreport-fab {
    position: fixed;
    right: 1.1rem;
    bottom: 1.1rem;
    z-index: 1500;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    border: none;
    border-radius: 999px;
    cursor: pointer;
    color: var(--mud-palette-primary-text, #fff);
    background: var(--mud-palette-primary, #1C4E4F);
    box-shadow: 0 4px 16px rgba(16, 20, 24, 0.25);
    opacity: 0.85;
}

.bugreport-fab:hover,
.bugreport-fab:focus-visible {
    opacity: 1;
}

/* The report dialog, a provider-free overlay like the idle and welcome overlays. Outside
   MudLayout, so set the brand font concretely (see .welcome-overlay). */
.bugreport-overlay {
    display: none;
    position: fixed;
    inset: 0;
    z-index: 1600;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(16, 20, 24, 0.55);
    font-family: 'Poppins', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    font-size: 0.95rem;
}

.bugreport-overlay--open {
    display: flex;
}

.bugreport-overlay__card {
    width: 100%;
    max-width: 34rem;
    max-height: 90vh;
    overflow-y: auto;
    padding: 2rem;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, #101418);
    border-radius: 14px;
    box-shadow: 0 12px 44px rgba(16, 20, 24, 0.3);
}

.bugreport-overlay__title {
    margin: 0 0 1rem;
    font-size: 1.35rem;
    font-weight: 500;
    color: var(--brand-carbon-wing);
}

.bugreport-overlay__label {
    display: block;
    margin-bottom: 0.35rem;
    font-weight: 500;
}

.bugreport-overlay__text {
    width: 100%;
    padding: 0.6rem 0.7rem;
    border: 1px solid var(--mud-palette-lines-inputs, #B6D2AD);
    border-radius: 8px;
    background: var(--mud-palette-background, #F6FAF9);
    color: inherit;
    font: inherit;
    resize: vertical;
}

.bugreport-overlay__consent {
    margin: 0.85rem 0;
    font-size: 0.88rem;
    color: var(--mud-palette-text-secondary, #445);
}

.bugreport-overlay__preview summary {
    cursor: pointer;
    font-size: 0.9rem;
    margin-bottom: 0.5rem;
}

.bugreport-overlay__error {
    margin: 0.75rem 0 0;
    color: var(--mud-palette-error, #e5484d);
}

.bugreport-overlay__actions {
    display: flex;
    gap: 0.6rem;
    justify-content: flex-end;
    margin-top: 1.1rem;
}

/* The crash banner: fixed above the page, never modal, because the page underneath may still be
   partly usable and reloading is the user's call. Outside MudLayout, so the brand font is set
   concretely here too. */
.bugreport-crash {
    position: fixed;
    left: 50%;
    bottom: 1.1rem;
    transform: translateX(-50%);
    z-index: 1700;
    width: min(38rem, calc(100vw - 2rem));
    font-family: 'Poppins', system-ui, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
    font-size: 0.95rem;
}

.bugreport-crash__card {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
    padding: 1.1rem 1.25rem;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, #101418);
    border-left: 4px solid var(--mud-palette-error, #e5484d);
    border-radius: 12px;
    box-shadow: 0 12px 44px rgba(16, 20, 24, 0.35);
}

.bugreport-crash__body {
    flex: 1;
}

.bugreport-crash__body p {
    margin: 0 0 0.6rem;
}

/* Queue flags and detail blocks on the MCR Bug reports page. */
.bugreport-flag {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.45rem;
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
    border-radius: 999px;
}

.bugreport-issue {
    display: inline-block;
    margin-left: 0.4rem;
    padding: 0.1rem 0.45rem;
    font-size: 0.72rem;
    font-weight: 500;
    color: var(--status-neutral-ink);
    border: 1px solid var(--mud-palette-lines-default, var(--brand-hairline));
    border-radius: 999px;
}

.bugreport-detail {
    padding: 0.75rem 0.5rem;
}

/* Help feedback queue: the helpful / not helpful chip. */
.helpfeedback-vote {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.1rem 0.55rem;
    font-size: 0.78rem;
    font-weight: 500;
    border-radius: 999px;
}

.helpfeedback-vote--yes {
    color: var(--status-positive-ink);
    background: var(--status-positive-wash);
}

.helpfeedback-vote--no {
    color: var(--status-warning-ink);
    background: var(--status-warning-wash);
}

.detail-section {
    margin-bottom: 0.9rem;
}

.detail-section__title {
    margin: 0 0 0.3rem;
    font-size: 0.95rem;
    font-weight: 500;
}

.detail-section__body {
    margin: 0;
    white-space: pre-wrap;
}

.detail-section__pre {
    max-height: 16rem;
    overflow: auto;
    margin: 0;
    padding: 0.6rem 0.7rem;
    font-size: 0.8rem;
    background: var(--mud-palette-background-gray, #EEF4F1);
    border-radius: 8px;
    white-space: pre-wrap;
    word-break: break-word;
}

/* =====================================================================================
   Food feedback page (/catering-feedback): the filter row with the "Pick a range"
   picker, the star spread distribution and the week-by-week table. This page cannot
   reach the chart bar styles in Analytics.razor.css (they are scoped to that
   component), so it carries its own. White-label safe: every colour derives from the
   MudBlazor palette variables with brand fallbacks. Nothing here animates, so there is
   nothing to gate behind prefers-reduced-motion.
   ===================================================================================== */

/* One row of filters (Showing, the optional range picker, Site), wrapping on narrow
   screens instead of forcing the two-column estate grid. */
.feedback-filters {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: var(--space-4) var(--space-5);
}

.feedback-filters .estate__field {
    flex: 0 1 13rem;
    min-width: 10rem;
}

.feedback-filters__range {
    flex: 0 1 17rem;
}

/* Star spread: one row per star level (5 down to 1) with the level as filled stars, a
   proportion bar sized against the biggest bucket, and the count as real text so colour
   is never the only signal. */
.feedback-dist {
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
}

.feedback-dist__row {
    display: grid;
    grid-template-columns: 7.5rem 1fr 2.5rem;
    align-items: center;
    gap: 0.6rem;
}

.feedback-dist__stars {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    color: var(--mud-palette-warning, var(--brand-mimosa, #F2B949));
}

.feedback-dist__track {
    display: block;
    height: 14px;
    background: var(--mud-palette-lines-default, var(--brand-hairline, rgba(20, 40, 40, 0.15)));
    border-radius: 999px;
    overflow: hidden;
}

.feedback-dist__track--slim {
    height: 8px;
}

.feedback-dist__fill {
    display: block;
    height: 100%;
    min-width: 2px;
    background: var(--mud-palette-primary, var(--brand-brunswick-green, #1C4E4F));
    border-radius: 999px;
}

.feedback-dist__count {
    font-size: 0.85rem;
    font-weight: 500;
    text-align: right;
    font-variant-numeric: tabular-nums;
}

/* Week by week: numeric columns right-aligned in tabular numerals, with a slim inline
   bar showing each week's share of the ratings volume. Fixed layout (with the table's
   colgroup) keeps the column widths stable, mirroring .mybookings-table; below
   MudBlazor's Sm breakpoint fixed widths would fight small screens, so it only applies
   from 600px up. */
.feedback-num {
    text-align: right;
    font-variant-numeric: tabular-nums;
}

@media (min-width: 600px) {
    .feedback-week-table table {
        table-layout: fixed;
    }
}

.feedback-week__volume {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.5rem;
    width: 100%;
}

.feedback-week__volume .feedback-dist__track {
    flex: 1 1 auto;
    max-width: 9rem;
}

.feedback-week__count {
    min-width: 2rem;
}

/* ============================================================================
   Help centre (/help) and its top-bar icon. Everything derives from the
   MudBlazor palette variables with brand fallbacks, so white-labelling flows.
   No inline script, no chart library.
   ============================================================================ */

/* The question-mark-in-a-circle icon in the app bar, matching the hamburger. */
.topbar-help {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    padding: 0.4rem;
    margin-right: 0.75rem;
    color: inherit;
    border-radius: 8px;
    text-decoration: none;
}

.topbar-help:hover {
    background: rgba(255, 255, 255, 0.12);
}

/* Welcoming banner. */
/* A slim find row under the page header. The old tall gradient hero was too heavy and buried the
   search; the search now stands on its own so it reads as the first thing to reach for. */
.help-find {
    margin: 0.25rem 0 1.5rem;
}

/* Card grid: choose a card to open its topic below. Flex, not grid, so the final row grows to fill
   the whole width instead of leaving a gap when the tile count is not a multiple of the row. */
.help-cards {
    display: flex;
    flex-wrap: wrap;
    gap: 0.85rem;
    margin-bottom: 1.75rem;
}

.help-card {
    flex: 1 1 13rem;
    min-width: 12rem;
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-rows: auto auto;
    column-gap: 0.7rem;
    row-gap: 0.15rem;
    text-align: left;
    padding: 0.9rem 1rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #D7E7E1);
    border-radius: 12px;
    cursor: pointer;
    transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}

.help-card:hover {
    border-color: var(--brand-cambridge-blue, #79A682);
    box-shadow: 0 3px 10px rgba(16, 20, 24, 0.08);
    transform: translateY(-1px);
}

.help-card--active {
    border-color: var(--mud-palette-primary, #1C4E4F);
    box-shadow: 0 0 0 2px var(--mud-palette-primary, #1C4E4F) inset;
}

.help-card__icon {
    grid-row: 1 / span 2;
    display: inline-flex;
    align-items: center;
    color: var(--mud-palette-primary, #1C4E4F);
}

.help-card__title {
    font-weight: 500;
    color: var(--mud-palette-text-primary, #142828);
}

.help-card__blurb {
    grid-column: 2;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #5b6b66);
}

/* Detail section for the chosen topic. Fills the available width: the readable body sits beside
   the common questions on wide screens, and stacks on narrow ones. */
.help-detail {
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #D7E7E1);
    border-radius: 12px;
    padding: 1.5rem 1.75rem;
    line-height: 1.55;
}

.help-detail__grid {
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    gap: 0 2.5rem;
    align-items: stretch;
}

/* A quiet divider between the article and its questions, so the pair reads as one panel and the
   article's white space looks deliberate rather than empty. */
.help-detail__faqs {
    padding-left: 2.5rem;
    border-left: 1px solid var(--mud-palette-lines-default, #D7E7E1);
}

@media (max-width: 800px) {
    .help-detail__grid { grid-template-columns: 1fr; }
    .help-detail__faqs {
        padding-left: 0;
        padding-top: 1.5rem;
        margin-top: 1.5rem;
        border-left: none;
        border-top: 1px solid var(--mud-palette-lines-default, #D7E7E1);
    }
}

.help-detail__main { max-width: 62ch; }

/* Vertical rhythm: give the heading, lead paragraph and lists room to breathe. */
.help-detail h3 {
    margin: 0 0 0.75rem;
    font-weight: 500;
    font-size: 1.2rem;
    color: var(--mud-palette-primary, #1C4E4F);
}

.help-detail__main p {
    margin: 0 0 1rem;
}

.help-detail ul {
    padding-left: 1.2rem;
    margin: 0 0 1rem;
}

.help-detail li {
    margin-bottom: 0.5rem;
}

.help-detail__main > *:last-child {
    margin-bottom: 0;
}

/* Role tag on a topic: a solid, clearly branded identity chip filled with the tenant's primary and
   its guaranteed-contrast on-primary text, so it reads as the tenant's colour under white-labelling
   and has real presence (a faint tint disappeared on the green theme). */
.help-tag {
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 600;
    padding: 0.22rem 0.7rem;
    border-radius: 999px;
    background: var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary-text, #F6FAF9);
    margin-bottom: 0.7rem;
}

/* Prominent find box: a clear, light bar that stands out under the page header. */
.help-search {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 0.7rem 1.1rem;
    background: var(--mud-palette-surface, #fff);
    border: 1px solid var(--mud-palette-lines-default, #D7E7E1);
    border-radius: 999px;
    max-width: 44rem;
    color: var(--mud-palette-primary, #1C4E4F);
    box-shadow: 0 1px 3px rgba(16, 20, 24, 0.06);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}

.help-search:focus-within {
    border-color: var(--brand-cambridge-blue, #79A682);
    box-shadow: 0 0 0 3px color-mix(in srgb, var(--brand-cambridge-blue, #79A682) 30%, transparent);
}

.help-search__input {
    flex: 1;
    min-width: 0;
    background: none;
    border: none;
    outline: none;
    color: var(--mud-palette-text-primary, #142828);
    font: inherit;
    font-size: 1rem;
}

.help-search__input::placeholder { color: var(--mud-palette-text-secondary, #6b7b76); }

.help-search__clear {
    background: none;
    border: none;
    color: var(--mud-palette-primary, #1C4E4F);
    cursor: pointer;
    font: inherit;
    font-size: 0.85rem;
    text-decoration: underline;
    white-space: nowrap;
}

/* Common questions accordion. */
.help-faqs__title {
    margin: 0 0 0.5rem;
    font-weight: 500;
    font-size: 0.95rem;
    color: var(--mud-palette-text-secondary, #5b6b66);
}

/* "Did this help?" feedback, recorded to the MCR Help feedback queue only (no email, no GitHub). */
.help-feedback {
    margin-top: 1.75rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--mud-palette-lines-default, #D7E7E1);
}

.help-feedback__ask {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-weight: 500;
}

.help-feedback__btn {
    background: none;
    border: 1px solid var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary, #1C4E4F);
    border-radius: 999px;
    padding: 0.25rem 1rem;
    font: inherit;
    cursor: pointer;
}

.help-feedback__btn.is-on {
    background: var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary-text, #F6FAF9);
}

.help-feedback__label {
    display: block;
    margin: 0.9rem 0 0.35rem;
    font-size: 0.88rem;
}

.help-feedback__text {
    width: 100%;
    max-width: 40rem;
    border: 1px solid var(--mud-palette-lines-default, #D7E7E1);
    border-radius: 10px;
    padding: 0.6rem 0.75rem;
    font: inherit;
    background: var(--mud-palette-surface, #fff);
    color: var(--mud-palette-text-primary, #142828);
    resize: vertical;
}

.help-feedback__note {
    font-size: 0.8rem;
    color: var(--mud-palette-text-secondary, #5b6b66);
    margin: 0.5rem 0 0.75rem;
}

.help-feedback__error { color: var(--mud-palette-error, #b3261e); }

.help-feedback__noted {
    font-size: 0.88rem;
    color: var(--mud-palette-text-secondary, #5b6b66);
    margin: 0.75rem 0 0.25rem;
}

.help-feedback__thanks {
    background: var(--brand-mint-cream, #D7E7E1);
    border-radius: 10px;
    padding: 0.75rem 1rem;
    margin: 0;
}

/* Revealable "show me an example" block. */
.help-example {
    margin-top: 1rem;
}

.help-example__toggle {
    background: none;
    border: 1px solid var(--mud-palette-primary, #1C4E4F);
    color: var(--mud-palette-primary, #1C4E4F);
    border-radius: 999px;
    padding: 0.3rem 0.9rem;
    font: inherit;
    font-size: 0.85rem;
    cursor: pointer;
}

.help-example__toggle:hover {
    background: var(--brand-mint-cream, #D7E7E1);
}

.help-example__body {
    margin-top: 0.75rem;
    padding: 0.9rem 1.1rem;
    background: var(--brand-mint-cream, #D7E7E1);
    border-radius: 10px;
}

.help-example__body p {
    margin: 0;
}

/* ==== Mobile polish (mobile-admin-polish) ==================================================== */

/* The app bar name lives on a MudText child component, so a scoped-CSS rule never reaches it;
   this one does. At handset widths the text yields entirely: the logo carries identity, and the
   two-line wrap it caused fattened the bar and pushed the avatar off the edge. */
.mud-appbar .appbar__name {
    white-space: nowrap;
}

@media (max-width: 599.98px) {
    .mud-appbar .appbar__name {
        display: none;
    }

    /* ---- The stacked-table system. MudBlazor's stacked mode (Breakpoint.Sm) was never styled
       for this portal: values clipped mid-character, desktop colgroup widths leaked in leaving
       half-empty cards, and action strips ran off the card edge. ---- */

    /* Desktop column widths mean nothing once rows stack; without this the stacked cells keep
       their percentage widths and the whole row squeezes into half the card. */
    .mud-table colgroup col {
        width: auto !important;
    }

    /* Long values (emails, cost codes, department names) wrap instead of clipping. */
    .mud-table .mud-table-cell {
        white-space: normal;
        word-break: break-word;
        overflow-wrap: anywhere;
        min-width: 0;
        flex-wrap: wrap;
        gap: 0.25rem 0.5rem;
    }

    /* Action-strip cells keep their buttons inside the card, wrapping onto further lines. */
    .mud-table .mud-table-cell .home-btn,
    .mud-table .mud-table-cell .mud-button-root {
        flex: 0 0 auto;
    }

    /* The sort header renders as a stray card in stacked mode; style it as the compact sort
       control it actually is rather than hiding the only sorting affordance on a phone. */
    .mud-table .mud-table-head .mud-table-cell {
        border-bottom: none;
        padding: 0.25rem 0.75rem;
        font-size: 0.85rem;
        color: var(--mud-palette-text-secondary, #4A5A5A);
    }

    /* The bug-report button floats over the bottom-right corner; give every page enough tail
       room that it can never sit on the last row's actions. */
    #main-content {
        padding-bottom: 5.5rem;
    }

    /* Header action rows and toolbars wrap as tidy rows rather than a ragged squeeze. */
    .mcr-page-header__actions {
        display: flex;
        flex-wrap: wrap;
        gap: 0.5rem;
        justify-content: flex-end;
    }

    .table-toolbar {
        flex-wrap: wrap;
    }
}

/* Tables that genuinely need their columns (the Food menus items table, the Estate rooms table)
   scroll sideways on narrow screens instead of hiding half their columns with no way to reach
   them: five of eight Food menus columns, including every row action, were simply off-screen. */
@media (max-width: 899.98px) {
    .food-admin-table .mud-table-container,
    .food-admin-table {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .food-admin-table table {
        min-width: 52rem;
    }

    .estate__table-scroll {
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
    }

    .estate__table-scroll .estate__table {
        min-width: 44rem;
    }
}

/* Shared modal-card shell used by both ModalDialog and ConfirmDialog. Kept in this global stylesheet
   (not scoped to either component) so any component that uses the modal-card__* class names picks
   up the branded look. Colours are all theme tokens so light and dark stay in step. */
.modal-card__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 1.1rem 1.5rem;
    background: var(--mud-palette-primary, #1C4E4F);
    border-radius: 14px 14px 0 0;
}

.modal-card__title {
    margin: 0;
    font-size: 1.2rem;
    font-weight: 500;
    color: var(--mud-palette-primary-text, #F6FAF9);
}

.modal-card__close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    color: var(--mud-palette-primary-text, #D7E7E1);
    background: none;
    border: none;
    border-radius: 8px;
    cursor: pointer;
    opacity: 0.85;
}

.modal-card__close:hover {
    background: rgba(255, 255, 255, 0.16);
    opacity: 1;
}

.modal-card__body {
    padding: 1.5rem;
}

.modal-card__foot {
    display: flex;
    gap: 0.5rem;
    justify-content: flex-end;
    flex-wrap: wrap;
    padding: 1rem 1.5rem;
    background: color-mix(in srgb, var(--mud-palette-surface, #F6FAF9) 92%, var(--mud-palette-text-primary, #101418) 8%);
    border-top: 1px solid var(--mud-palette-lines-default, rgba(20, 40, 40, 0.12));
    border-radius: 0 0 14px 14px;
}

.modal-card__error {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    margin: 0 0 0.85rem;
    padding: 0.5rem 0.75rem;
    border-radius: 8px;
    color: var(--mud-palette-error, #C62828);
    background: var(--mud-palette-error-hover, rgba(198, 40, 40, 0.08));
    font-size: 0.9rem;
}

/* ConfirmDialog: suppress MudDialog's default title bar and inner padding so our
   modal-card__head/body/foot fill the paper edge-to-edge. These rules cannot live in
   ConfirmDialog.razor.css because MudBlazor's dialog service portals the MudDialog output
   through MudDialogProvider, so ConfirmDialog's scoped-CSS attribute never lands on the
   .mud-dialog node; ::deep in the scoped file matches nothing, and the default MudPaper
   wraps the styled shell with a white gutter. Keyed off the .confirm-dialog and
   .confirm-dialog__content classes we pass via Class and ContentClass. */
.confirm-dialog.mud-dialog {
    padding: 0;
    background: var(--mud-palette-surface, #fff);
    border-radius: 14px;
    overflow: hidden;
}

.confirm-dialog .mud-dialog-title {
    display: none;
}

.confirm-dialog .mud-dialog-content,
.confirm-dialog__content {
    padding: 0 !important;
    overflow: visible;
}

.confirm-dialog .mud-dialog-actions {
    display: none;
}

/* ===========================================================================
   Portal hero: ONE treatment, rendered by Components/Shared/PortalHero.razor.
   ===========================================================================
   Home and ExhibitorHome each had their own hero and they drifted: the
   exhibitor's lost the ghosted wordmark and the whole call-to-action row. These
   rules live in app.css rather than the component's scoped stylesheet because
   the lede and actions are passed in as child content, which carries the PARENT
   page's scope attribute and so is unreachable from a scoped file here.

   Two grounds, one layout. The default derives from the tenant's chosen scheme.
   `--product` paints the fixed Symphony Spaces colours for a tenantless surface
   (the exhibitor's home is product-level and must not take on a venue's brand).
   =========================================================================== */
.portal-hero {
    position: relative;
    overflow: hidden;
    border-radius: 16px;
    padding: 2.5rem;
    margin-bottom: var(--gap-lg);
    color: var(--mud-palette-primary-text, #F6FAF9);
    background: linear-gradient(135deg,
        var(--mud-palette-primary, #1C4E4F) 0%,
        color-mix(in srgb, var(--mud-palette-primary, #1C4E4F) 45%, #101418) 100%);
}

/* Fixed product ground: Brunswick Green to Carbon Wing, never the tenant's primary. */
.portal-hero--product {
    color: var(--brand-sea-salt);
    background: linear-gradient(135deg, #1C4E4F 0%, color-mix(in srgb, #1C4E4F 45%, #101418) 100%);
}

.portal-hero__body {
    position: relative;
    z-index: 1;
    /* Capped so the text never runs under the watermark on a wide screen. */
    max-width: 34rem;
}

.portal-hero__eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 12px;
    margin: 0 0 0.5rem;
    font-size: var(--eyebrow-size);
    font-weight: var(--eyebrow-weight);
    letter-spacing: var(--eyebrow-tracking);
    text-transform: uppercase;
    color: color-mix(in srgb, var(--mud-palette-primary-text, #F6FAF9) 78%, transparent);
}

.portal-hero--product .portal-hero__eyebrow {
    color: color-mix(in srgb, var(--brand-sea-salt) 78%, transparent);
}

/* The wordmark's signature Mimosa rule. Mimosa is a fixed brand accent, not the primary, so it
   stays literal through its token on both grounds. */
.portal-hero__eyebrow::before {
    content: "";
    flex: 0 0 auto;
    width: 28px;
    height: 3px;
    border-radius: 2px;
    background: var(--brand-mimosa);
}

.portal-hero__title {
    margin: 0 0 0.75rem;
    font-size: clamp(1.9rem, 4vw, 2.75rem);
    font-weight: 500;
    line-height: 1.1;
}

.portal-hero__lede {
    margin: 0 0 var(--gap-lg);
    font-size: 1.05rem;
    color: color-mix(in srgb, var(--mud-palette-primary-text, #F6FAF9) 88%, transparent);
}

.portal-hero--product .portal-hero__lede {
    color: color-mix(in srgb, var(--brand-sea-salt) 88%, transparent);
}

.portal-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
}

/* A subtle watermark sitting wholly INSIDE the hero. The wordmark is two words
   ("SYMPHONY SPACES"), so any bleed past the right edge amputates a glyph and reads as a layout
   bug rather than a design choice. */
.portal-hero__mark {
    position: absolute;
    top: 50%;
    right: 2rem;
    width: min(30rem, 45%);
    height: auto;
    transform: translateY(-50%);
    opacity: 0.12;
    pointer-events: none;
}

/* Narrow widths: the watermark would sit under the title and lede, so drop it and let the text
   have the full width. The actions row wraps on its own (flex-wrap above). */
@media (max-width: 48rem) {
    .portal-hero {
        padding: 1.75rem 1.5rem;
    }
    .portal-hero__body {
        max-width: 100%;
    }
    .portal-hero__mark {
        display: none;
    }
}

/* ===========================================================================
   Card stack: THE way a vertical stack of cards is spaced in this portal.
   ===========================================================================
   Spacing belongs to the CONTAINER, never to sibling margins. Every previous
   attempt used `.card + .card { margin-block-start: ... }`, and the
   adjacent-sibling combinator only matches two cards that are IMMEDIATELY
   adjacent: any wrapper, grid, or conditionally-rendered block between them
   silently drops the gap. That is why the same complaint came back five times
   on five different pages, each fix repairing only the case in front of it.

   A flex column with a gap applies to every child whatever it is, whatever
   wraps it, and whether or not it renders. Use `.card-stack` on any page that
   stacks cards, and do NOT add a `+` margin rule alongside it, or gaps double.
   =========================================================================== */
.card-stack {
    display: flex;
    flex-direction: column;
    gap: var(--gap-lg);
}

/* MudGrid ships its own negative gutter margin. Inside a flex column that would
   eat the first gap, so pin it: a KPI strip sits the same distance from the card
   below it as every other pair. */
.card-stack > .mud-grid {
    margin: 0;
    width: 100%;
}

/* A footer note beside a dialog's action button (for example "your answers save as you enter
   them"). Global, not scoped: MudDialogProvider portals the dialog, so a scoped attribute never
   lands on it, the same reason .confirm-dialog's rules live here. */
.modal-card__foot-note {
    margin-inline-end: auto;
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #526670);
}

/* Optional tick-list inside the confirm dialog (for example the events an exhibitor's revoke
   should cover). Scrolls rather than growing the dialog past the viewport on a long list. */
.confirm-dialog__choices {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-block-start: 0.85rem;
    max-height: 18rem;
    overflow-y: auto;
}

.confirm-dialog__choice {
    display: flex;
    align-items: flex-start;
    gap: 0.6rem;
    padding: 0.5rem 0.6rem;
    border: 1px solid var(--mud-palette-lines-default, #d0d7d3);
    border-radius: 8px;
    cursor: pointer;
}

.confirm-dialog__choice:hover {
    background: var(--mud-palette-action-default-hover, rgba(16, 20, 24, 0.04));
}

.confirm-dialog__choice--all {
    border-style: dashed;
    font-weight: 500;
}

.confirm-dialog__choice-body {
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
    min-width: 0;
}

.confirm-dialog__choice-label {
    color: var(--mud-palette-text-primary, #101418);
}

.confirm-dialog__choice-detail {
    font-size: 0.85rem;
    color: var(--mud-palette-text-secondary, #526670);
}

.confirm-dialog__choice-note {
    font-size: 0.85rem;
    color: var(--mud-palette-warning-darken, #8a6100);
}

/* Exhibitor cards and panel grid: shared between ExhibitorHome (rendered at /) and MyEvents
   (/my-events) so the exhibitor sees the same shell across both entry points. Promoted from the
   ExhibitorHome scoped CSS in the exhibitor-home-and-event-detail change. */

.exhibitor-panel {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.exhibitor-panel__heading {
    margin: 0;
}

.exhibitor-panel__empty {
    padding: 1.5rem;
    background: var(--mud-palette-surface);
    border-radius: 12px;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.exhibitor-panel__grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 1rem;
}

.exhibitor-card {
    display: flex;
    flex-direction: column;
    border-radius: 12px;
    overflow: hidden;
    background: var(--mud-palette-surface);
    border: 1px solid var(--mud-palette-lines-default);
    transition: box-shadow 120ms ease, transform 120ms ease;
}

.exhibitor-card:hover {
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
}

.exhibitor-card--past {
    opacity: 0.92;
}

.exhibitor-card__image {
    height: 140px;
    background-size: cover;
    background-position: center;
    background-color: var(--mud-palette-background-grey);
}

.exhibitor-card__image--placeholder {
    background-image: linear-gradient(135deg, var(--mud-palette-primary), var(--mud-palette-primary-lighten));
}

.exhibitor-card__content {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 1rem 1.25rem 0.5rem;
}

.exhibitor-card__title {
    margin: 0;
}

.exhibitor-card__when {
    margin: 0;
    color: var(--mud-palette-text-secondary);
}

.exhibitor-card__bookings {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
    margin-top: 0.25rem;
}

.exhibitor-card__actions {
    padding: 0.5rem 1.25rem 1rem;
}

.my-events__heading {
    margin: 0 0 0.75rem 0;
}

.my-events__section {
    margin-bottom: 2rem;
}

.my-events__section--past {
    margin-top: 2rem;
}

.my-events__rate {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin-top: 0.5rem;
}

.my-events__rate-stars {
    display: flex;
    gap: 0.125rem;
}

.my-events__rate-hint {
    margin: 0;
}

/* Shared event field set (Components/Shared/EventFieldSet.razor), used by the New event form and
   the Edit event modal. Global rather than scoped so both hosts get identical spacing: a scoped
   sheet on the component would still be scoped to the component, but its two callers each wrap it
   in their own container, and this is the pair that drifted in the first place. */
.event-fields {
    display: flex;
    flex-direction: column;
    gap: var(--gap-md);
}

/* Date and time pickers flow in a responsive row: four across on a wide modal, wrapping to two or
   one as the space narrows, so a picker never squeezes to unusable. */
.event-fields__row {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(170px, 1fr));
    gap: var(--gap-sm);
}

.event-fields__key-dates {
    background: transparent;
}

/* Rows in the submitted-details dialog (what one exhibitor supplied, and the organiser's route to
   correct it). Global because MudDialogProvider portals the dialog, as with .confirm-dialog. */
.submitted-details__row {
    margin-block-end: var(--gap-sm);
}
