/* /Components/Layout/ReconnectModal.razor.rz.scp.css */
.components-reconnect-first-attempt-visible[b-ja1kj1eomm],
.components-reconnect-repeated-attempt-visible[b-ja1kj1eomm],
.components-reconnect-failed-visible[b-ja1kj1eomm],
.components-pause-visible[b-ja1kj1eomm],
.components-resume-failed-visible[b-ja1kj1eomm],
.components-rejoining-animation[b-ja1kj1eomm] {
    display: none;
}

#components-reconnect-modal.components-reconnect-show .components-reconnect-first-attempt-visible[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-show .components-rejoining-animation[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-paused .components-pause-visible[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-resume-failed .components-resume-failed-visible[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-retrying[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-retrying .components-reconnect-repeated-attempt-visible[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-retrying .components-rejoining-animation[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-failed[b-ja1kj1eomm],
#components-reconnect-modal.components-reconnect-failed .components-reconnect-failed-visible[b-ja1kj1eomm] {
    display: block;
}


#components-reconnect-modal[b-ja1kj1eomm] {
    background-color: white;
    width: 20rem;
    margin: 20vh auto;
    padding: 2rem;
    border: 0;
    border-radius: 0.5rem;
    box-shadow: 0 3px 6px 2px rgba(0, 0, 0, 0.3);
    opacity: 0;
    transition: display 0.5s allow-discrete, overlay 0.5s allow-discrete;
    animation: components-reconnect-modal-fadeOutOpacity-b-ja1kj1eomm 0.5s both;
    &[open]

{
    animation: components-reconnect-modal-slideUp-b-ja1kj1eomm 1.5s cubic-bezier(.05, .89, .25, 1.02) 0.3s, components-reconnect-modal-fadeInOpacity-b-ja1kj1eomm 0.5s ease-in-out 0.3s;
    animation-fill-mode: both;
}

}

#components-reconnect-modal[b-ja1kj1eomm]::backdrop {
    background-color: rgba(0, 0, 0, 0.4);
    animation: components-reconnect-modal-fadeInOpacity-b-ja1kj1eomm 0.5s ease-in-out;
    opacity: 1;
}

@keyframes components-reconnect-modal-slideUp-b-ja1kj1eomm {
    0% {
        transform: translateY(30px) scale(0.95);
    }

    100% {
        transform: translateY(0);
    }
}

@keyframes components-reconnect-modal-fadeInOpacity-b-ja1kj1eomm {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

@keyframes components-reconnect-modal-fadeOutOpacity-b-ja1kj1eomm {
    0% {
        opacity: 1;
    }

    100% {
        opacity: 0;
    }
}

.components-reconnect-container[b-ja1kj1eomm] {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 1rem;
}

#components-reconnect-modal p[b-ja1kj1eomm] {
    margin: 0;
    text-align: center;
}

#components-reconnect-modal button[b-ja1kj1eomm] {
    border: 0;
    background-color: #6b9ed2;
    color: white;
    padding: 4px 24px;
    border-radius: 4px;
}

    #components-reconnect-modal button:hover[b-ja1kj1eomm] {
        background-color: #3b6ea2;
    }

    #components-reconnect-modal button:active[b-ja1kj1eomm] {
        background-color: #6b9ed2;
    }

.components-rejoining-animation[b-ja1kj1eomm] {
    position: relative;
    width: 80px;
    height: 80px;
}

    .components-rejoining-animation div[b-ja1kj1eomm] {
        position: absolute;
        border: 3px solid #0087ff;
        opacity: 1;
        border-radius: 50%;
        animation: components-rejoining-animation-b-ja1kj1eomm 1.5s cubic-bezier(0, 0.2, 0.8, 1) infinite;
    }

        .components-rejoining-animation div:nth-child(2)[b-ja1kj1eomm] {
            animation-delay: -0.5s;
        }

@keyframes components-rejoining-animation-b-ja1kj1eomm {
    0% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    4.9% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 0;
    }

    5% {
        top: 40px;
        left: 40px;
        width: 0;
        height: 0;
        opacity: 1;
    }

    100% {
        top: 0px;
        left: 0px;
        width: 80px;
        height: 80px;
        opacity: 0;
    }
}
/* /Components/Pages/BookingsSourceChart.razor.rz.scp.css */
/* Wrapper for the ApexCharts bookings-by-source chart. ApexCharts builds its own SVG/DOM via JS
   after render; those nodes sit inside this Blazor-rendered .dash-apex div, so ::deep descendant
   rules still reach them (the scope id anchors on .dash-apex). Reserve the chart height so the
   card doesn't jump while the chart mounts. */
.dash-apex[b-h3kjeisjn9] {
    min-height: 320px;
}

/* Keep the legend on a single horizontal row. ApexCharts styles the bottom/top legend container with
   `flex-wrap: wrap`, so in the 2/3-width card the four keys (Direct / OTA / Agents / Total) wrap onto a
   second line. Forcing nowrap keeps them on one line; the container is already `overflow: auto`, so the
   rare too-narrow viewport scrolls rather than clipping. ::deep reaches the ApexCharts-built legend node
   because it sits inside this .dash-apex wrapper (which carries the scope id). */
.dash-apex[b-h3kjeisjn9]  .apexcharts-legend {
    flex-wrap: nowrap;
}

/* Custom .NET tooltip (the <ApexPointTooltip> fragment). ApexCharts wraps the Blazor-rendered node in
   its own .apexcharts-tooltip container. When a custom tooltip is supplied that container doesn't get
   the light-theme background, so it renders dark and hides our dark text — force it white with a subtle
   border/shadow. ::deep reaches it because it sits inside this .dash-apex wrapper. */
