#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

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

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto 0 auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

/* Approvals: rows and cards whose approval step has passed its SLA due date. FlexTable applies the class
   through its RowClass callback (see Approvals.razor.cs), so the marker has to live in a global stylesheet
   rather than a scoped one - scoped CSS would rewrite the selector with this component's scope id, which a
   class name handed to KBlazor never carries. */
.sla-overdue > td:first-child {
    border-left: 3px solid var(--mud-palette-error);
}

.sla-overdue {
    background-color: rgba(244, 67, 54, 0.08) !important;
}

.sla-overdue-text {
    color: var(--mud-palette-error);
}

/* Steps of an approval chain that have not been opened yet. */
.approval-chain-upcoming {
    color: var(--mud-palette-text-disabled);
}

/* Horizon theme (UI-1): status-tone colour pairs shared by status chips and policy-check rows. --*-fg/-bg
   are the single source of truth for LeaveApp.Client.Components.Horizon.StatusTonePalette -
   StatusTonePaletteTests recomputes each pair's WCAG contrast ratio (>= 4.5:1 for normal text) and asserts
   this file contains the exact same hex values, so app.css and the C# constants can't drift apart. --*-icon
   keeps the full-saturation Horizon token hue (HorizonTheme.Teal/Amber/Brick) for icons, which are
   decorative next to the label text and don't carry the 4.5:1 text-contrast requirement. */
:root {
    --horizon-approved-fg: #22746B;
    --horizon-approved-bg: #E3F1EE;
    --horizon-approved-icon: #247C73;

    --horizon-pending-fg: #945D19;
    --horizon-pending-bg: #FBEFD9;
    --horizon-pending-icon: #D9902F;

    --horizon-error-fg: #A1493F;
    --horizon-error-bg: #F6E3E0;
    --horizon-error-icon: #B65247;

    --horizon-neutral-fg: #4A4F52;
    --horizon-neutral-bg: #ECE9E3;
    --horizon-neutral-icon: #4A4F52;

    /* Hollow/skipped approval-chain markers: a mid grey between the divider and secondary text. */
    --horizon-muted: #8A8F8E;

    /* Request detail's pinned action bar on a phone (see .horizon-detail__footer-actions). */
    --horizon-detail-footer-height: 72px;
}

/* Horizon theme (UI-1): shared surface treatments for cards and chips. */
.horizon-card {
    border-radius: 16px;
    box-shadow: 0 1px 2px rgba(36,41,45,.06), 0 4px 16px rgba(36,41,45,.04);
    border: 1px solid #DDD8CF;
}

.horizon-chip {
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 4px 10px;
    font-size: .8125rem;
    font-weight: 600;
}

/* Status chip tones (StatusTone.cs): the four colours every status-shaped enum maps onto. */
.horizon-chip--approved {
    background-color: var(--horizon-approved-bg);
    color: var(--horizon-approved-fg);
}

.horizon-chip--pending {
    background-color: var(--horizon-pending-bg);
    color: var(--horizon-pending-fg);
}

.horizon-chip--error {
    background-color: var(--horizon-error-bg);
    color: var(--horizon-error-fg);
}

.horizon-chip--neutral {
    background-color: var(--horizon-neutral-bg);
    color: var(--horizon-neutral-fg);
}

/* PageHeader: title row, optional actions slot, and the page's help button. The help button is hidden on
   desktop because MainLayout's app bar carries page help there instead; it stays visible on mobile, which
   has no app-bar help slot. */
.page-header {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}

.page-header__titles {
    flex: 1 1 auto;
    min-width: 0;
}

.page-header__help {
    display: block;
}

@media (min-width: 768px) {
    .page-header__help {
        display: none;
    }
}

/* MudBlazor's default h3 (Typo.h3, what every PageHeader title renders as) is sized for a full desktop
   heading - on a 375px phone that's ~48px, wrapping a greeting like "Good evening, Shawn" onto three lines.
   Every page's title shrinks to a size that reads as one line at phone width; desktop is untouched. */
@media (max-width: 767px) {
    .page-header__titles .mud-typography-h3 {
        font-size: 1.75rem;
        line-height: 1.25;
    }
}

/* BalanceImpact: current -> new balance, with an optional fill bar. */
.horizon-balance-impact {
    display: flex;
    align-items: center;
    gap: 16px;
}

.horizon-balance-impact__now,
.horizon-balance-impact__after {
    display: flex;
    flex-direction: column;
}

.horizon-balance-impact__caption {
    font-size: .75rem;
    color: #6B706F;
}

.horizon-balance-impact__value {
    font-size: 1.125rem;
    font-weight: 700;
    color: #222629;
}

.horizon-balance-impact__arrow {
    color: #6B706F;
}

.horizon-balance-impact__bar {
    height: 8px;
    border-radius: 999px;
    background-color: #ECE9E3;
    overflow: hidden;
    margin-top: 8px;
}

.horizon-balance-impact__bar-fill {
    height: 100%;
    background-color: #F7941D;
}

/* RequestSummary: type, date range and day total. */
.horizon-request-summary {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.horizon-request-summary__icon {
    color: #6B706F;
    margin-top: 2px;
}

/* PolicyChecks: one reassuring row when clean, otherwise a row per policy result. */
.horizon-policy-checks__row {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 8px 12px;
    border-radius: 8px;
}

.horizon-policy-checks__row + .horizon-policy-checks__row {
    margin-top: 8px;
}

.horizon-policy-checks__row--pass {
    background-color: var(--horizon-approved-bg);
    color: var(--horizon-approved-fg);
}

.horizon-policy-checks__row--pending {
    background-color: var(--horizon-pending-bg);
    color: var(--horizon-pending-fg);
}

.horizon-policy-checks__row--error {
    background-color: var(--horizon-error-bg);
    color: var(--horizon-error-fg);
}

/* ---- My Leave (UI-1 Task 6): gauge row, Request Leave tile, upcoming/recent panels, recent-requests timeline ---- */

/* Desktop, narrow (768-899px viewport, ~456-588px of content once the 248px drawer and 64px of page padding
   are subtracted): two columns. auto-fit/minmax wraps rather than overflowing, and two 200px+ columns is the
   most this width can fit without squeezing four gauge cards down to an unreadable width. */
.horizon-gauge-row--desktop {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;
}

/* Desktop, 900px viewport and up: always exactly four columns (Available, Pending, Taken, the Request Leave
   tile), matching the mockup. minmax(0, 1fr) rather than auto-fit here on purpose - between roughly 900px
   and 1160px of viewport width, auto-fit's own math (floor((content + gap) / (200 + gap)) columns) lands on
   exactly three, orphaning the tile onto its own row where it renders as a ~20px strip instead of a
   number-tile-sized tile (there's no taller sibling in that row for grid's default align-items: stretch to
   match). Forcing four fixed tracks - shrinking them instead of wrapping - both matches the mockup and
   sidesteps that dead zone entirely. */
@media (min-width: 900px) {
    .horizon-gauge-row--desktop {
        grid-template-columns: repeat(4, minmax(0, 1fr));
    }
}

/* With floating days the row has a fifth tile (Floating days before the Request Leave tile). */
@media (min-width: 900px) {
    .horizon-gauge-row--desktop.horizon-gauge-row--five {
        grid-template-columns: repeat(5, minmax(0, 1fr));
    }
}

/* Mobile: Available spans the full width above a Pending/Taken pair - the tile never renders here. Always
   exactly two columns (not auto-fit): at a 320-375px viewport there's only room for one column's worth of
   gauge before auto-fit would collapse to a single column anyway, and .horizon-number-tile's min-width: 0
   (below) is what lets two columns actually fit
   without overflowing, not the track-sizing function. */
.horizon-gauge-row--mobile {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
}

.horizon-gauge-row--mobile .horizon-number-tile:first-child,
.horizon-gauge-row--mobile .horizon-number-tile--floating {
    grid-column: 1 / -1;
}

/* My Leave number tiles (they replaced the dials): label over a large figure. min-width: 0 lets a grid
   item shrink below its content's natural width so two columns fit a 375px phone. */
.horizon-number-tile { display: flex; flex-direction: column; justify-content: center; gap: 4px; min-width: 0; }

.horizon-request-tile {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    /* Grid's default align-items: stretch already matches this to its row's tallest cell whenever it shares
       a row with a number tile (true for every desktop width now - see the two rules above); this is a floor
       for whatever's left, approximating a number tile's own rendered height (label + figure + 32px of MudPaper
       pa-4 padding), so it's never a thin strip even if it does end up alone in a row. */
    min-height: 120px;
    border-radius: 16px;
    background-color: var(--mud-palette-primary);
    color: #FFFFFF;
    font-weight: 700;
    text-decoration: none;
}

.horizon-request-tile:hover {
    color: #FFFFFF;
    opacity: .92;
}

.horizon-request-tile__label {
    white-space: nowrap;
}

/* Upcoming leave / Recent requests panels: side by side on desktop once there's room for two ~320px+
   columns, stacked (mobile, and a narrow desktop viewport) otherwise - auto-fit/minmax collapses to a
   single column rather than squeezing both panels and overflowing horizontally. */
.horizon-panels {
    display: flex;
    flex-direction: column;
    gap: 16px;
}

.horizon-panels--desktop {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(360px, 1fr));
    align-items: start;
}