.dash-apex[b-h3kjeisjn9]  .apexcharts-tooltip {
    background: #fff !important;
    color: #1a1a1a;
    border: 1px solid rgba(0, 0, 0, 0.12) !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* The tooltip body: a small padded card with a date header and label/value rows. */
.dash-apex[b-h3kjeisjn9]  .dash-tip {
    padding: 8px 10px;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: #1a1a1a;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-date {
    font-weight: 600;
    margin-bottom: 4px;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-total {
    margin-top: 4px;
    padding-top: 4px;
    border-top: 1px solid rgba(0, 0, 0, 0.08);
    font-weight: 600;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-value {
    font-variant-numeric: tabular-nums;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-swatch {
    width: 10px;
    height: 10px;
    border-radius: 2px;
    display: inline-block;
}

.dash-apex[b-h3kjeisjn9]  .dash-tip-line {
    width: 12px;
    height: 3px;
    border-radius: 2px;
    display: inline-block;
}
/* /Components/Pages/BookingsSourcePieChart.razor.rz.scp.css */
/* Wrapper for the ApexCharts booking-source pie. ApexCharts builds its own SVG/DOM via JS after
   render inside this Blazor-rendered .dash-apex div, so ::deep descendant rules still reach those
   nodes (the scope id anchors on .dash-apex). Reserve the chart height so the card doesn't jump
   while the chart mounts. */
.dash-apex[b-gptg639l1j] {
    min-height: 320px;
}

/* Custom .NET tooltip (the <ApexPointTooltip> fragment). ApexCharts wraps the Blazor-rendered node in
   its own .apexcharts-tooltip container. When a custom tooltip is supplied that container doesn't get
   the light-theme background, so it renders dark and hides our dark text — force it white with a subtle
   border/shadow. ::deep reaches it because it sits inside this .dash-apex wrapper. */
.dash-apex[b-gptg639l1j]  .apexcharts-tooltip {
    background: #fff !important;
    color: #1a1a1a;
    border: 1px solid rgba(0, 0, 0, 0.12) !important;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

/* The tooltip body: a small padded card with a bold source/count header and the ISK revenue and its
   share stacked beneath. */
.dash-apex[b-gptg639l1j]  .dash-tip {
    padding: 8px 10px;
    font-size: 0.8125rem;
    line-height: 1.5;
    color: #1a1a1a;
}

.dash-apex[b-gptg639l1j]  .dash-tip-head {
    font-weight: 600;
    margin-bottom: 2px;
}

.dash-apex[b-gptg639l1j]  .dash-tip-line-item {
    font-variant-numeric: tabular-nums;
}
/* /Components/Pages/Customers/CustomerDetailsPane.razor.rz.scp.css */
/* Scoped styling for CustomerDetailsPane (§2/§6/§8.5: page-specific presentation lives in the
   scoped *.razor.css companion, not the global sheet or an inline style).

   The tab strip is MudTabs styled globally via the .tab-style-5 class (see styles.css), and booking
   rows open a stacked pane rather than an inline detail, so this pane carries no page-specific tab
   or booking-row styling. */
/* /Components/Pages/Home.razor.rz.scp.css */
/* Dashboard (Home) — stat cards, chart chrome, recent-bookings table.
   All colours reference theme tokens (--bp-* / --mud-palette-*); no hardcoded hex. Selectors
   target elements this component renders directly (plain divs/table), so component scoping applies. */

.dash-card[b-0rizby97mh] {
    display: flex;
    flex-direction: column;
    justify-content: space-between;
    height: 100%;
    min-height: 92px;
    gap: 12px;
}

.dash-card__row[b-0rizby97mh] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 12px;
}

.dash-card__text[b-0rizby97mh] {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.dash-card__title[b-0rizby97mh] {
    font-size: 12px;
    font-weight: 600;
    color: var(--bp-text-muted);
}

.dash-card__value[b-0rizby97mh] {
    font-size: 30px;
    font-weight: 700;
    line-height: 1.1;
    color: var(--bp-text);
}

.dash-card__sub[b-0rizby97mh] {
    font-size: 11px;
    color: var(--bp-text-faint);
}

.dash-card__foot[b-0rizby97mh] {
    font-size: 11px;
    color: var(--bp-text-faint);
    text-align: right;
}

.dash-delta[b-0rizby97mh] {
    align-self: flex-start;
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 11px;
    font-weight: 600;
    padding: 1px 7px;
    border-radius: 6px;
}

.delta-up[b-0rizby97mh] {
    color: var(--mud-palette-success);
    background: var(--mud-palette-success-hover);
}

.delta-down[b-0rizby97mh] {
    color: var(--mud-palette-error);
    background: var(--mud-palette-error-hover);
}

.delta-neutral[b-0rizby97mh] {
    color: var(--bp-text-muted);
    background: var(--bp-surface-alt);
}

.dash-icon[b-0rizby97mh] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    border-radius: 10px;
    flex-shrink: 0;
}

/* Light glyph on the saturated tile (matches the reference cards), overriding Mud's colour class. */
.dash-icon[b-0rizby97mh]  .mud-icon-root {
    color: var(--mud-palette-white);
}

/* Saturated tiles: the solid palette colour. */
.dash-icon--primary[b-0rizby97mh] {
    background: var(--mud-palette-primary);
}

.dash-icon--info[b-0rizby97mh] {
    background: var(--mud-palette-info);
}

.dash-icon--warning[b-0rizby97mh] {
    background: var(--mud-palette-warning);
}

.dash-icon--error[b-0rizby97mh] {
    background: var(--mud-palette-error);
}

/* Stat card look (reference image): a white card with a coloured bottom-accent border matching its
   icon tile, plus a soft shadow tinted the same colour. Both the border and the shadow key off the
   tone token, so card + tile + accent stay in one colour family.
   ::deep off the .dash-cards wrapper because the tone class lives on the MudPaper child component,
   which doesn't carry this component's scope id (see the wrapper note in Home.razor). The -rgb
   palette triplets (emitted by MudBlazor's theme) supply the alpha for the shadow. */
.dash-cards[b-0rizby97mh]  .dash-card-paper {
    border-bottom: 3px solid transparent;
    transition: box-shadow 150ms ease;
}

.dash-cards[b-0rizby97mh]  .dash-shadow--primary {
    border-bottom-color: var(--mud-palette-primary);
    box-shadow: 0 2px 6px -3px rgba(var(--mud-palette-primary-rgb), 0.22) !important;
}

.dash-cards[b-0rizby97mh]  .dash-shadow--info {
    border-bottom-color: var(--mud-palette-info);
    box-shadow: 0 2px 6px -3px rgba(var(--mud-palette-info-rgb), 0.22) !important;
}

.dash-cards[b-0rizby97mh]  .dash-shadow--warning {
    border-bottom-color: var(--mud-palette-warning);
    box-shadow: 0 2px 6px -3px rgba(var(--mud-palette-warning-rgb), 0.22) !important;
}

.dash-cards[b-0rizby97mh]  .dash-shadow--error {
    border-bottom-color: var(--mud-palette-error);
    box-shadow: 0 2px 6px -3px rgba(var(--mud-palette-error-rgb), 0.22) !important;
}

.dash-section-head[b-0rizby97mh] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    flex-wrap: wrap;
    margin-bottom: 12px;
}

/* Bookings-last-30-days layout: the stacked column chart card (2fr, ~2/3) beside the source pie card
   (1fr, ~1/3). Deliberately CSS Grid rather than MudGrid/flex — grid tracks resolve to a definite
   pixel width, so ApexCharts measures a real width when it draws. In a flexbox item the chart can init
   against a 0-width box and render into a blank space. align-items:stretch keeps both cards the same
   height; stacks to a single column below MudBlazor's md break. */
.dash-source-split[b-0rizby97mh] {
    display: grid;
    grid-template-columns: 2fr 1fr;
    gap: 16px;
    align-items: stretch;
}

@media (max-width: 959.98px) {
    .dash-source-split[b-0rizby97mh] {
        grid-template-columns: 1fr;
    }
}

/* Recent-bookings grid: styled to match the Bookings list (StandardGrid.razor.css). The wrapper
   carries the CSS-isolation scope id the ::deep rules anchor to (Blazor never stamps it onto the
   MudDataGrid child), and sets the table-line colour to the base-page border token so every rule
   in the bordered/outlined grid matches the list. */
.dash-grid[b-0rizby97mh] {
    --mud-palette-table-lines: var(--bp-border);
}

/* Square edges (no corner rounding). The bordered/outlined table draws square corners; with no
   radius on the grid root there's nothing for them to overshoot, so the border frame connects
   cleanly at all four corners. */
.dash-grid[b-0rizby97mh]  .mud-data-grid {
    border-radius: 0;
}

/* Cell padding: 12px horizontal / 16px vertical, same as StandardGrid. */
.dash-grid[b-0rizby97mh]  .mud-table-cell {
    padding: 16px 12px !important;
}

/* Bold column headers (heavier than the semibold primary column below). */
.dash-grid[b-0rizby97mh]  .mud-table-head .mud-table-cell {
    font-weight: 700 !important;
    color: var(--bp-text);
}

/* The identifying (Booking) column reads semibold so it leads each row. */
.dash-grid[b-0rizby97mh]  .bp-col-primary {
    font-weight: 600 !important;
}

/* Rows are click targets (open the booking's details pane on this page). */
.dash-grid[b-0rizby97mh]  tbody tr.mud-table-row {
    cursor: pointer;
}

.dash-grid[b-0rizby97mh]  .bp-row-selected td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
}

/* Source chips carry their own scoped styling (SourceChip.razor.css) — nothing to add here. */
/* /Components/Pages/Journeys/JourneyDispatchDetailsPane.razor.rz.scp.css */
/* Scoped styling for the dispatch pane: the Klaviyo delivery-events timeline and the request-payload block.

   Applied to a plain <div>, not to a MudBlazor component: Blazor stamps the CSS-isolation scope id only
   onto plain HTML elements this component renders, never onto a child component's DOM — a class handed to
   MudText/MudChip from here would silently match nothing.

   Colours come from the --bp-* design tokens (§2/§8), the same set every other scoped sheet in this app
   uses — no hardcoded values. The payload is a single-line jsonb string, so it needs pre-wrap to break and
   its own scrollbars for anything that still overflows (a long template id or URL): the pane must never
   grow the page sideways, and a large payload must not stretch the pane vertically. */
/* ── Klaviyo delivery events (design 2a: semantic timeline, outcome-coloured nodes) ─────────────

   A rail of 28px nodes, one per polled event, each tinted by that event's OWN outcome; the content
   column carries the event name + stamp + gap, an optional failure-reason callout in the same tone,
   and the Klaviyo event id as a monospace chip. Same geometry language as the journey panel's step
   rail (JourneyPanel.razor.css), so the two timelines in this module read as one idea.

   Tone is a per-row VARIABLE SET rather than three parallel rules: the node fill, its ring, its icon
   colour and the reason callout all read --jd-tone-*, so a row can never end up with a red ring and
   a grey callout. Values are --bp-* tokens only (§2/§8.2). */

.jd-events[b-59yjcysymr] {
    display: flex;
    flex-direction: column;
}

.jd-ev[b-59yjcysymr] {
    display: flex;
    gap: 14px;
}

/* Sent and Delivered — the event succeeded, whatever the dispatch's eventual verdict was. */
.jd-ev--success[b-59yjcysymr] {
    --jd-tone-bg: var(--bp-tint-success-bg);
    --jd-tone-border: var(--bp-tint-success-border);
    --jd-tone-fg: var(--bp-tint-success-fg);
}

/* Bounced and Dropped — separated from each other by the node icon, not by tone. */
.jd-ev--danger[b-59yjcysymr] {
    --jd-tone-bg: var(--bp-tint-error-bg);
    --jd-tone-border: var(--bp-tint-error-border);
    --jd-tone-fg: var(--bp-tint-error-fg);
}

/* An event type this build has no opinion about yet (Klaviyo engagement events are the expected
   next ones): rendered plainly rather than guessed into a colour. */
.jd-ev--neutral[b-59yjcysymr] {
    --jd-tone-bg: var(--bp-surface-alt);
    --jd-tone-border: var(--bp-border);
    --jd-tone-fg: var(--bp-text-muted);
}

.jd-ev-rail[b-59yjcysymr] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 28px;
    flex: 0 0 28px;
}

.jd-ev-node[b-59yjcysymr] {
    width: 28px;
    height: 28px;
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--jd-tone-bg);
    border: 1px solid var(--jd-tone-border);
    color: var(--jd-tone-fg);
}

/* The node/callout/id icons are MudIcon <svg>s, i.e. child-component DOM that this sheet's scope
   attribute is never stamped on — hence ::deep. Colour comes from the wrapper (MudIcon defaults to
   Color.Inherit); only the size needs reaching in, because MudIcon's own Size steps (20px at the
   smallest) are too big for a 28px node and far too big for the meta chips. */
.jd-ev-node[b-59yjcysymr]  .mud-icon-root {
    font-size: 1rem;
}

/* Hidden on the last row: the rail must stop at the final node rather than trail off. */
.jd-ev-connector[b-59yjcysymr] {
    flex: 1;
    width: 2px;
    margin: 4px 0;
    background: var(--bp-border-strong);
}

.jd-ev:last-child .jd-ev-connector[b-59yjcysymr] {
    display: none;
}

.jd-ev-body[b-59yjcysymr] {
    flex: 1;
    min-width: 0;
    padding-bottom: 16px;
}

.jd-ev:last-child .jd-ev-body[b-59yjcysymr] {
    padding-bottom: 0;
}

/* Wraps rather than truncates: a long event name plus stamp plus gap has to survive the 480px pane
   floor (§4.1) on a narrow viewport. */
.jd-ev-head[b-59yjcysymr] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 8px;
    min-width: 0;
}

.jd-ev-name[b-59yjcysymr] {
    font-size: 0.875rem;
    font-weight: 700;
}