.horizon-upcoming {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 16px;
    border-radius: 12px;
    background-color: var(--horizon-approved-bg);
    cursor: pointer;
}

/* Recent requests: a vertical rail with a tone-coloured dot per request. */
.horizon-timeline {
    position: relative;
    padding-left: 20px;
}

.horizon-timeline__item {
    position: relative;
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 10px 0;
    cursor: pointer;
}

.horizon-timeline__item:not(:last-child)::after {
    content: "";
    position: absolute;
    left: -15px;
    top: 20px;
    bottom: -10px;
    width: 2px;
    background-color: var(--horizon-neutral-bg);
}

.horizon-timeline__dot {
    position: absolute;
    left: -20px;
    top: 12px;
    width: 10px;
    height: 10px;
    border-radius: 50%;
}

.horizon-timeline__dot--approved { background-color: var(--horizon-approved-icon); }
.horizon-timeline__dot--pending { background-color: var(--horizon-pending-icon); }
.horizon-timeline__dot--error { background-color: var(--horizon-error-icon); }
.horizon-timeline__dot--neutral { background-color: var(--horizon-neutral-icon); }

.horizon-timeline__body {
    flex: 1 1 auto;
    min-width: 0;
}

.horizon-timeline__range {
    font-weight: 700;
}

.horizon-timeline__attachment {
    color: #6B706F;
    margin-top: 2px;
}

/* ---- Horizon shell (UI-1 Task 4): DesktopShell / MobileShell / NavMenu / UserMenu / MoreSheet ---- */

.brand-wordmark {
    font-family: Montserrat, Inter, sans-serif;
    font-weight: 700;
    font-size: 22px;
    line-height: 1.2;
    white-space: nowrap;
}

.brand-wordmark .brand-accent {
    color: #F7941D;
}

.brand-wordmark--drawer {
    color: #FFFFFF;
    padding: 24px 16px 20px;
    /* "JP Marshall Leave" at the base 22px once caused a horizontal scrollbar in the drawer, and "JPM Leave
       Management" is longer still (~13em of nowrap bold Montserrat). At 16px it is ~206px, inside the drawer's
       216px content width (248px minus this padding). .horizon-drawer's overflow-x: hidden (below) is the
       backstop in case anything else (e.g. a long nav label) ever overflows. */
    font-size: 16px;
}

.brand-wordmark--topbar {
    color: #222629;
    /* ~13em wide for "JPM Leave Management", so 15px (~195px) is what fits beside the bell and avatar at
       320px; the ellipsis below covers anything tighter. */
    font-size: 15px;
    /* The one shrinkable/truncatable piece of .mobile-topbar's content - the bell and avatar next to it are
       fixed-size and have nothing to give, so at the narrowest supported phone width (320px) this is what
       must give way (ellipsis) rather than pushing the avatar past the visible edge. min-width: 0 overrides
       a flex item's default automatic minimum, which is otherwise its nowrap text's full width. */
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Desktop drawer: charcoal, no elevation; nav items get rounded hover/active surfaces. overflow-x: hidden
   works around a CSS default: MudBlazor's own .mud-drawer sets overflow-y: auto and leaves overflow-x at its
   initial value (visible) - but per the CSS Overflow spec, "visible" on one axis computes to "auto" when the
   other axis isn't "visible", so any content even 1px wider than the drawer's 248px (the wordmark, a long
   nav label) was enough to draw a horizontal scrollbar along the bottom of the whole drawer. */
.horizon-drawer {
    border-right: none;
    overflow-x: hidden;
}

/* The drawer is a fixed-height flex column: let the menu shrink and part of it ends up scrolling in its own
   box. Keep the menu at full height; the drawer itself scrolls if a short window ever needs it to. */
.horizon-drawer .horizon-nav {
    flex-shrink: 0;
}

.horizon-drawer .mud-navmenu .mud-nav-link {
    border-radius: 8px;
    margin: 2px 12px;
    /* Not width: auto - the link is a flex item of .mud-nav-item (and the group header a button), so auto
       shrinks it to its label and the hover/active surface stopped short of the drawer's right side. */
    width: calc(100% - 24px);
    padding: 10px 12px;
    color: #E9E6E0;
}

.horizon-drawer .mud-navmenu .mud-nav-link:hover:not(.mud-nav-link-disabled) {
    background-color: rgba(255, 255, 255, .06);
}

/* Active item: charcoal surface, 4px orange bar flush with the drawer's left edge, orange icon. The bar is a
   ::before reaching back across the link's 12px margin; MudBlazor's ripple sets overflow:hidden on the link
   (and draws its ripple with ::after), so the active link re-opens overflow to let the bar show. */
.horizon-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) {
    position: relative;
    overflow: visible;
    background-color: #30363B;
    color: #FFFFFF;
    font-weight: 600;
}

.horizon-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled)::before {
    content: "";
    position: absolute;
    left: -12px;
    top: 0;
    bottom: 0;
    width: 4px;
    border-radius: 0 4px 4px 0;
    background-color: #F7941D;
}

.horizon-drawer .mud-navmenu .mud-nav-link.active:not(.mud-nav-link-disabled) .mud-nav-link-icon {
    color: #F7941D;
}

/* The Admin section: a quiet, non-interactive heading over its links, which sit indented beneath it. */
.horizon-nav-heading {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 18px 12px 4px;
    padding: 0 12px;
    color: #9AA0A6;
    font-size: 12px;
    font-weight: 600;
    letter-spacing: .06em;
    text-transform: uppercase;
}

/* MudNavLink puts Class on its .mud-nav-item wrapper, not on the link itself. */
.horizon-drawer .mud-navmenu .horizon-nav-sub .mud-nav-link {
    padding-left: 28px;
}

/* Desktop app bar: paper, flat, hairline bottom border. */
.horizon-appbar {
    border-bottom: 1px solid #DDD8CF;
}

.horizon-appbar .mud-toolbar {
    gap: 8px;
    padding-left: 32px;
    padding-right: 24px;
}

.horizon-appbar__title {
    font-weight: 600;
}

.horizon-appbar__divider {
    width: 1px;
    height: 32px;
    background-color: #DDD8CF;
    margin: 0 8px;
}

/* MudBlazor's own .mud-main-content rule sets padding-top: var(--mud-appbar-height) to clear the fixed
   MudAppBar; app.css loads after MudBlazor's stylesheet, so this shorthand `padding` (same selector
   specificity, later in the cascade) must repeat that clearance itself rather than resetting padding-top to
   24px and pushing the page heading under the app bar. */
.horizon-main {
    background-color: #F6F2EA;
    min-height: 100vh;
    padding: calc(var(--mud-appbar-height) + 24px) 32px 24px;
}

/* UserMenu activator: charcoal avatar with initials, then (desktop) name and chevron. */
.user-menu__activator.mud-button-root {
    min-width: 0;
    padding: 4px 8px 4px 4px;
    border-radius: 999px;
    color: inherit;
}

.user-menu__activator .mud-button-label {
    gap: 10px;
}

.user-menu .user-menu__avatar {
    background-color: #24292D;
    color: #FFFFFF;
    font-weight: 600;
    font-size: .875rem;
}

.user-menu__name {
    font-size: .9375rem;
    color: #222629;
}

/* Mobile top bar: 56px, paper, hairline bottom border, fixed. overflow-x: hidden is a backstop against the
   whole bar (and so the page) picking up horizontal scroll if its content ever slightly outgrows a narrow
   phone width - the wordmark below is the one piece of content that can actually give up space to prevent
   that happening in the first place; the bell/avatar have no spare space to give and must stay whole. */