.jd-ev-time[b-59yjcysymr] {
    font-size: 0.75rem;
    color: var(--bp-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Fainter than the absolute stamp: the gap is the derived reading, the stamp is the record. */
.jd-ev-gap[b-59yjcysymr] {
    font-size: 0.75rem;
    color: var(--bp-text-faint);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Failure reason as a callout in the row's tone. Provider text is free-form and can be long or
   unbroken, so it wraps anywhere rather than widening the pane. */
.jd-ev-reason[b-59yjcysymr] {
    margin-top: 7px;
    display: flex;
    align-items: flex-start;
    gap: 8px;
    padding: 8px 10px;
    border-radius: var(--bp-radius-sm);
    background: var(--jd-tone-bg);
    border: 1px solid var(--jd-tone-border);
    font-size: 0.8125rem;
    line-height: 1.4;
    color: var(--bp-text);
    overflow-wrap: anywhere;
}

.jd-ev-reason-icon[b-59yjcysymr] {
    display: flex;
    color: var(--jd-tone-fg);
    flex: 0 0 auto;
    /* Nudged onto the first text line's optical centre. */
    margin-top: 1px;
}

.jd-ev-reason[b-59yjcysymr]  .mud-icon-root {
    font-size: 0.875rem;
}

/* The Klaviyo event id: neutral in every tone — it is an identifier, not a verdict. */
.jd-ev-id[b-59yjcysymr] {
    margin-top: 7px;
    display: inline-flex;
    align-items: center;
    gap: 5px;
    max-width: 100%;
    padding: 3px 8px;
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface-alt);
    border: 1px solid var(--bp-border);
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--bp-text-muted);
    overflow-wrap: anywhere;
}

.jd-ev-id-icon[b-59yjcysymr] {
    display: flex;
    color: var(--bp-text-faint);
    flex: 0 0 auto;
}

.jd-ev-id[b-59yjcysymr]  .mud-icon-root {
    font-size: 0.75rem;
}

/* ── request payload ───────────────────────────────────────────────────────────────────────────── */

.jd-payload[b-59yjcysymr] {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 12px;
    line-height: 1.5;
    white-space: pre-wrap;
    word-break: break-word;
    max-height: 20rem;
    overflow: auto;
    padding: 0.75rem;
    border-radius: var(--bp-radius-md);
    background-color: var(--bp-surface-alt);
    border: 1px solid var(--bp-border);
    color: var(--bp-text);
}
/* /Components/Pages/Journeys/JourneyPanel.razor.rz.scp.css */
/* Journey step timeline — design 1a ("cleaner timeline, tighter cards").

   One continuous rail carries a dot per MILESTONE (booking anchor), with that milestone's step
   cards stacked in the content column beside it. Every colour is a --bp-* token from
   base-page.css (§2/§8.2); this file replaces the inline style="..." attributes the panel used
   to carry on its anchor headers (§6/§8.5).

   Geometry note: the rail column is 20px + 14px gap, so a step card gets ~390px inside the 480px
   pane — enough for a name, a status pill, and the two-column meta rows without wrapping. */

/* ── milestone row ───────────────────────────────────────────────────────── */

.jp-milestone[b-9emt9sy4ut] {
    display: flex;
    gap: 14px;
}

.jp-rail[b-9emt9sy4ut] {
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 20px;
    flex: 0 0 20px;
}

.jp-dot[b-9emt9sy4ut] {
    width: 14px;
    height: 14px;
    flex: 0 0 auto;
    border-radius: 50%;
    /* Aligns the dot with the milestone header's text baseline below. */
    margin-top: 20px;
}

/* Any failed step: retryable, so it outranks "all landed" and the milestone stays red. */
.jp-dot--failed[b-9emt9sy4ut] {
    background: var(--bp-tint-error-fg);
    box-shadow: 0 0 0 4px var(--bp-tint-error-bg);
}

/* Every step terminal — nothing further will happen here. */
.jp-dot--settled[b-9emt9sy4ut] {
    background: var(--bp-tint-success-fg);
    box-shadow: 0 0 0 4px var(--bp-tint-success-bg);
}

/* Still to come. */
.jp-dot--pending[b-9emt9sy4ut] {
    background: var(--bp-tint-info-fg);
    box-shadow: 0 0 0 4px var(--bp-tint-info-bg);
}

/* Anchor exists but nothing is scheduled against it — hollow, so it reads as a marker only. */
.jp-dot--empty[b-9emt9sy4ut] {
    background: var(--bp-surface);
    box-shadow: inset 0 0 0 2px var(--bp-border-strong);
}

.jp-connector[b-9emt9sy4ut] {
    flex: 1;
    width: 2px;
    margin-top: 6px;
    background: var(--bp-border-strong);
}

.jp-milestone-content[b-9emt9sy4ut] {
    flex: 1;
    min-width: 0;
    padding: 16px 0;
}

.jp-milestone-header[b-9emt9sy4ut] {
    display: flex;
    align-items: center;
    gap: 8px;
    min-width: 0;
}

.jp-milestone-label[b-9emt9sy4ut] {
    font-size: 0.875rem;
    font-weight: 700;
    white-space: nowrap;
}

.jp-milestone-time[b-9emt9sy4ut] {
    font-size: 0.75rem;
    color: var(--bp-text-muted);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

/* Wraps MudIcon rather than classing it directly: Blazor CSS isolation stamps its scope attribute
   on this component's own elements, never on a child component's rendered <svg>. The icon inherits
   the colour from here (MudIcon defaults to Color.Inherit); flex kills the inline baseline gap. */
.jp-milestone-icon[b-9emt9sy4ut] {
    display: flex;
    align-items: center;
    color: var(--bp-text-muted);
    flex: 0 0 auto;
}

.jp-empty[b-9emt9sy4ut] {
    margin-top: 8px;
    font-size: 0.75rem;
    color: var(--bp-text-faint);
}

/* ── step card ───────────────────────────────────────────────────────────── */

.jp-steps[b-9emt9sy4ut] {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 10px;
}

.jp-step-card[b-9emt9sy4ut] {
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius-md);
    padding: 12px 14px;
}

.jp-step-head[b-9emt9sy4ut] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.jp-step-name[b-9emt9sy4ut] {
    display: flex;
    align-items: center;
    gap: 2px;
    min-width: 0;
    font-size: 0.875rem;
    font-weight: 700;
}

.jp-step-name-text[b-9emt9sy4ut] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.jp-step-tags[b-9emt9sy4ut] {
    display: flex;
    gap: 6px;
    margin-top: 10px;
    flex-wrap: wrap;
}

.jp-step-actions[b-9emt9sy4ut] {
    margin-top: 12px;
}

/* ── pills ───────────────────────────────────────────────────────────────── */

.jp-pill[b-9emt9sy4ut] {
    display: inline-flex;
    align-items: center;
    padding: 3px 10px;
    border: 1px solid transparent;
    border-radius: 999px;
    font-size: 0.6875rem;
    font-weight: 600;
    line-height: 1.4;
    white-space: nowrap;
}

/* Status — solid for the two states that demand attention, tint for the two that don't. */
.jp-pill--failed[b-9emt9sy4ut] {
    background: var(--bp-tint-error-fg);
    color: var(--bp-on-dark);
    font-weight: 700;
}

.jp-pill--scheduled[b-9emt9sy4ut] {
    background: var(--bp-tint-info-fg);
    color: var(--bp-on-dark);
    font-weight: 700;
}

.jp-pill--sent[b-9emt9sy4ut] {
    background: var(--bp-tint-success-bg);
    color: var(--bp-tint-success-fg);
    font-weight: 700;
}

.jp-pill--skipped[b-9emt9sy4ut] {
    background: var(--bp-surface-alt);
    color: var(--bp-text-muted);
    font-weight: 700;
}

/* Channel, and the fallback for in-flight/unmapped values. */
.jp-pill--neutral[b-9emt9sy4ut] {
    background: var(--bp-surface-alt);
    color: var(--bp-text);
    border-color: var(--bp-border);
}

/* Category — outlined so it never competes with the status pill. */
.jp-pill--transactional[b-9emt9sy4ut] {
    background: var(--bp-surface);
    color: var(--bp-accent-strong);
    border-color: var(--bp-accent);
}

.jp-pill--marketing[b-9emt9sy4ut] {
    background: var(--bp-surface);
    color: var(--bp-tint-secondary-fg);
    border-color: var(--bp-tint-secondary-border-strong);
}

/* ── meta rows (label → value) ───────────────────────────────────────────── */

.jp-meta[b-9emt9sy4ut] {
    margin-top: 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    font-size: 0.78125rem;
}

.jp-meta-row[b-9emt9sy4ut] {
    display: flex;
    gap: 8px;
    align-items: baseline;
}

.jp-meta-label[b-9emt9sy4ut] {
    width: 74px;
    flex: 0 0 74px;
    color: var(--bp-text-muted);
    font-weight: 600;
}

.jp-meta-value[b-9emt9sy4ut] {
    min-width: 0;
    font-variant-numeric: tabular-nums;
}

/* The "· 1h after booked" trailer and the skip reason — supporting detail, not the value. */
.jp-meta-note[b-9emt9sy4ut] {
    color: var(--bp-text-muted);
    font-variant-numeric: normal;
}

.jp-meta-value--failed[b-9emt9sy4ut] {
    color: var(--bp-tint-error-fg);
    font-weight: 600;
}

.jp-meta-value--sent[b-9emt9sy4ut] {
    color: var(--bp-tint-success-fg);
    font-weight: 600;
}
/* /Components/Pages/Journeys/JourneyTemplateDetailsPane.razor.rz.scp.css */
/* Journey-template pane, sectioned layout: pinned name field, Information group box, staged step
   cards, tour-mapping cards. The pane's footer holds only the explicit Save button (§4.3 override)
   and is styled by base-page.css. Colours/radii come from --bp-* tokens only (§2, §8) —
   no hardcoded hex. Classes sit on plain elements; where a MudBlazor child needs styling it is
   reached through a descendant selector from a plain wrapper (a scoped class set directly on a
   Mud component never lands on its DOM). */

/* ═══ NAME FIELD ═══ */
/* Pinned above the scrolling body. The negative offsets cancel .bp-pane-body's 12px padding so the
   block bleeds to the pane edges and its rule lines up with the header's. */
.jt-name-block[b-pc8o2t8z75] {
    position: sticky;
    top: -12px;
    z-index: 2;
    margin: -12px -12px 16px;
    padding: 12px 12px 14px;
    background: var(--bp-surface);
    border-bottom: 1px solid var(--bp-border);
}

.jt-field-label[b-pc8o2t8z75] {
    font-size: 10.5px;
    font-weight: 700;
    letter-spacing: .07em;
    text-transform: uppercase;
    color: var(--bp-text-faint);
    margin-bottom: 6px;
}

/* ═══ SECTION HEADS ═══ */
/* Step count, shown in the Steps GroupBox's TitleActions slot (inline on the box border). */
.jt-count[b-pc8o2t8z75] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 20px;
    height: 20px;
    padding: 0 6px;
    font-size: 11px;
    font-weight: 700;
    color: var(--mud-palette-text-primary);
    background: var(--mud-palette-primary);
    border-radius: 999px;
}

.jt-violations[b-pc8o2t8z75] {
    margin: 6px 0 0;
    padding-left: 18px;
}

/* ═══ STAGE GROUPS ═══ */
.jt-group[b-pc8o2t8z75] {
    margin-bottom: 8px;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius-md);
    overflow: hidden;
}

.jt-group-head[b-pc8o2t8z75] {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 12px;
    cursor: pointer;
    user-select: none;
}

.jt-expanded > .jt-group-head[b-pc8o2t8z75] {
    background: var(--bp-accent-bg);
}

.jt-collapsed > .jt-group-head:hover[b-pc8o2t8z75] {
    background: var(--bp-surface-alt);
}

.jt-group-chevron[b-pc8o2t8z75] {
    display: inline-flex;
    color: var(--bp-text-muted);
}

/* Rounded-square stage badge. On the tinted expanded head it inverts to the plain surface so it
   stays legible; collapsed it reads as a quiet grey chip. */
.jt-group-icon[b-pc8o2t8z75] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    flex-shrink: 0;
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface-alt);
    color: var(--bp-text-muted);
}

.jt-expanded .jt-group-icon[b-pc8o2t8z75] {
    background: var(--bp-surface);
    color: var(--bp-accent-strong);
}

/* `::deep` is required to reach a MudIcon's own DOM: the scoped-CSS rewriter appends the scope
   attribute to the RIGHTMOST selector, so a plain `.wrapper .mud-icon-root` would compile to
   `.wrapper .mud-icon-root[scope]` and never match (the svg belongs to MudIcon, not this file). */
.jt-group-chevron[b-pc8o2t8z75]  .mud-icon-root.mud-icon-size-small,
.jt-group-icon[b-pc8o2t8z75]  .mud-icon-root.mud-icon-size-small {
    font-size: 15px;
}

.jt-group-label[b-pc8o2t8z75] {
    font-size: 13px;
    font-weight: 700;
    color: var(--bp-text);
}

.jt-group-count[b-pc8o2t8z75] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 18px;
    height: 18px;
    padding: 0 5px;
    font-size: 10.5px;
    font-weight: 700;
    color: var(--bp-text-muted);
    background: var(--bp-border);
    border-radius: 999px;
}

.jt-group-body[b-pc8o2t8z75] {
    border-top: 1px solid var(--bp-border);
    padding: 2px 12px 8px 44px;
}

.jt-group-empty[b-pc8o2t8z75] {
    padding: 8px 0 2px;
}

/* ═══ STEP CARDS ═══ */
.jt-step-row[b-pc8o2t8z75] {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 10px 6px;
    margin: 0 -6px;
    border-radius: var(--bp-radius-sm);
    cursor: pointer;
}

.jt-step-row + .jt-step-row[b-pc8o2t8z75] {
    border-top: 1px solid var(--bp-border-soft);
    border-radius: 0;
}

.jt-step-row:hover[b-pc8o2t8z75] {
    background: var(--bp-surface-alt);
}

.jt-step-main[b-pc8o2t8z75] {
    flex: 1;
    min-width: 0;
}

.jt-step-title[b-pc8o2t8z75] {
    display: flex;
    align-items: center;
    gap: 6px;
}

.jt-step-schedule[b-pc8o2t8z75] {
    font-size: 12px;
    color: var(--bp-text-muted);
    margin-top: 3px;
}

.jt-step-tags[b-pc8o2t8z75] {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 6px;
    margin-top: 8px;
}

/* ═══ TOUR MAPPINGS ═══ */
.jt-mapping-list[b-pc8o2t8z75] {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.jt-mapping-card[b-pc8o2t8z75] {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 11px 12px;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius-md);
    cursor: pointer;
}

.jt-mapping-card:hover[b-pc8o2t8z75] {
    background: var(--bp-surface-alt);
    border-color: var(--bp-border-strong);
}

.jt-mapping-icon[b-pc8o2t8z75] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 34px;
    height: 34px;
    flex-shrink: 0;
    border-radius: var(--bp-radius-sm);
    background: var(--bp-surface-alt);
    border: 1px solid var(--bp-border);
    color: var(--bp-text-muted);
}

.jt-mapping-icon[b-pc8o2t8z75]  .mud-icon-root.mud-icon-size-small {
    font-size: 17px;
}

.jt-mapping-main[b-pc8o2t8z75] {
    flex: 1;
    min-width: 0;
}

.jt-mapping-name[b-pc8o2t8z75] {
    font-size: 13px;
    font-weight: 700;
    color: var(--bp-text);
}

.jt-mapping-ref[b-pc8o2t8z75] {
    font-size: 11.5px;
    color: var(--bp-text-faint);
    font-variant-numeric: tabular-nums;
}

/* /Components/Pages/Reviews/ReviewDetailsPane.razor.rz.scp.css */
/* Scoped styling for the review pane (design 1a). Only what MudBlazor cannot carry: the tinted severity
   hero, its star row and score, the review quote, and the profile URL's wrapping. The property grids are
   MudGrid + the pane's Field helper, so they need nothing here.

   Applied to plain HTML elements only — Blazor stamps the scope id onto this component's own DOM, never
   onto a child component's, so a class handed to MudText, MudIcon or MudPaper from here would silently
   match nothing. Colours come from the --bp-* design tokens (§2/§8). */

/* Severity tone. Each class defines the pair once; the hero reads --rd-tone-bg and the quote border
   reads --rd-tone-fg, so a band's colour is stated in exactly one place. */
.rd-tone-critical[b-r6igxxveky] {
    --rd-tone-bg: var(--bp-tint-error-bg);
    --rd-tone-fg: var(--bp-tint-error-fg);
}

.rd-tone-mixed[b-r6igxxveky] {
    --rd-tone-bg: var(--bp-tint-warning-bg);
    --rd-tone-fg: var(--bp-tint-warning-fg);
}

.rd-tone-positive[b-r6igxxveky] {
    --rd-tone-bg: var(--bp-tint-success-bg);
    --rd-tone-fg: var(--bp-tint-success-fg);
}

/* Triage hero: the rating is the reason this pane gets opened, so it is the first thing in the body. */
.rd-hero[b-r6igxxveky] {
    padding: 1rem;
    border-radius: var(--bp-radius);
    background: var(--rd-tone-bg);
}

/* Colour lands on the wrapper spans and is inherited by the MudIcons inside. */
.rd-stars[b-r6igxxveky] {
    display: inline-flex;
    gap: 0.125rem;
    line-height: 1;
    color: var(--rd-tone-fg);
}

.rd-stars-empty[b-r6igxxveky] {
    color: var(--bp-text-ghost);
}

.rd-score[b-r6igxxveky] {
    display: flex;
    align-items: baseline;
    gap: 0.2rem;
    font-weight: 700;
    font-size: 1.35rem;
    line-height: 1;
    color: var(--rd-tone-fg);
}

.rd-score-scale[b-r6igxxveky] {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--bp-text-muted);
}

/* Reviewer-written prose: hard line breaks are meaningful, and a URL or an unbroken word must wrap
   rather than widen the pane past its 480px floor (§4.1). The tone border repeats the hero's verdict
   where the evidence for it actually is. */
.rd-body[b-r6igxxveky] {
    white-space: pre-wrap;
    overflow-wrap: anywhere;
    font-size: 0.875rem;
    line-height: 1.6;
    color: var(--bp-text);
    padding: 0.75rem 1rem;
    border-left: 3px solid var(--rd-tone-fg);
    border-radius: 0 var(--bp-radius-md) var(--bp-radius-md) 0;
    background: var(--bp-surface-alt);
}