.mobile-topbar {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 56px;
    z-index: 1100;
    display: flex;
    align-items: center;
    gap: 4px;
    padding: 0 8px 0 16px;
    overflow-x: hidden;
    background-color: #FFFDF9;
    border-bottom: 1px solid #DDD8CF;
}

.horizon-main--mobile {
    padding: calc(56px + 16px) 16px calc(72px + 16px + env(safe-area-inset-bottom));
}

/* Mobile bottom nav: 64px, four labelled items; Request is a raised orange circle. */
.bottom-nav {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    height: calc(64px + env(safe-area-inset-bottom));
    padding-bottom: env(safe-area-inset-bottom);
    z-index: 1100;
    display: flex;
    align-items: stretch;
    background-color: #FFFDF9;
    border-top: 1px solid #DDD8CF;
}

.bottom-nav__item {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    color: #6B706F;
    text-decoration: none;
    background: none;
    border: none;
    font: inherit;
    cursor: pointer;
    padding: 0;
}

.bottom-nav__label {
    font-size: .75rem;
    line-height: 1;
    white-space: nowrap;
}

.bottom-nav__item--active,
.bottom-nav__item--active .bottom-nav__icon {
    color: #F7941D;
}

.bottom-nav__item--active .bottom-nav__label {
    font-weight: 600;
}

.bottom-nav__item--request {
    justify-content: flex-end;
    padding-bottom: 8px;
}

.bottom-nav__request-circle {
    width: 56px;
    height: 56px;
    border-radius: 50%;
    margin-top: -28px;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: #F7941D;
    box-shadow: 0 4px 12px rgba(247, 148, 29, .35);
    border: 3px solid #FFFDF9;
}

.bottom-nav__request-circle .bottom-nav__icon {
    color: #FFFFFF;
}

.bottom-nav__item--request.bottom-nav__item--active .bottom-nav__request-circle .bottom-nav__icon {
    color: #FFFFFF;
}

/* MoreSheet: bottom-anchored dialog with rounded top corners. */
.mud-dialog.more-sheet {
    border-radius: 16px 16px 0 0;
    margin: 0;
}

.more-sheet__heading {
    display: block;
    padding: 0 16px;
    color: #6B706F;
}

/* Request Leave (desktop): the summary card stays in view while the form scrolls - only once the grid
   puts it beside the form (MudBlazor's md breakpoint, 960px); stacked under the form it just scrolls. */
@media (min-width: 960px) {
    .horizon-request__summary {
        position: sticky;
        top: 96px;
    }
}

.horizon-request__actions {
    display: flex;
    justify-content: flex-end;
    flex-wrap: wrap;
    gap: 12px;
}

/* Attachment drop zone: MudFileUpload keeps its file input in the DOM (Hidden="false"), stretched
   transparently over the dashed zone so a dropped or clicked file lands on the input itself. */
.horizon-dropzone-host {
    position: relative;
    max-width: 100%;
}

.horizon-dropzone-input {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    cursor: pointer;
    z-index: 1;
}

.horizon-dropzone {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    min-height: 96px;
    padding: 16px;
    border: 1px dashed #BDB6AA;
    border-radius: 12px;
    color: #4A4F4E;
    text-align: center;
    overflow-wrap: anywhere;
}

.horizon-dropzone__browse {
    color: var(--horizon-approved-fg);
    text-decoration: underline;
}

/* Request Leave (mobile): Back / Continue share the row equally; minmax(0, 1fr) lets them shrink at
   320px instead of the buttons' min-content width pushing the row wider than the screen. */
.horizon-request-steps__actions {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 12px;
}

.horizon-request-steps__actions .mud-button-root {
    min-height: 48px;
}

.horizon-request-impact {
    background-color: var(--horizon-approved-bg);
}

.horizon-request-impact__days {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--horizon-approved-fg);
}

/* MudStepper pads its content 0 24px, which (on top of the page gutter) inset the step cards ~40px from
   each side - narrower than the page heading. The page's own 16px gutter is enough. */
.horizon-request-steps .mud-stepper-content {
    padding: 0;
}

/* Horizon fields: outlined with a 12px radius (MudBlazor's default outlined radius is 4px). Any container
   of Horizon fields opts in with .horizon-fields; the request form's own class is kept as an alias. */
.horizon-fields .mud-input-outlined-border,
.horizon-request-form .mud-input-outlined-border {
    border-radius: 12px;
}

/* Approvals (UI-1 Task 8): toolbar above the queue table, the table's own scroll container, and the
   desktop quick-review panel. */
.horizon-approvals__main {
    min-width: 0;
}

.horizon-approvals__toolbar {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 12px;
}

.horizon-approvals__search {
    flex: 0 1 320px;
    min-width: 0;
    margin-top: 0;
}

.horizon-approvals__count {
    margin-left: auto;
    white-space: nowrap;
}

/* The page must never scroll sideways: a table wider than its card scrolls inside this wrapper instead. */
.horizon-table-scroll {
    max-width: 100%;
    overflow-x: auto;
}

.horizon-quick-review__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.horizon-quick-review__meta {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 4px;
    margin-top: 4px;
}

.horizon-quick-review__row {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}

.horizon-quick-review__icon {
    color: var(--horizon-neutral-fg);
    flex-shrink: 0;
}

.horizon-quick-review__link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
}

/* People (UI-1 Task 10): the table's main column (min-width: 0 lets it shrink below its content's natural
   width instead of forcing the grid wider - same reason Approvals' own main column needs it), and the
   search + department toolbar above the table, mirroring Approvals' own toolbar (Task 8) - a flexible
   search box plus a fixed-width department select. */
.horizon-people__main {
    min-width: 0;
}

/* The edit panel's column stays in view while a long table scrolls - only once the grid puts it beside the
   table (People's lg split, 1280px; see People.StackedPanelMediaQuery). top clears the fixed app bar with the
   same variable .horizon-main pads by: plus the item's own 16px top gutter (MudGrid Spacing="4" pads items top
   and left only) the card stops 24px below the bar, where the page content starts. max-height ends the column
   8px above the viewport's bottom edge, and a form taller than that scrolls inside the column, so BasicEdit's
   Save/Close row at its top stays reachable.
   align-self stops the item stretching to the table's height, which would leave it no room to stick. */
@media (min-width: 1280px) {
    .horizon-people__side {
        position: sticky;
        top: calc(var(--mud-appbar-height) + 8px);
        max-height: calc(100vh - var(--mud-appbar-height) - 16px);
        overflow-y: auto;
        align-self: flex-start;
    }
}

.horizon-people__toolbar {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 12px;
    flex-wrap: wrap;
}

.horizon-people__search {
    flex: 0 1 320px;
    min-width: 0;
    margin-top: 0;
}

.horizon-people__department {
    flex: 0 0 220px;
    min-width: 0;
    margin-top: 0;
}

/* Team calendar (UI-4): the toolbar (month arrows, label, department picker, scope toggle) and the mobile
   agenda's day-grouped rows. See the banner below for the desktop month grid. */
.horizon-calendar__toolbar {
    display: flex;
    align-items: center;
    gap: 16px;
    margin-bottom: 16px;
    flex-wrap: wrap;
}

.horizon-calendar__toolbar .mud-select {
    flex: 0 0 200px;
    min-width: 0;
    margin-top: 0;
}

.horizon-calendar-agenda__day {
    margin-bottom: 20px;
}

.horizon-calendar-agenda__heading {
    margin-bottom: 8px;
}

.horizon-calendar-agenda__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0 8px 8px;
    border-bottom: 1px solid #DDD8CF;
    border-left: 4px solid var(--horizon-approved-fg);
}

.horizon-calendar-agenda__row--holiday {
    border-radius: 4px;
    padding: 6px 10px;
    border-bottom: none;
    border-left: none;
}

/* The agenda is the phone-width view (unlike the grid/upcoming panel, which are desktop-only), so a long
   name plus a long date range pushing this row wider than the viewport is the one instance of this failure
   mode that actually happens at the width it would matter - see AppCssLayoutTests. */
.horizon-calendar-agenda__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.horizon-calendar-agenda__range {
    flex-shrink: 0;
}