/* Profile URLs run long (Viator paths carry ids); break rather than push the property grid sideways. */
.rd-profile-url[b-r6igxxveky] {
    overflow-wrap: anywhere;
}
/* /Components/Pages/Surveys/SurveyReportingDashboard.razor.rz.scp.css */
/*
 * Scoped presentation for the NPS reporting analytics visualisations that have no direct MudBlazor
 * primitive: the segmented detractor/passive/promoter proportion bar, the 0–10 distribution
 * histogram, the distribution legend, and the per-row star/choice layouts. Everything else on the
 * page is composed from MudBlazor components (§8.1).
 *
 * Colours come only from the global design tokens (--bp-* / --mud-palette-*) — no hard-coded hex
 * (§2). The one thing passed inline from markup is dynamic geometry (bar height, segment weight),
 * supplied as CSS custom properties (--h / --seg) and consumed here — never colour (§6).
 *
 * These rules only target plain HTML elements authored in the .razor file; MudBlazor components are
 * styled via their own params + global utility classes, since CSS-isolation scope ids don't attach
 * to child-component roots.
 *
 * Responsiveness: the pane is sized max(40%, min(480px, 92vw)) (base-page.css), so its width does
 * NOT track the viewport linearly — a viewport media query would fire at the wrong moment. The
 * analytics body is therefore a size container (.pane-analytics) and the two-column distributions
 * reflow against the PANE's inline size: flex bases wrap them to a stacked column as soon as they
 * no longer fit side by side, and one @container tier tightens the leftovers on a phone-width pane.
 */

/* ── Pane analytics size container ─────────────────────────────────────── */
.pane-analytics[b-2v86pjtegu] {
    container-type: inline-size;
    container-name: pane;
}

/* ── Pane header eyebrow + title ───────────────────────────────────────── */
/* basis 100% (not 0) so this block claims the header's whole free width: its sibling
   .bp-toolbar-spacer is also flex:1 and would otherwise split that space 50/50, halving the room
   the title gets. The spacer belongs to DetailsPane, so page-scoped CSS can't reach it — outgrowing
   it here is the only lever. Shrinks back down normally, hence min-width:0. */
.pane-head-start[b-2v86pjtegu] {
    flex: 1 1 100%;
    min-width: 0;
}

/* Single-line, ellipsised — the scope note, whose tail is the least important text in the header. */
.pane-title-ellipsis[b-2v86pjtegu] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

/* The title instead spills onto a second line before ellipsising, so a narrow pane still names the
   questionnaire. No-op at widths where it already fits on one line. */
.pane-title-clamp[b-2v86pjtegu] {
    display: -webkit-box;
    -webkit-box-orient: vertical;
    -webkit-line-clamp: 2;
    line-clamp: 2;
    overflow: hidden;
}

/* ── NPS: score summary column ─────────────────────────────────────────── */
/* Grows to fill the row once the histogram has wrapped below it; 150px is the basis at which the
   two columns stop fitting side by side, not a hard floor. */
.nps-summary[b-2v86pjtegu] {
    flex: 1 1 150px;
    min-width: 0;
}

/* Segmented detractor | passive | promoter proportion bar. Each segment's flex weight is its
   response count, passed inline as --seg. */
.prop-bar[b-2v86pjtegu] {
    display: flex;
    height: 8px;
    border-radius: 4px;
    overflow: hidden;
    background: var(--bp-surface-alt);
}

.prop-seg[b-2v86pjtegu] {
    flex: var(--seg) 0 0;
}

    .prop-seg--det[b-2v86pjtegu] {
        background: var(--mud-palette-error);
    }

    .prop-seg--pas[b-2v86pjtegu] {
        background: var(--mud-palette-warning);
    }

    .prop-seg--pro[b-2v86pjtegu] {
        background: var(--mud-palette-success);
    }

/* Percentage summary under the proportion bar. */
.dist-item[b-2v86pjtegu] {
    font-size: 11px;
    color: var(--bp-text-muted);
    white-space: nowrap;
}

.pct[b-2v86pjtegu] {
    font-weight: 600;
}

    .pct--det[b-2v86pjtegu] {
        color: var(--mud-palette-error);
    }

    .pct--pas[b-2v86pjtegu] {
        color: var(--mud-palette-warning);
    }

    .pct--pro[b-2v86pjtegu] {
        color: var(--mud-palette-success);
    }

/* ── NPS: 0–10 distribution histogram ──────────────────────────────────── */
/* Takes the remaining width when both columns fit, and the full row once they don't. min-width:0
   (not 220px) is what lets it wrap instead of forcing the row wider than the pane. */
.nps-dist[b-2v86pjtegu] {
    flex: 3 1 220px;
    min-width: 0;
}

.nps-hist[b-2v86pjtegu] {
    display: flex;
    align-items: flex-end;
    gap: 3px;
    height: 80px;
}

.nps-hist-col[b-2v86pjtegu] {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: flex-end;
    height: 100%;
}

/* Bar height is passed inline as --h. */
.nps-bar[b-2v86pjtegu] {
    width: 100%;
    border-radius: 2px 2px 0 0;
    height: var(--h);
}

    .nps-bar--det[b-2v86pjtegu] {
        background: var(--mud-palette-error);
    }

    .nps-bar--pas[b-2v86pjtegu] {
        background: var(--mud-palette-warning);
    }

    .nps-bar--pro[b-2v86pjtegu] {
        background: var(--mud-palette-success);
    }

.nps-cap[b-2v86pjtegu] {
    font-size: 9px;
    color: var(--bp-text-faint);
}

/* Distribution legend (swatch + range label). */
.legend[b-2v86pjtegu] {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    font-size: 10px;
    color: var(--bp-text-muted);
}

.dist-swatch[b-2v86pjtegu] {
    width: 8px;
    height: 8px;
    border-radius: 2px;
    display: inline-block;
}

    .dist-swatch--det[b-2v86pjtegu] {
        background: var(--mud-palette-error);
    }

    .dist-swatch--pas[b-2v86pjtegu] {
        background: var(--mud-palette-warning);
    }

    .dist-swatch--pro[b-2v86pjtegu] {
        background: var(--mud-palette-success);
    }

/* ── Star rating distribution ──────────────────────────────────────────── */
.star-summary[b-2v86pjtegu] {
    flex: 0 0 auto;
    display: flex;
    flex-direction: column;
}

.star-dist[b-2v86pjtegu] {
    flex: 1 1 220px;
    min-width: 0;
    margin-left: auto;
    text-align: right;
}

.star-row[b-2v86pjtegu] {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 8px;
    font-size: 11px;
    margin-bottom: 5px;
}

.star-row-label[b-2v86pjtegu] {
    display: inline-flex;
    align-items: center;
    justify-content: flex-end;
    gap: 6px;
    min-width: 84px;
}

.stars[b-2v86pjtegu] {
    letter-spacing: 1px;
    white-space: nowrap;
    color: var(--mud-palette-warning);
}

.star-count[b-2v86pjtegu] {
    width: 28px;
    text-align: right;
    color: var(--bp-text);
}

/* ── Multiple-choice option frequency ──────────────────────────────────── */
.choice-row[b-2v86pjtegu] {
    display: flex;
    align-items: center;
    gap: 8px;
    font-size: 12px;
    margin-bottom: 6px;
}

.choice-label[b-2v86pjtegu] {
    flex: 0 1 40%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    color: var(--bp-text);
}

.choice-count[b-2v86pjtegu] {
    width: 28px;
    text-align: right;
    font-weight: 600;
    color: var(--bp-text);
}

.choice-pct[b-2v86pjtegu] {
    width: 36px;
    text-align: right;
    color: var(--bp-text-muted);
}

/* ── Verbatim feedback quote ───────────────────────────────────────────── */
.verbatim-quote[b-2v86pjtegu] {
    font-style: italic;
    line-height: 1.45;
}

/* ── Narrow pane (phone-width viewport, where the pane falls back to 92vw) ─
   The columns have already stacked by this point via their flex bases; this tier only reclaims the
   gaps and fixed label gutters that stop paying for themselves at ~300px of card content. */