/* Team calendar (UI-4): the desktop month grid. Each week is its own .horizon-calendar__grid - seven equal,
   shrinkable columns - with the day numbers, the holiday band and each bar's lane positioned onto it by an
   explicit inline grid-column/grid-row (computed in CalendarMonthGrid's code block). min-width: 0 on every
   grid child is required: a grid item's automatic minimum width is otherwise its content's natural size, and
   a long name would force the whole week wider than its column and overflow the page (see AppCssLayoutTests
   for the same failure mode elsewhere in this app). */
.horizon-calendar__weekdays {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    margin-bottom: 4px;
}

.horizon-calendar__weekday {
    min-width: 0;
    text-align: center;
    padding: 4px 0;
    font-weight: 600;
    color: var(--horizon-neutral-fg);
}

.horizon-calendar__grid {
    display: grid;
    grid-template-columns: repeat(7, minmax(0, 1fr));
    /* Row tracks are set inline by CalendarMonthGrid (WeekRowTracks), sized per week to its lane count - see there. */
    border-top: 1px solid #DDD8CF;
    border-left: 1px solid #DDD8CF;
}

.horizon-calendar__day {
    min-width: 0;
    min-height: 96px;
    padding: 4px 6px;
    border-right: 1px solid #DDD8CF;
    border-bottom: 1px solid #DDD8CF;
}

.horizon-calendar__day--out {
    color: var(--horizon-neutral-fg);
    background-color: #FAF9F5;
    opacity: 0.7;
}

.horizon-calendar__day--weekend {
    background-color: #F7F5EF;
}

/* Today gets the orange ring, not a filled tone - the leave bars already use the approved (teal) pair, and
   reusing it here for "today" would make that colour mean two different things on the same grid. The ring is
   an unfilled border, so the day number keeps the page's own text colour underneath it and introduces no new
   text-on-background contrast pair to check (see StatusTonePaletteTests for the pairs that do need one). */
.horizon-calendar__day--today .horizon-calendar__day-number {
    display: inline-block;
    min-width: 20px;
    padding: 0 4px;
    border-radius: 999px;
    border: 2px solid var(--horizon-pending-icon);
    text-align: center;
}

.horizon-calendar__holiday {
    min-width: 0;
    margin: 2px 0;
    padding: 2px 6px;
    border-radius: 4px;
    font-size: 0.75rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.horizon-calendar__entry {
    min-width: 0;
    margin: 1px 2px;
    padding: 2px 6px 2px 8px;
    border-radius: 4px;
    background-color: var(--horizon-approved-bg);
    color: var(--horizon-approved-fg);
    border-left: 4px solid var(--horizon-approved-fg);
    font-size: 0.75rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* A bar that continues past this week's edge (or began before it) renders with a flat edge on that side,
   rather than the rounded corner every other bar gets, so it visually keeps going instead of looking like it
   stops mid-week. */
.horizon-calendar__entry--continues-start {
    margin-left: 0;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    /* A carried-over bar isn't where the person's leave actually starts, so it must not show the accent
       stripe either - that would read as "leave starts here". border-left-width: 0 (rather than removing
       the declaration) keeps the box model stable; padding-left restores the 6px the bar had before the
       stripe was added (2px 6px in the base rule), so the text sits the same distance from the edge either
       way. */
    border-left-width: 0;
    padding-left: 6px;
}

.horizon-calendar__entry--continues-end {
    margin-right: 0;
    border-top-right-radius: 0;
    border-bottom-right-radius: 0;
}

/* Team calendar (UI-4 Task 6): the desktop-only "Upcoming leave" panel beside the month grid. Rows share the
   agenda's own flex/border-bottom row treatment. min-width: 0 on the name is required for the same reason as
   the grid's own cells (see the banner above) - a long name is otherwise flex's natural content width, which
   would force the whole md="4" panel column wider and overflow the page rather than truncating. */
.horizon-calendar-upcoming__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 4px;
}

.horizon-calendar-upcoming__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid #DDD8CF;
}

.horizon-calendar-upcoming__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.horizon-calendar-today__row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
    padding: 8px 0;
    border-bottom: 1px solid #DDD8CF;
}

.horizon-calendar-today__name {
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.horizon-calendar-today__back {
    flex-shrink: 0;
    color: var(--horizon-neutral-fg);
    font-size: 0.85rem;
}

.horizon-calendar-upcoming__range {
    flex-shrink: 0;
    color: var(--horizon-neutral-fg);
    font-size: 0.85rem;
}

/* People's "Edit employee" panel (fix round 2, live-check finding): BasicEdit's own top action row (Save
   full-width-minus-one-column, Close in a fixed 1/12 slice - see KBlazor.Components.BasicEdit`1's
   BuildRenderTree) is hard-coded and has no parameter to change; at the side panel's ~300-350px width that
   1/12 slice is far narrower than "Close" needs, so the button pushed past its column and the whole page
   overflowed horizontally. BasicEdit exposes nothing to fix this from the host, so this overrides those two
   grid items to their natural (shrink-to-fit) width instead of a fixed fraction, and lets the row wrap if
   they still don't both fit - the same MudButton, just no longer squeezed into an 8% column. */
.horizon-basic-edit > .mud-grid:first-child {
    flex-wrap: wrap;
}

.horizon-basic-edit > .mud-grid:first-child > .mud-grid-item {
    flex: 0 0 auto;
    width: auto;
    max-width: 100%;
}

/* Settings editors (Leave types, Companies, Holidays, ...): BasicEdit always heads its form "{kind} : {row}" - the row
   class's [Display] name, or the bare class name ("LeaveTypeRow : Casual Leave") - and has no parameter to change or drop
   it. The page shows its own EditorTitle ("Leave type: Casual Leave", "New leave type") on a panel marked .row-editor, so
   BasicEdit's heading, the h6 straight after its Save/Close grid, is hidden there. Hidden, not removed: the help-video
   scripts find BasicEdit's Save button by its grid's position among the panel's children. */
.row-editor > .mud-grid + h6.mud-typography-h6 {
    display: none;
}

/* FlexTable sizes each column to its header text, pins every cell's div at that width with an ellipsis, and gives the
   rest of the row to an empty filler column - so on the Outbox the event names and errors were cut off beside half a
   table of empty space. Inside .flex-table-fit a cell grows to its content (up to max-width, then the ellipsis), so the
   table lays its columns out by what is in them. The column's own width still holds as a minimum: dragging a column
   wider still works. */
.flex-table-fit .flex-table td > div {
    width: auto !important;
    max-width: 28rem;
}

/* ...and the trailing filler column (an &nbsp; header, an empty command cell on the Outbox) loses its padding, which on
   its own pushed a table that just fits about 9px past its container and onto a needless scrollbar. */
.flex-table-fit .flex-table tr > th:last-child,
.flex-table-fit .flex-table tr > td:last-child {
    padding: 0 !important;
}

/* Request detail (UI-1 Task 9): back link, the two cards, attachment file cards, and the phone's sticky
   action footer. min-width: 0 on the columns lets long names and file names wrap or ellipsise instead of
   widening the page at 320px. */
.horizon-detail__back {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-bottom: 16px;
}

.horizon-detail__col {
    min-width: 0;
}

.horizon-detail__name,
.horizon-detail__job {
    overflow-wrap: anywhere;
}

.horizon-detail__job {
    font-weight: 400;
}

.horizon-detail__summary {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-start;
    gap: 16px 24px;
    margin: 16px 0 8px;
}

.horizon-detail__summary > .horizon-request-summary {
    min-width: 0;
}

.horizon-detail__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.horizon-detail__section-title {
    font-weight: 600;
    margin-bottom: 8px;
}

/* Balance impact and attachments side by side when there is room, stacked otherwise. */
.horizon-detail__facts {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 240px), 1fr));
    gap: 16px 32px;
}

.horizon-file-card {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 10px 12px;
    border: 1px solid var(--mud-palette-lines-default);
    border-radius: 12px;
    margin-bottom: 8px;
    min-width: 0;
}

.horizon-file-card__icon {
    color: var(--horizon-neutral-fg);
    flex-shrink: 0;
}

.horizon-file-card__text {
    display: flex;
    flex-direction: column;
    flex: 1 1 auto;
    min-width: 0;
}