@container pane (max-width: 420px) {
    .nps-hist[b-2v86pjtegu] {
        gap: 2px;
        height: 64px;
    }

    /* Stacked full-width: drop the right-alignment gutter and let the track fill the row rather than
       leaving ~150px of dead space to the left of a 120px bar. */
    .star-dist[b-2v86pjtegu] {
        margin-left: 0;
        text-align: left;
    }

    /* The label keeps its 84px gutter here (it's affordable once the block is full-width) so every
       bar still starts on the same x — dropping it leaves the tracks ragged. */
    .star-row[b-2v86pjtegu] {
        gap: 6px;
        justify-content: flex-start;
        --star-track-max: none;
    }

    .choice-row[b-2v86pjtegu] {
        gap: 6px;
    }

    .dist-item[b-2v86pjtegu] {
        font-size: 10px;
    }
}
/* /Components/Pages/TourDepartures/TourDepartureDetailsPane.razor.rz.scp.css */
/* Scoped styling for TourDepartureDetailsPane (§2/§6/§8.5: page-specific presentation lives in the
   scoped *.razor.css companion, not the global sheet or an inline style).

   The tab strip is MudTabs styled globally via .tab-style-5 (styles.css). The Passengers roster uses
   MudTable + MudLink (palette-coloured), so no page-specific rules are needed here at present. */
/* /Components/Shared/Base/EmptyState.razor.rz.scp.css */
/* Centered, muted empty-state block (mirrors StandardGrid's NoRecordsContent). Padding gives it
   presence inside a pane section without a border; colour comes from the token hook in markup. */
.bp-empty-state[b-w5z2woc09v] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 2rem 1rem;
    text-align: center;
}

.bp-empty-state__icon[b-w5z2woc09v] {
    opacity: 0.5;
}

.bp-empty-state__action[b-w5z2woc09v] {
    margin-top: 0.25rem;
}
/* /Components/Shared/Base/SourceChip.razor.rz.scp.css */
/* Scoped styling for SourceChip (§2/§6/§8.5: presentation lives in the scoped *.razor.css
   companion, not the global sheet or an inline style).

   The brand background colour per booking source is fixed by spec and has no MudTheme token, so the
   hex lives here as named source classes rather than inline styles. The on-colour text does have a
   token (--bp-on-dark), so it is used rather than a bare #fff. MudChip renders its own markup with
   no scope id, so the chip is reached with ::deep anchored to the .source-chip wrapper <span> —
   which is part of this component and therefore carries this file's scope id on every page that
   uses it. !important overrides MudChip's own equal-specificity filled-colour rule. */
.source-chip[b-5jg1n27j65]  .mud-chip {
    color: var(--bp-on-dark) !important;
    font-weight: 500;
}

.source-chip.source-direct[b-5jg1n27j65]  .mud-chip {
    background-color: #0B75D1 !important;
}

.source-chip.source-ota[b-5jg1n27j65]  .mud-chip {
    background-color: #424668 !important;
}

.source-chip.source-agent[b-5jg1n27j65]  .mud-chip {
    background-color: #878AA3 !important;
}
/* /Components/Shared/Base/StatusBadge.razor.rz.scp.css */
/* Optional leading dot for the pill (StatusBadge Dot="true").

   Scoped to `.badge-with-dot` rather than `.badge` so a plain badge keeps yzen's own layout
   untouched — this file must not change how the ~dozen existing dotless call sites render.

   Dot colour comes from `currentColor`, which the yzen `text-*` variant class on the badge
   already sets, so the dot tracks every variant automatically with no token lookup here. */

.badge-with-dot[b-a8g063n7oo] {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
}

.badge-dot[b-a8g063n7oo] {
    width: 7px;
    height: 7px;
    flex: 0 0 auto;
    border-radius: 50%;
    background: currentColor;
}
/* /Components/Shared/GroupBox.razor.rz.scp.css */
/* GroupBox "border title": native fieldset/legend so the title notches the top border on ANY
   background (no surface-colour matching). Overrides Bootstrap reboot, which resets
   fieldset { border:0 } and legend { float:left; width:100% } — both of which would kill the notch.
   Colours/radius come from --bp-* tokens (§2) — no hardcoded hex. */

.groupbox[b-vimk18w6fu] {
    min-inline-size: 0; /* undo fieldset's default min-width:min-content so it can shrink */
    margin: 0;
    padding: 0.5rem 1rem 0.75rem;
    border: 1px solid var(--bp-border);
    border-radius: var(--bp-radius);
}

.groupbox-legend[b-vimk18w6fu] {
    float: none; /* counter Bootstrap reboot's legend float:left / width:100% */
    width: auto;
    margin: 0 0 0 0.25rem;
    padding: 0 0.375rem; /* breathing room where the title cuts the border */
    font-size: inherit;
    line-height: 1;
}