.horizon-file-card__name {
    font-size: .875rem;
    font-weight: 500;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.horizon-file-card__meta {
    font-size: .75rem;
    color: var(--mud-palette-text-secondary);
}

.horizon-detail__decision {
    padding: 12px;
    border-radius: 12px;
    background-color: var(--horizon-neutral-bg);
    overflow-wrap: anywhere;
}

.horizon-detail__actions {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Phone: the buttons sit in a fixed-height bar pinned directly above the bottom nav (.bottom-nav is
   64px + the safe-area inset tall), full width like the nav itself. Its height is pinned to
   --horizon-detail-footer-height and nothing else goes in it (the error area stays in the chain card), so
   .horizon-detail--with-footer can reserve exactly that much room at the foot of the page - on top of
   .horizon-main--mobile's own bottom-nav clearance - and the last card always scrolls fully clear of the
   bar. The bottom padding also clears the Request button's circle, which rises ~14px above the nav. */
.horizon-detail--with-footer {
    padding-bottom: calc(var(--horizon-detail-footer-height) + 16px);
}

.horizon-detail__footer-actions {
    position: fixed;
    left: 0;
    right: 0;
    bottom: calc(64px + env(safe-area-inset-bottom));
    height: var(--horizon-detail-footer-height);
    box-sizing: border-box;
    z-index: 1099;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 16px 18px;
    border-top: 1px solid var(--mud-palette-lines-default);
    background-color: var(--mud-palette-surface);
}

.horizon-detail__footer-actions .mud-button-root {
    flex: 1 1 0;
    min-width: 0;
    height: 44px;
    /* One order for every button in the bar, so the bar simply paints them in the order the markup emits
       them (Reject, Request Changes, Approve, then Withdraw and Cancel last). Nothing here may give a
       decision button an order of its own again: that would break the DOM/visual order match below. */
    order: 4;
}

/* Approve is the dominant action: it takes the larger share of the row. */
.horizon-detail__footer-actions .horizon-detail__approve {
    flex-grow: 1.6;
}

/* The decision buttons are NOT reordered here: RequestDetail.razor emits them in the pinned bar's own visual
   order (Reject, Request Changes, Approve - mobile-approval-review.png), so tab and screen-reader order match
   what is painted (WCAG 2.4.3). The `order: 4` above is all that is left, keeping Withdraw and Cancel last. */

/* Below 360px the three-button bar is tight for "Request Changes": it swaps to the shorter "Changes" label.
   Only the pinned bar renders both spans (see RequestDetail.razor - the desktop stack renders a single
   label), so a button never loses its text label outright. The base rule that hides the short label is
   deliberately UNSCOPED: were it scoped to the bar, a short span rendered anywhere else would show and the
   button would read "Request ChangesChanges". Only the swap itself is scoped to the bar. */
.horizon-detail__label-short {
    display: none;
}

@media (max-width: 359px) {
    .horizon-detail__footer-actions .horizon-detail__label-full {
        display: none;
    }

    .horizon-detail__footer-actions .horizon-detail__label-short {
        display: inline;
    }
}

/* Request Changes is an outlined Warning button, which paints border, icon AND label with the raw Amber
   token - and Amber on the paper surface is ~2.6:1, well under WCAG AA for normal text. The label is
   repainted with the primary text colour (~15:1); the amber stays on the border and the pencil icon, which
   are decorative and carry no text-contrast requirement, matching the mockups. See StatusTonePaletteTests. */
.horizon-request-changes.mud-button-root {
    color: var(--mud-palette-text-primary);
    border-color: var(--horizon-pending-icon);
}

.horizon-request-changes.mud-button-root .mud-icon-root {
    color: var(--horizon-pending-icon);
}

/* UI-3: the banner an employee sees on a request an approver sent back for changes. It reuses the pending
   (amber) status tone - the same pair the ChangesRequested chip is painted with, so the page reads as one
   colour - with the full-saturation amber reserved for the border and the icon, which carry no text-contrast
   requirement. The action sits on the same row as the text on a tablet upwards and drops full width below. */
.horizon-returned {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    padding: 16px;
    margin-bottom: 16px;
    border-radius: 16px;
    border: 1px solid var(--horizon-pending-icon);
    background-color: var(--horizon-pending-bg);
    color: var(--horizon-pending-fg);
}

.horizon-returned__icon {
    flex: 0 0 auto;
    color: var(--horizon-pending-icon);
}

/* min-width: 0 (and wrapping anywhere) keeps a long comment inside the banner instead of pushing it wider
   than a 320px phone. */
.horizon-returned__body {
    flex: 1 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

.horizon-returned__title {
    font-weight: 600;
}

.horizon-returned__deadline {
    margin-top: 4px;
    font-weight: 600;
}

.horizon-returned__action {
    flex: 0 0 auto;
}

@media (max-width: 599px) {
    .horizon-returned {
        flex-wrap: wrap;
    }

    .horizon-returned__action {
        width: 100%;
    }
}

/* Scrolled-to elements (the comment field, the error area) stop clear of the fixed top bar and the pinned
   bar + bottom nav instead of landing underneath them. */
.horizon-detail__scroll-target {
    scroll-margin-top: calc(56px + 16px);
    scroll-margin-bottom: calc(var(--horizon-detail-footer-height) + 64px + 16px + env(safe-area-inset-bottom));
}

/* CommentThread (UI-2 Task 3): the request detail page's comment thread - RequestCommentDto entries plus any
   chain step's decision note, oldest first. min-width: 0 throughout keeps a long name/comment wrapping
   inside its own column instead of pushing the card wider than 320px. */
.horizon-comment-thread {
    min-width: 0;
}

.horizon-comment-list {
    display: flex;
    flex-direction: column;
    gap: 16px;
    margin: 12px 0 16px;
}

.horizon-comment-entry {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    min-width: 0;
}

.horizon-comment-entry__avatar.mud-avatar {
    background-color: var(--horizon-neutral-bg);
    color: var(--horizon-neutral-fg);
    font-weight: 600;
    font-size: .75rem;
    flex-shrink: 0;
}

.horizon-comment-entry__body {
    flex: 1 1 auto;
    min-width: 0;
}

.horizon-comment-entry__meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}

.horizon-comment-entry__author {
    font-weight: 600;
    font-size: .875rem;
}

.horizon-comment-entry__time {
    font-size: .75rem;
}

.horizon-comment-entry__text {
    margin-top: 4px;
    font-size: .875rem;
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.horizon-comment-composer {
    display: flex;
    align-items: flex-start;
    gap: 8px;
    margin-top: 4px;
}

.horizon-comment-composer .mud-input-control {
    flex: 1 1 auto;
    min-width: 0;
}

.horizon-comment-composer__send {
    margin-top: 4px;
    flex-shrink: 0;
}

.horizon-comment-composer__error {
    margin-top: 4px;
    color: var(--horizon-error-fg);
}

/* ApprovalChain (full view): a vertical stepper. Each step is a marker column and a body; a 2px rail runs
   from each marker down to the next. Done markers are filled in their outcome's tone, the current step is
   an orange ring, and unopened levels are hollow grey circles. */
.horizon-chain {
    list-style: none;
    margin: 0;
    padding: 0;
}

/* The "Round {n} — resubmitted {date}" caption (Task 4): leads the steps from round 2 on. */
.horizon-chain__round {
    display: block;
    margin-bottom: 12px;
}

.horizon-chain__step {
    position: relative;
    display: grid;
    grid-template-columns: 24px minmax(0, 1fr);
    column-gap: 12px;
    padding-bottom: 20px;
}

.horizon-chain__step:last-child {
    padding-bottom: 0;
}

.horizon-chain__step:not(:last-child)::before {
    content: "";
    position: absolute;
    left: 11px;
    top: 28px;
    bottom: 4px;
    width: 2px;
    background-color: var(--mud-palette-lines-default);
}

.horizon-chain__step--done:not(:last-child)::before {
    background-color: var(--horizon-approved-icon);
}

.horizon-chain__marker {
    width: 24px;
    height: 24px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--mud-palette-primary-text);
    box-sizing: border-box;
}

.horizon-chain__marker .mud-icon-root {
    font-size: 1rem;
}

.horizon-chain__marker--approved { background-color: var(--horizon-approved-icon); }
.horizon-chain__marker--rejected { background-color: var(--horizon-error-icon); }
.horizon-chain__marker--escalated { background-color: var(--horizon-pending-icon); }
.horizon-chain__marker--changes-requested { background-color: var(--horizon-pending-icon); }
.horizon-chain__marker--skipped { background-color: var(--horizon-muted); }
/* An edit that started the round: neutral, not the amber of a change request - nobody asked for it. */
.horizon-chain__marker--edited { background-color: var(--horizon-muted); }

.horizon-chain__marker--current {
    border: 3px solid var(--mud-palette-primary);
    background-color: var(--mud-palette-surface);
    box-shadow: inset 0 0 0 3px var(--mud-palette-surface), inset 0 0 0 12px var(--mud-palette-primary);
}

.horizon-chain__marker--future {
    border: 2px solid var(--horizon-muted);
    background-color: transparent;
}

.horizon-chain__body {
    min-width: 0;
    overflow-wrap: anywhere;
}

.horizon-chain__heading {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 4px 8px;
    min-height: 24px;
}

.horizon-chain__stage {
    font-weight: 600;
    color: var(--mud-palette-text-primary);
}

.horizon-chain__chip {
    padding: 2px 8px;
    font-size: .75rem;
}

.horizon-chain__status { font-weight: 500; }
.horizon-chain__status--approved { color: var(--horizon-approved-fg); }
.horizon-chain__status--pending { color: var(--horizon-pending-fg); }
.horizon-chain__status--error { color: var(--horizon-error-fg); }
.horizon-chain__status--neutral { color: var(--horizon-neutral-fg); }

.horizon-chain__comment {
    font-style: italic;
}

/* CalendarColourPicker (personal calendar colours): a 200px wheel beside its controls, stacking under 600px. */
.colour-picker {
    display: grid;
    grid-template-columns: 200px 1fr;
    gap: 24px;
    align-items: start;
}

@media (max-width: 600px) {
    .colour-picker {
        grid-template-columns: 1fr;
        justify-items: center;
    }
}

.colour-picker__wheel {
    flex-shrink: 0;
}

.colour-picker__segment {
    cursor: pointer;
}

.colour-picker__segment:focus-visible {
    outline: 2px solid #24292D;
    outline-offset: 1px;
}

.colour-picker__controls {
    display: flex;
    flex-direction: column;
    gap: 4px;
    min-width: 0;
}

.colour-picker__label {
    font-size: 0.7rem;
    font-weight: 600;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--horizon-muted);
    margin-top: 12px;
}

.colour-picker__label:first-child {
    margin-top: 0;
}

.colour-picker__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}

.colour-picker__chip {
    border: 1px solid #DDD8CF;
    background: #FFFFFF;
    border-radius: 999px;
    padding: 4px 12px;
    font-size: 0.8125rem;
    cursor: pointer;
}

.colour-picker__chip--on {
    background: #24292D;
    color: #FFFFFF;
    border-color: #24292D;
}

.colour-picker__hint {
    font-size: 0.75rem;
    color: var(--horizon-muted);
    margin-top: 2px;
}

.colour-picker__swatches {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}

.colour-picker__swatch {
    width: 34px;
    height: 34px;
    border-radius: 8px;
    border: 1px solid rgba(0, 0, 0, .1);
    cursor: pointer;
    padding: 0;
}

.colour-picker__swatch--on {
    outline: 2px solid #24292D;
    outline-offset: 2px;
}

.colour-picker__preview {
    background-color: #F7F4EE;
    border: 1px solid #DDD8CF;
    border-radius: 4px;
    padding: 6px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.colour-picker__preview-short {
    width: 45%;
}

/* ---- Welcome (signed-out landing page, WelcomeLayout + Pages/Welcome.razor) ---- */

.welcome-shell {
    min-height: 100vh;
    min-height: 100dvh;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px 16px calc(24px + env(safe-area-inset-bottom));
    background-color: #F6F2EA;
    box-sizing: border-box;
}

.welcome {
    width: 100%;
    max-width: 420px;
    display: flex;
    flex-direction: column;
    gap: 20px;
    padding: 32px 24px;
    background-color: #FFFDF9;
    border: 1px solid #DDD8CF;
    border-radius: 12px;
    box-sizing: border-box;
}

.brand-wordmark--welcome {
    color: #222629;
    font-size: 24px;
    white-space: normal;
}

.welcome__lede,
.welcome__install-text {
    color: #6B706F;
}

.welcome__install {
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding-top: 20px;
    border-top: 1px solid #DDD8CF;
}

.welcome__install-title {
    font-weight: 600;
}

.welcome__installed {
    color: #22746B;
}


/* Letterhead preview: an embedded PDF on wide screens; phones often can't show one inline, so they get the link only. */
.letterhead-preview__frame { width: 100%; height: 80vh; border: 1px solid var(--mud-palette-lines-default); border-radius: 4px; }
@media (max-width: 767.98px) { .letterhead-preview__frame { display: none; } }

/* Screen-reader-only text (the help wizard's "Step n of N" live region). */
.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

/* Help wizard: a stable panel height so Back/Next don't jump between short and long panels; images capped so a
   tall infographic never pushes the text out of view. */
.help-wizard:focus {
    outline: none;
}

.help-wizard__panel {
    min-height: 260px;
    padding-top: 8px;
}

.help-wizard__step-label {
    display: none;
}

.help-wizard__image {
    margin: 12px 0 0;
}

.help-wizard__image img {
    display: block;
    max-width: 100%;
    max-height: 220px;
    object-fit: contain;
}

.help-wizard__image figcaption {
    margin-top: 4px;
    font-size: 12px;
    color: var(--mud-palette-text-secondary);
}

.help-wizard__bullets {
    padding-left: 20px;
}

/* 1.5 line spacing in bullet text, and half a line between bullets so each reads as its own point. The
   MudText inside carries its own typography line-height, so it is set there too. */
.help-wizard__bullets li,
.help-wizard__bullets li .mud-typography {
    line-height: 1.5;
}

.help-wizard__bullets li + li {
    margin-top: .5em;
}

/* The page's own menu icon beside the help title, so help visibly belongs to the page it explains. */
.help-wizard__title {
    display: flex;
    align-items: center;
    gap: 10px;
}

/* Phones: step titles don't fit across, so the stepper keeps only its numbered circles and the current step's
   title shows above the heading instead; the dialog fills the screen. */
@media (max-width: 599px) {
    .help-wizard__nav .mud-step-label-content {
        display: none;
    }

    .help-wizard__step-label {
        display: block;
    }

    .help-wizard-dialog {
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        max-height: 100vh;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }
}

/* Help video player (HelpVideoDialog): a 16:9 frame as wide as the large dialog allows, but never so tall that the
   transcript below drops out of view at a desk; the transcript scrolls in its own box. Phones get the whole screen,
   like the help wizard. */
.help-video__part {
    margin-bottom: 8px;
}

.help-video__frame {
    display: flex;
    justify-content: center;
    background: #24292D;
    border-radius: 12px;
    overflow: hidden;
}

.help-video__frame video {
    display: block;
    width: 100%;
    max-height: 62vh;
    aspect-ratio: 16 / 9;
    background: #24292D;
}

.help-video__error {
    width: 100%;
    aspect-ratio: 16 / 9;
    max-height: 62vh;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 6px;
    padding: 16px;
    text-align: center;
    color: #FFFFFF;
}

.help-video__transcript {
    margin-top: 16px;
}

.help-video__transcript-heading {
    margin-bottom: 4px;
}

.help-video__transcript-text {
    max-height: 22vh;
    overflow-y: auto;
    white-space: pre-line;
    line-height: 1.5;
    padding: 12px 16px;
    border: 1px solid #DDD8CF;
    border-radius: 12px;
    color: var(--mud-palette-text-primary);
}

@media (max-width: 599px) {
    .help-video-dialog {
        width: 100vw;
        max-width: 100vw;
        height: 100vh;
        max-height: 100vh;
        height: 100dvh;
        max-height: 100dvh;
        margin: 0;
        border-radius: 0;
    }

    .help-video__frame {
        border-radius: 8px;
    }

    .help-video__transcript-text {
        max-height: none;
    }
}

/* Help videos page (HelpVideos.razor): the whole video first, then one row per page's section. */
.help-videos {
    max-width: 720px;
}

.help-videos__whole {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    flex-wrap: wrap;
}

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

.help-videos__item {
    display: flex;
    align-items: center;
    gap: 12px;
    width: 100%;
    min-height: 48px;
    padding: 8px 12px;
    border: 0;
    border-radius: 12px;
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
}

.help-videos__item:hover,
.help-videos__item:focus-visible {
    background: var(--mud-palette-action-default-hover);
}

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

.help-videos__icon {
    color: var(--mud-palette-text-secondary);
}

.help-videos__title {
    flex: 1;
    font-weight: 500;
}

.help-videos__duration {
    color: var(--mud-palette-text-secondary);
    font-variant-numeric: tabular-nums;
}

.help-videos__play {
    color: var(--mud-palette-primary);
}

/* Leave flow roses (LeaveRoseChart, LeaveMonthsChart): projected petals are faded and dashed; a selection dims every
   other petal; the viewBox comes from the layout's label extents, and overflow stays visible as a backstop so no label
   is ever clipped. */
.rose-svg { display: block; max-width: 520px; margin: 0 auto; overflow: visible; }
.rose-petal, .month-petal, .rose-label { cursor: pointer; outline: none; }
.rose-petal:focus-visible path, .month-petal:focus-visible .month-hit { stroke: var(--mud-palette-primary); stroke-width: 2; }
.rose-petal__shape { fill-opacity: .85; }
.flow-dim { opacity: .3; }
.flow-projected { fill-opacity: .4; stroke-dasharray: 3 2; stroke: currentColor; }
.rose-leader { fill: none; stroke: var(--mud-palette-lines-default); stroke-width: 1; }
.rose-caption { font-weight: 600; fill: var(--mud-palette-text-secondary); }
.flow-label { font-size: 12px; fill: var(--mud-palette-text-primary); }
.month-ring { fill: none; stroke: var(--mud-palette-lines-default); stroke-dasharray: 2 3; }
.month-hit { fill: var(--mud-palette-text-primary); fill-opacity: .03; }
.month-petal:hover .month-hit, .month-petal--selected .month-hit { fill-opacity: .08; }
.months-legend { display: flex; justify-content: center; gap: 16px; margin-top: 8px; font-size: .875rem; }
.months-legend__item { display: inline-flex; align-items: center; gap: 6px; }
.months-table { width: 100%; border-collapse: collapse; margin-top: 8px; font-size: .875rem; font-variant-numeric: tabular-nums; }
.months-table th, .months-table td { padding: 2px 6px; text-align: right; border-bottom: 1px solid var(--mud-palette-lines-default); }
.months-table th:first-child, .months-table td:first-child { text-align: left; }
.months-table tfoot th, .months-table tfoot td { font-weight: 600; border-bottom: 0; }
.months-table__month { background: none; border: 0; padding: 0; font: inherit; color: var(--mud-palette-primary); cursor: pointer; text-align: left; }
.months-table__row--selected { background: rgba(247, 148, 29, .12); }
.months-detail__heading { margin-top: 6px; font-weight: 600; }
.rose-taken-types__title { display: block; color: var(--mud-palette-text-secondary); }
/* The two roses: side by side from 1100px, where each panel is still wide enough for its labels; stacked below it or
   when the card is told to stack (a narrow panel such as People's). minmax(0, 1fr) lets each column shrink below its
   content's width. */
.flow-card__charts { display: grid; grid-template-columns: minmax(0, 1fr); gap: 16px; }
@media (min-width: 1100px) {
    .flow-card__charts:not(.flow-card__charts--stacked) { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.flow-card__panel { border: 1px solid var(--mud-palette-lines-default); border-radius: 8px; padding: 12px; min-width: 0; }
.flow-card__panel-title { margin-bottom: 4px; }
.flow-list { margin-top: 8px; }
.flow-list__row { display: flex; align-items: center; gap: 8px; width: 100%; padding: 6px 4px; background: none; border: 0;
    border-radius: 6px; font: inherit; color: inherit; text-align: left; cursor: pointer; line-height: 1.5; }
.flow-list__row--selected { background: rgba(247, 148, 29, .12); }
.flow-list__swatch { width: 10px; height: 10px; border-radius: 2px; flex: none; }
.flow-list__swatch.flow-projected { opacity: .45; }
.flow-list__label { flex: 1; }
.flow-list__days { font-variant-numeric: tabular-nums; }
.flow-list__divider { border-top: 1px solid var(--mud-palette-lines-default); margin: 4px 0; }
.flow-detail { border-top: 1px solid var(--mud-palette-lines-default); margin-top: 8px; padding-top: 8px; }
.flow-detail__row { display: flex; justify-content: space-between; gap: 12px; padding: 4px 0; line-height: 1.5; }
.flow-detail__person { background: none; border: 0; padding: 0; font: inherit; color: var(--mud-palette-primary); cursor: pointer; text-align: left; }
.flow-detail__days { font-variant-numeric: tabular-nums; }
.flow-card__header { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; margin-bottom: 8px; }
.flow-card__pickers { display: flex; gap: 8px; }
.flow-card__picker { min-width: 120px; }

/* Recommended-by-the-app badge (spec 2026-10-14 §5). */
.horizon-recommended { display: inline-flex; flex-wrap: wrap; align-items: center; gap: 6px; }
.horizon-recommended__why { font-size: 12px; color: var(--mud-palette-text-secondary); }

/* My Leave long-weekend suggestions (spec 2026-10-14 §7). */
.leave-suggestion { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 8px; padding: 8px 0;
    border-bottom: 1px solid var(--mud-palette-lines-default); line-height: 1.5; }
.leave-suggestion__text { flex: 1 1 240px; }

/* A long-weekend suggestion drawn as its break: "1 → 4" beside a strip of the days off, framed by a faded working day
   each side. Leave days wear the person's calendar colours (inline style) or this default teal. */
.leave-strip { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; grid-template-areas: "ratio days action" "caption caption caption";
    align-items: center; gap: 6px 16px; padding: 12px 0; border-bottom: 1px solid var(--mud-palette-lines-default); }
.leave-strip__ratio { grid-area: ratio; display: flex; flex-direction: column; align-items: center; min-width: 84px; }
.leave-strip__numbers { font-size: 1.6rem; font-weight: 600; line-height: 1.2; white-space: nowrap; }
.leave-strip__label { font-size: 0.75rem; color: var(--horizon-muted); white-space: nowrap; }
.leave-strip__days { grid-area: days; display: flex; gap: 4px; min-width: 0; }
.leave-strip__day { flex: 1 1 0; min-width: 34px; height: 58px; display: flex; flex-direction: column; align-items: center; justify-content: center;
    border-radius: 6px; border: 1px solid #DDD8CF; background-color: #FFFFFF; color: #6B6F72; font-size: 0.75rem; line-height: 1.2; }
.leave-strip__day .horizon-holiday__icon.mud-icon-root { margin-right: 0; }
.leave-strip__num { font-size: 0.95rem; font-weight: 600; color: inherit; }
.leave-strip__day--context { opacity: 0.5; }
.leave-strip__day--weekend { background-color: #F7F5EF; }
.leave-strip__day--leave { background-color: var(--horizon-approved-bg); color: var(--horizon-approved-fg); border-left: 4px solid var(--horizon-approved-fg); }
.leave-strip__action { grid-area: action; }
.leave-strip__action .mud-button-root { width: 100%; }
.leave-strip__caption { grid-area: caption; font-size: 0.875rem; color: var(--horizon-neutral-fg); }

/* A public holiday wherever it is drawn (Team Calendar grid and agenda, the suggestion strip): gold with a picture,
   never charcoal - black is kept for blackout days, when leave can't be taken. The picture comes from HolidayIcons.
   It sits after the strip's day rules so its colours win over their plain white cell. */
.horizon-holiday {
    background-color: var(--horizon-pending-bg);
    color: var(--horizon-pending-fg);
    border: 1px solid var(--horizon-pending-icon);
}
.horizon-holiday__icon.mud-icon-root { width: 1.1em; height: 1.1em; color: var(--horizon-pending-icon); vertical-align: -0.2em; margin-right: 4px; }
/* On the Team Calendar the picture sits inline in the holiday's own small text, so it takes that text's size. */
.horizon-calendar__holiday .horizon-holiday__icon.mud-icon-root,
.horizon-calendar-agenda__row--holiday .horizon-holiday__icon.mud-icon-root { font-size: inherit; }

/* A blackout period on the Team Calendar: days leave can't be taken. Black is used for nothing else on the calendar
   (holidays are gold, leave wears people's own colours). */
.horizon-blackout { background-color: #3A3F44; color: #FFFFFF; }

/* The Request Leave date picker's marks (RequestFormState.PickerDayClass) and their key. The chosen start and end keep
   the picker's own orange; days between them keep their mark, so a blackout inside the chosen range still shows. */
.mud-picker-calendar .mud-day.horizon-picker-day--holiday:not(.mud-selected):not(.mud-range-start-selected):not(.mud-range-end-selected) {
    background-color: var(--horizon-pending-bg); color: var(--horizon-pending-fg); box-shadow: inset 0 0 0 1px var(--horizon-pending-icon); }
.mud-picker-calendar .mud-day.horizon-picker-day--blackout:not(.mud-selected):not(.mud-range-start-selected):not(.mud-range-end-selected) { background-color: #3A3F44; color: #FFFFFF; }
.horizon-picker-legend { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 4px; font-size: 0.75rem; color: var(--horizon-neutral-fg); }
.horizon-picker-legend__swatch { display: inline-block; width: 10px; height: 10px; border-radius: 50%; margin-right: 6px; vertical-align: -1px; border: 1px solid transparent; }
.horizon-picker-legend__swatch.horizon-holiday { border-color: var(--horizon-pending-icon); }
.horizon-calendar__blackout { min-width: 0; margin: 1px 2px; padding: 2px 6px; border-radius: 4px; font-size: 0.75rem; font-weight: 600;
    overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.horizon-calendar-agenda__row--blackout { border-radius: 4px; padding: 6px 10px; border-bottom: none; border-left: none; }

/* The Holidays editor's picture picker: one button per HolidayPictures entry, the chosen one gold. */
.holiday-picker__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(40px, 1fr)); gap: 6px; max-width: 440px; }
.holiday-picker__option { height: 38px; display: flex; align-items: center; justify-content: center; cursor: pointer;
    border: 1px solid #DDD8CF; border-radius: 6px; background-color: #FFFFFF; }
.holiday-picker__option .horizon-holiday__icon.mud-icon-root { margin-right: 0; color: var(--horizon-neutral-fg); }
.holiday-picker__option--on { border: 2px solid var(--horizon-pending-icon); background-color: var(--horizon-pending-bg); }
.holiday-picker__option--on .horizon-holiday__icon.mud-icon-root { color: var(--horizon-pending-icon); }

@media (max-width: 599.98px) {
    .leave-strip { grid-template-columns: minmax(0, 1fr); grid-template-areas: "ratio" "days" "caption" "action"; }
}

/* Staffing: the range and category toolbar, the short-days list and the units x days grid. Status colours come from the
   status-tone tokens: short is the error tone (red), at minimum the pending/warning tone (amber), above the approved tone
   (teal). Never the holiday gold border-and-picture treatment or the blackout charcoal. */
.staffing__toolbar { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.staffing__toolbar > .mud-input-control,
.staffing__toolbar .mud-picker { flex: 0 0 200px; min-width: 0; margin-top: 0; }

.staffing-list { list-style: none; margin: 8px 0 0; padding: 0; }
.staffing-list__line {
    display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; width: 100%; padding: 8px 4px;
    background: none; border: none; border-bottom: 1px solid var(--mud-palette-divider); color: inherit; font: inherit;
    text-align: left; cursor: pointer;
}
.staffing-list li:last-child .staffing-list__line { border-bottom: none; }
.staffing-list__line:hover, .staffing-list__line:focus-visible { background-color: var(--mud-palette-action-default-hover); }
.staffing-list__unit { font-weight: 600; }
.staffing-list__cause { color: var(--horizon-neutral-fg); font-size: 0.875rem; }

.staffing-grid-scroll { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.staffing-grid { border-collapse: separate; border-spacing: 2px; min-width: 100%; }
.staffing-grid th { font-weight: 600; font-size: 0.8125rem; white-space: nowrap; padding: 4px 8px; text-align: center; }
.staffing-grid th.staffing-grid__unit { text-align: left; position: sticky; left: 0; z-index: 1; background-color: var(--mud-palette-surface); }
.staffing-grid__category th { text-align: left; padding-top: 12px; color: var(--horizon-neutral-fg); text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.75rem; }
.staffing-cell { min-width: 72px; height: 36px; padding: 0; border-radius: 6px; text-align: center; }
.staffing-cell__button {
    display: inline-flex; align-items: center; justify-content: center; gap: 4px; width: 100%; height: 100%; min-height: 36px;
    background: none; border: none; color: inherit; font: inherit; font-variant-numeric: tabular-nums; cursor: pointer;
}
.staffing-short { background-color: var(--horizon-error-bg); color: var(--horizon-error-fg); font-weight: 600; }
.staffing-at-minimum { background-color: var(--horizon-pending-bg); color: var(--horizon-pending-fg); }
.staffing-above { background-color: var(--horizon-approved-bg); color: var(--horizon-approved-fg); }
.staffing-cell__at-risk {
    min-width: 18px; padding: 0 5px; border-radius: 999px; font-size: 0.6875rem; font-weight: 700; line-height: 18px;
    background-color: var(--horizon-error-icon); color: #FFFFFF;
}
.staffing-day__people { margin: 4px 0 0; padding-left: 20px; }

/* Phones: the list reads on its own, one part per line, and the grid scrolls sideways under it. */
@media (max-width: 767.98px) {
    .staffing-list__line { flex-direction: column; align-items: flex-start; }
    .staffing__toolbar > .mud-input-control,
    .staffing__toolbar .mud-picker { flex: 1 1 140px; }
}

/* Audit: the Story toolbar, the timeline (a heading per day, each line's time, sentence, integrity chip, Details), the Record integrity days list, and
   Verify this record's fingerprint. An entry changed outside the app carries the pending/warning tone's left rule. */
.audit__toolbar { display: flex; align-items: center; gap: 16px; margin-bottom: 16px; flex-wrap: wrap; }
.audit__toolbar > .mud-input-control,
.audit__toolbar .mud-picker { flex: 0 0 200px; min-width: 0; margin-top: 0; }
.audit__person { display: flex; align-items: center; gap: 8px 12px; flex-wrap: wrap; flex: 1 1 320px; min-width: 0; }
.audit__person > .mud-input-control { flex: 1 1 220px; min-width: 0; margin-top: 0; }

.audit-timeline { margin: 0; padding: 0; }
.audit-timeline__zone { display: block; padding: 0 4px 6px 12px; }
.audit-day + .audit-day { margin-top: 16px; }
.audit-day__head { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; padding: 6px 4px 6px 12px;
                   border-bottom: 1px solid var(--mud-palette-divider); }
.audit-day__title { font-weight: 600; }
.audit-day__chip { margin-left: auto; align-self: center; }
.audit-day__lines { list-style: none; margin: 0; padding: 0; }
.audit-entry { padding: 10px 4px 10px 12px; border-bottom: 1px solid var(--mud-palette-divider); border-left: 3px solid transparent; }
.audit-entry:last-child { border-bottom: none; }
.audit-entry--outside { border-left-color: var(--horizon-pending-icon); }
.audit-entry__head { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 4px 12px; margin-bottom: 2px; }
.audit-entry__toggle { margin-left: -8px; }
.audit-entry__details { margin: 4px 0 0; padding-left: 20px; font-size: 0.875rem; overflow-wrap: anywhere; }

.audit-integrity__notes { margin: 12px 0 0; padding-left: 20px; }
.audit-days { list-style: none; margin: 8px 0 0; padding: 0; }
.audit-days__line { display: flex; flex-wrap: wrap; align-items: center; gap: 4px 16px; padding: 8px 4px; border-bottom: 1px solid var(--mud-palette-divider); }
.audit-days__line:last-child { border-bottom: none; }
.audit-days__date { font-weight: 600; min-width: 96px; font-variant-numeric: tabular-nums; }
.audit-days__text { color: var(--horizon-neutral-fg); font-size: 0.875rem; }

/* A verify run that couldn't check the record is an outage, not tampering: the neutral tone, never red or blue. */
.mud-alert.horizon-alert--neutral { background-color: var(--horizon-neutral-bg); color: var(--horizon-neutral-fg); }
.mud-alert.horizon-alert--neutral .mud-alert-icon { color: var(--horizon-neutral-icon); }

.verify-record { max-width: 760px; }
.verify-record__fingerprint { display: block; margin-top: 4px; font-size: 0.9375rem; letter-spacing: 0.04em; overflow-wrap: anywhere; }
.verify-record__check { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.verify-record__check > .mud-input-control { flex: 1 1 320px; min-width: 0; margin-top: 0; }