/* Legend keeps its default display so the border notch renders; the inner wrapper does the layout. */
.groupbox-legend-inner[b-vimk18w6fu] {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
/* /Components/Shared/StandardGrid.razor.rz.scp.css */
/* Scoped styling for StandardGrid (§2/§6/§8.5: page-specific presentation lives in the scoped
   *.razor.css companion, not the global sheet).

   ANCHORING: Blazor CSS isolation stamps the scope id onto plain HTML elements written in THIS
   file only — never onto child components (MudCard/MudDataGrid/MudButton). Every visual below
   lives inside such a child, so the rules use `::deep` (compiled to `[scope] <descendant>`) and
   need one HTML element carrying the scope id to anchor to. The `.standard-grid` wrapper <div>
   is that element; it doubles as the grid style hook and is `display: contents` so it adds no
   box to the layout. Custom properties set on it still inherit into the grid. */
.standard-grid[b-vgt055syg2] {
    display: contents;
    /* Grid separators (§4.5): MudBlazor's Bordered draws vertical column rules, Outlined the
       outer frame, the default row rules the horizontals — every line uses the base-page border
       token so the whole grid is fully ruled like the sample. Inherits down to the MudDataGrid. */
    --mud-palette-table-lines: var(--bp-border);
}

/* The grid, toolbar and footer live in one elevated MudCard. Clip to the card radius so the
   bordered grid's square corners meet the rounded card edge. Popovers (page-size select) render
   in a body-level portal, so this never clips them.

   The card fills the height its list region hands it (flex:1 + min-height:0) and, being a flex
   column already (.mud-card), lets its inner grid take the leftover height and scroll. This is what
   keeps a full page of rows INSIDE the grid instead of growing the card and scrolling the page —
   see the .mud-data-grid / .mud-table-container rules below. */
[b-vgt055syg2] .standard-grid-card {
    overflow: hidden;
    flex: 1 1 auto;
    min-height: 0;
}

/* The data grid is the vertical scroll surface WITHIN the card. Make its root a flex column that
   takes the card's leftover height (flex:1 + min-height:0), so its table container — not the page —
   owns the scroll. The subtitle, toolbar, filter chips and pager footer sit outside the grid and
   keep their natural height, staying put while the rows scroll. */
[b-vgt055syg2] .standard-grid-card .mud-data-grid {
    flex: 1 1 auto;
    min-height: 0;
    display: flex;
    flex-direction: column;
}

/* The scroll container: fills the grid's height and scrolls its rows vertically. FixedHeader keeps
   the column header pinned (sticky thead, top:0) as the body scrolls, so a page of 25 rows scrolls
   within the grid while the header, toolbar and footer stay visible and the page never scrolls. */
[b-vgt055syg2] .standard-grid-card .mud-table-container {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
}

/* §4.4 toolbar rendered on a secondary (tinted) surface inside the card. The .bp-toolbar cascade
   (shared control baseline + filter-input styling) still applies; this variant only supplies the
   fill, radius and padding, and drops the page-level blend/margin that only suited the app bg. */
[b-vgt055syg2] .bp-toolbar-surface {
    background: rgb(var(--light-rgb));
    border-radius: 0.5rem;
    padding: 12px 16px;
    mix-blend-mode: normal;
}

/* Filter-card inputs (§4.4): the search box, date pickers and MudSelects sit on the tinted toolbar
   surface above. Fill each input with the MudBlazor input/surface token so it reads as a distinct
   field against the grey toolbar instead of blending into it (theme-aware: #fff light / dark surface). */
[b-vgt055syg2] .bp-toolbar-surface .mud-input {
    background-color: var(--mud-palette-surface);
}

/* ═══ SEARCH GROUP (§4.4) ═══ */
/* The search box + its Search button form ONE combined control taking ~30% of the toolbar width
   (design request 2026-07-16): the button is attached flush to the field's right edge — squared
   inner corners meeting at a single seam — rather than a detached button. The field flex-fills the
   group; the button hugs its label. Search is button/Enter-driven — no debounce. */
/* `stretch` (not flex-end) is what keeps the button the SAME height as the field: it makes both
   items span the group's height instead of each sizing itself, so the button tracks whatever the
   field actually computes to. See the button rule below. */
[b-vgt055syg2] .bp-grid-search-group {
    display: flex;
    align-items: stretch;
    gap: 0;
    flex: 0 0 30%;
    max-width: 30%;
}

[b-vgt055syg2] .bp-grid-search-group .bp-grid-search {
    flex: 1 1 auto;
}

/* Square off the field's right corners so its edge meets the button cleanly (the toolbar's default
   rounds all four via .bp-toolbar .filter-select .mud-input-outlined-border). */
[b-vgt055syg2] .bp-grid-search .mud-input.mud-input-outlined,
[b-vgt055syg2] .bp-grid-search .mud-input-outlined-border {
    border-top-right-radius: 0 !important;
    border-bottom-right-radius: 0 !important;
}

/* Match the Search button to the field exactly:
   - height DERIVED from the field, not pinned to --bp-filter-h. Pinning both to the token only lines
     them up while the field really is that tall: yzen overrides MudBlazor's dense input padding
     (`.mud-input > input.mud-input-root { padding: 6px 11px 7px !important }` in assets/css/styles.css),
     so the field's own content height is 38px and a 40px button stood 2px taller. `height/min-height:
     auto` + `align-self: stretch` makes the button span the group instead, so it is exactly as tall as
     the field whatever the theme does to the input's metrics. min-height:0 beats MudButton's own
     size min-height; both need !important to win against it;
   - left corners squared and pulled -1px so it shares the field's right border as one seam;
   - margin-bottom: 4px mirrors the dense input's `.mud-input-control-margin-dense { margin: 4px 0 }`
     (the field has mt-0, so only its 4px BOTTOM margin remains) — it is subtracted from the stretched
     height, so both bordered boxes share one top AND bottom edge (see the filter-pill note in
     base-page.css). */
[b-vgt055syg2] .bp-grid-search-btn.mud-button-root {
    height: auto !important;
    min-height: 0 !important;
    box-sizing: border-box;
    flex: 0 0 auto;
    align-self: stretch;
    margin-block-end: 4px;
    margin-inline-start: -1px;
    border-top-left-radius: 0;
    border-bottom-left-radius: 0;
    text-transform: none;
}

/* Cell padding (§6 spacing): 12px horizontal, 16px vertical on every header and body cell so the
   grid reads with consistent breathing room instead of MudBlazor's default dense padding. */
[b-vgt055syg2] .mud-table-cell {
    padding: 16px 12px !important;
}

/* Column header names are bold — heavier than both the body rows and the primary column (§4.5). */
[b-vgt055syg2] .mud-table-head .mud-table-cell {
    font-weight: 700 !important;
    color: var(--bp-text);
}

/* The first (name/identifier) column reads semibold so each row's primary label leads the row —
   the whole row is the click target (§4.5). Callers tag their identifying column with
   CellClass="bp-col-primary"; it lands on the body <td>, so it sits below the bold header weight. */
[b-vgt055syg2] .bp-col-primary {
    font-weight: 600 !important;
}

/* Pointer cursor on clickable rows (was an inline RowStyle; §6 keeps presentation in CSS). */
[b-vgt055syg2] tr.bp-row-click {
    cursor: pointer;
}

/* Selected row: stays highlighted while its details pane is open (§4.2). Overrides the row's
   hover background and marks it with a left accent bar. Tint and bar are both the yzen brand
   primary (--bp-selected-bg is derived from the same --primary-rgb as --mud-palette-primary), so
   the row reads as one colour rather than a green fill under a blue bar. */
[b-vgt055syg2] .bp-row-selected,
[b-vgt055syg2] .bp-row-selected td {
    background-color: var(--bp-selected-bg) !important;
}

[b-vgt055syg2] .bp-row-selected td:first-child {
    box-shadow: inset 3px 0 0 var(--mud-palette-primary);
}

/* ═══ SORT AFFORDANCE (§4.5) ═══ */
/* The indicator is a Remix Icon glyph (icons.css) in the header's ::after; MudBlazor's own sort
   icon is hidden so we fully control it. Unsorted sortable columns show the faint up/down caret
   pair (expand-up-down-fill); a sorted column replaces it with a single BOLD directional caret
   in the strong brand colour — arrow-up-s-fill for asc, arrow-down-s-fill for desc. */
[b-vgt055syg2] .mud-table-cell .column-header .sort-direction-icon {
    display: none;
}

[b-vgt055syg2] .mud-table-cell .column-header:has(.sortable-column-header)::after {
    font-family: "remixicon";
    content: "\f326"; /* ri-expand-up-down-fill — filled caret up + down */
    font-size: 15px;
    line-height: 1;
    /*margin-inline-start: 4px;*/
    color: var(--bp-text-ghost);
    -webkit-font-smoothing: antialiased;
}

[b-vgt055syg2] .mud-table-cell .column-header:has(.sort-direction-icon.mud-direction-asc)::after {
    content: "\ea77"; /* ri-arrow-up-s-fill — bold caret up */
    color: var(--bp-accent-strong);
}

[b-vgt055syg2] .mud-table-cell .column-header:has(.sort-direction-icon.mud-direction-desc)::after {
    content: "\ea4d"; /* ri-arrow-down-s-fill — bold caret down */
    color: var(--bp-accent-strong);
}

/* Footer pager numeric buttons (§4.5): the custom pager (MudButtonGroup of MudButtons) sits
   inside the grid card. Each numbered button should size to its digit(s) + padding, not
   MudButton's default ~64px min-width, which otherwise makes single-digit page buttons far
   wider than they need to be. Zero the min-width so the button collapses to content + padding;
   !important beats MudBlazor's own .mud-button min-width rule. */
[b-vgt055syg2] .pager-page {
    min-width: 0 !important;
    padding-inline: 16px !important;
}

/* ═══ BULK-ACTION BAR (§4.5 / request rule 3.1) ═══ */
/* Shown while rows are selected. Dark filled rounded card with white outlined pill buttons
   (design note 2026-07-13). The pill buttons themselves are styled by BulkActionButton. */
[b-vgt055syg2] .bp-grid-bulkbar {
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
    margin-bottom: 12px;
    padding: 8px 8px 8px 16px;
    border-radius: var(--bp-radius);
    background: var(--bp-bulkbar-bg);
    color: var(--bp-bulkbar-fg);
    box-shadow: var(--bp-shadow-menu);
}

[b-vgt055syg2] .bp-grid-bulkbar__count {
    font-size: 13px;
    font-weight: 600;
    color: var(--bp-bulkbar-fg);
    margin-right: 6px;
}

/* Clear-selection (✕) icon button on the dark bar. */
[b-vgt055syg2] .bp-grid-bulkbar__clear.mud-button-root {
    color: rgba(255, 255, 255, 0.85);
}

[b-vgt055syg2] .bp-grid-bulkbar__clear.mud-button-root:hover {
    background: var(--bp-bulkbar-btn-hover);
}
