/**
 * Seat Selection Styles — map-first redesign.
 * Fixed selection rail (desktop) / sticky bottom bar + bottom sheet (mobile),
 * map toolbar (legend + zoom), info strip, per-seat ticket-type picker,
 * countdown pill, toast notifications, and seat color classes.
 *
 * Design tokens: page #F5F7F9, map #F4F7FA, card #fff, seat card #F6F9FD,
 * info strip #F4F8FD, borders #E2E7EC / #EEF1F4 / #D5DBE1.
 */

/* ===== Map-first grid ===== */

.seat-layout-grid {
    display: grid;
    grid-template-columns: 1fr 340px;
    gap: 20px;
    align-items: start;
}

/* ===== Map card ===== */

.map-card {
    background: #fff;
    border: 1px solid #E2E7EC;
    border-radius: 12px;
    overflow: hidden;
}

.map-toolbar {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    flex-wrap: wrap;
    padding: 12px 16px;
    border-bottom: 1px solid #EEF1F4;
}

.map-legend {
    display: flex;
    align-items: center;
    /* Row/column split rather than a single value: the column gap is the original 16px, unchanged
       for the three status entries. The row gap only ever applies once the bar wraps, which it
       could not do before flex-wrap was added below. */
    flex-wrap: wrap;
    gap: 8px 16px;
    /* Grow into the toolbar. .map-toolbar is a space-between flex row holding this legend and the
       (contextually hidden) zoom controls, so the legend was shrink-to-fit — 457px inside 934px.
       Without this there is no free space inside .map-legend, and the `margin-left: auto` that
       right-aligns the supporter-side pair has nothing to consume and silently does nothing.
       flex-grow rather than `flex: 1`, to leave flex-basis at auto so the content still sizes the
       box and the zoom controls keep their intrinsic width when shown. */
    flex-grow: 1;
    font-size: 12px;
    color: #5B6B7B;
}

.legend-item {
    display: flex;
    align-items: center;
    gap: 6px;
}

.legend-dot {
    width: 13px;
    height: 13px;
    border-radius: 50%;
    display: inline-block;
    /* Two of the three swatches carry a 1px border; without border-box they would
       measure 15px against the borderless one's 13px and the row would look ragged. */
    box-sizing: border-box;
}

/* Phase 88 (VIS-03, D-09): legend dots source their colors from the same CSS
   custom properties as the seats (set by SeatingRenderer.applyPlanColorConfig),
   converging the legend with the plan's configured palette. Hex fallbacks
   preserve today's rendering when no visual config is set.

   These only ever RESOLVED the fallbacks until venue-map.js's init() started
   scoping applyPlanColorConfig to .map-card: the properties were written on
   #venue-map-container, and .map-legend is a sibling of .venue-map-wrapper, not a
   descendant of the container. Custom properties inherit downward only, so a
   legend outside the subtree silently rendered the shipped defaults next to a map
   drawn in the vendor's own palette. If either page's markup is ever restructured,
   the legend and the map container must keep a COMMON ANCESTOR carrying these
   properties, or this reverts with no error anywhere. */
.legend-dot--available {
    background: var(--seat-available-fill, #E3EEFB);
    border: 1px solid var(--seat-available-stroke, #9DBFE8);
}

/* --seat-selected-fill first, --vendor-primary second: same precedence as
   seat-selection.js's BRAND_BLUE and venue-map.js's DOT_STYLES.selected, so all
   three "selected" surfaces resolve one colour. */
.legend-dot--selected {
    background: var(--seat-selected-fill, var(--vendor-primary, #1668C0));
}

/* D-28 (Phase 109): the fourth "Gezin" (family) legend dot — a hollow brand-500 ring rather
   than a solid fill, so it reads as "already yours" without competing with the true
   in-progress "Geselecteerd" colour above. Styled from the SAME custom property the seat rule
   below uses, so the legend and the map cannot drift apart. */
.legend-dot--family {
    background: #fff;
    border: 2px solid var(--tm-brand-500, #3C60A8);
}

/* Bordered to match the overview dot, which draws --seat-sold-stroke around the
   same fill — without it the Bezet swatch reads a shade lighter than the seats it
   stands for. */
.legend-dot--sold {
    background: var(--seat-sold-fill, #CBD2D9);
    border: 1px solid var(--seat-sold-stroke, #A8B4BE);
}

/* Quick task 260920-sjf — shape only; the colour lives on the per-side modifiers below.
   venue-map.js overwrites that colour via inline style once the layout fetch has delivered the
   plan's HomeSideColor / AwaySideColor (same convention as the tooltip dot and fallback-grid
   swatch). Inline style outranks a class selector, so the JS value always wins without
   !important. */
.legend-dot--side {
}

/* Pushes the supporter-side pair to the far right of the legend bar, away from the three
   availability-state entries, so the two kinds of information read as two groups rather than one
   list of five. Applied to the FIRST of the pair only: `margin-left: auto` eats all the free space
   before it, carrying everything after it to the right edge — the standard flex idiom, and it
   needs no wrapper element. Harmless on a non-team event, where neither entry is emitted at all.

   Once the bar wraps (see flex-wrap above) the pair lands on its own line, still right-aligned,
   which is why the wrap was added alongside this: without it, right-pushing two more entries
   would have risked horizontal overflow on a narrow viewport. */
.legend-item--side-lead {
    margin-left: auto;
}

/* These two carry the brand defaults ONLY to cover the window between first paint and the
   layout fetch returning. Since the operator decision of 2026-09-20 a team event renders both
   legend entries unhidden and unconditionally, so that window is now visible to users — without
   a fallback the dot would paint as nothing next to its label. They intentionally mirror the
   same two defaults venue-map.js falls back to (updateSupporterSideLegend), so a plan that has
   not set its own colours looks identical before and after the fetch and nothing flickers. */
.legend-dot--side-home {
    background: #3C60A8;
}

.legend-dot--side-away {
    background: #D4920A;
}

.map-zoom-controls {
    display: flex;
    align-items: center;
    gap: 6px;
}

.zoom-btn {
    width: 30px;
    height: 30px;
    border: 1px solid #D5DBE1;
    background: #fff;
    border-radius: 7px;
    font-size: 16px;
    font-weight: 700;
    color: #3E4A56;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    padding: 0;
    transition: background 0.15s, border-color 0.15s;
}

.zoom-btn:hover:not(:disabled) {
    background: #F0F4F9;
    border-color: var(--vendor-primary, #1668C0);
}

.zoom-btn:disabled {
    color: #C4CCD4;
    cursor: default;
}

.zoom-btn .bi {
    font-size: 13px;
}

/* "Overzicht" back button — labeled variant of the square zoom button */
.zoom-btn--overview {
    width: auto;
    padding: 0 12px;
    gap: 7px;
    font-size: 13px;
    font-weight: 600;
}

/* Info strip — active section name · availability · price line */
.map-info-strip {
    display: flex;
    align-items: center;
    gap: 12px;
    flex-wrap: wrap;
    padding: 11px 16px;
    background: #F4F8FD;
    border-bottom: 1px solid #EEF1F4;
}

.map-info-strip .info-section-name {
    font-weight: 800;
    font-size: 14px;
    color: #16202B;
}

.map-info-strip .info-avail {
    font-size: 12px;
    color: #2E8B57;
    font-weight: 600;
}

.map-info-strip .info-sep {
    color: #C4CCD4;
}

.map-info-strip .info-price {
    font-size: 12px;
    color: #5B6B7B;
}

/* Map body */
.venue-map-wrapper {
    position: relative;
    overflow: hidden;
}

/* D-01: the box is sized from the plan's own aspect ratio (published by venue-map.js
   as --venue-aspect) instead of a fixed pixel height, so the browser re-solves it on
   every viewport resize with zero JavaScript. The 16/9 fallback covers the window
   between first paint and VenueMap.init, and any payload with no canvas size.

   D-01b: full card WIDTH wins over fitting the viewport. A portrait plan in a
   landscape card cannot have both — filling the width needs height = width / ratio,
   which for a ~0.85 plan in a ~1045px card is ~1230px, taller than most viewports.
   Capping at viewport height would keep the page scroll-free but leave ~230px of dead
   gutter down each side, which is the complaint this change exists to fix. So the cap
   is deliberately NOT viewport-fitting: it is a runaway guard only, letting the map
   exceed the fold. That is safe here because .selection-rail is position: sticky —
   the cart panel tracks the user down a tall map instead of scrolling away. */
.seat-layout-grid .venue-map-container {
    height: auto;
    aspect-ratio: var(--venue-aspect, 16 / 9);
    max-height: 200vh;
    max-height: 200svh;
    min-height: 320px;
    /* When max-height binds, an aspect-ratio box with auto width preserves the ratio by
       shrinking its WIDTH rather than letterboxing — so the map would sit flush left with
       every pixel of leftover space dumped on the right. Centring splits that space
       evenly instead. Reachable at ordinary desktop sizes, not just freak window shapes:
       the cap binds whenever width > 2 x viewport-height x ratio, which an extreme
       portrait plan (ratio ~0.4) satisfies on a normal screen. */
    margin-inline: auto;
    /* venue-map.js retunes --venue-aspect to whatever viewBox is being shown, so the
       frame matches the selected section instead of stranding ~183px of blank above and
       below it. Easing it over the same 300ms as the viewBox animation makes the card
       read as focusing on the section rather than snapping to a new height. */
    transition: aspect-ratio 300ms ease-out;
    border: none;
    border-radius: 0;
    background: #F4F7FA;
}

@media (prefers-reduced-motion: reduce) {
    .seat-layout-grid .venue-map-container {
        transition: none;
    }
}

/* The container is already position: relative; overflow: hidden (shop.css). Filling it
   with an absolutely-positioned SVG means the map fills the aspect-solved box exactly,
   without depending on a percentage height resolving against an aspect-ratio-derived
   height. More specific than shop.css's `.venue-map-container svg` rule, so this wins
   on the Detail page without editing that shared rule. */
.seat-layout-grid .venue-map-container > svg {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* A SELECTED section gets its own, tighter budget. The overview cap above is
   deliberately permissive — a portrait venue should fill the card width even if that
   runs past the fold. A section inverts that: you are picking one seat out of a few
   hundred, so the whole section visible at once beats huge seats you have to scroll
   past. Without this, Sectie 4 (padded aspect ~0.4) wants 934 / 0.4 = 2335px and lands
   on a 1838px card showing ~5 rows at a time. Three-class specificity beats the base
   rule and the mobile media query alike. */
.seat-layout-grid .venue-map-container.venue-map-container--section {
    max-height: calc(100vh - 200px);
    max-height: calc(100svh - 200px);
}

/* D-04: escape hatch for the fallback card grid path — it draws no plan, so a
   fixed-aspect overflow:hidden box would clip the Bootstrap card rows. Three-class
   specificity beats both the desktop rule above and the mobile media-query rule
   below regardless of source order. */
.seat-layout-grid .venue-map-container.venue-map-container--fallback {
    aspect-ratio: auto;
    height: auto;
    max-height: none;
    min-height: 0;
    overflow: visible;
    background: transparent;
}

/* ===== Selection rail (desktop) ===== */

.selection-rail {
    position: sticky;
    top: 16px;
    max-height: 600px;
    background: #fff;
    border: 1px solid #E2E7EC;
    border-radius: 12px;
    overflow: hidden;
    display: flex;
    flex-direction: column;
    box-shadow: 0 8px 30px rgba(16, 40, 70, 0.12);
}

.rail-header {
    padding: 14px 16px;
    border-bottom: 1px solid #EEF1F4;
}

.rail-header-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.rail-title {
    font-weight: 800;
    font-size: 15px;
    color: #16202B;
}

.count-pill {
    background: #EAF1FB;
    color: var(--vendor-primary, #1668C0);
    font-weight: 800;
    font-size: 14px;
    border-radius: 20px;
    min-width: 28px;
    height: 26px;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0 9px;
}

/* Countdown pill */
.countdown-pill {
    margin-top: 11px;
    display: flex;
    align-items: center;
    gap: 8px;
    background: #FFF4E0;
    border: 1px solid #F3D89B;
    border-radius: 9px;
    padding: 9px 12px;
    font-size: 12px;
    font-weight: 600;
    color: #8A5D00;
}

.countdown-pill .countdown-timer {
    font-variant-numeric: tabular-nums;
    font-size: 17px;
    font-weight: 800;
    color: #B4790A;
    margin-left: auto;
    letter-spacing: 0.02em;
}

.rail-body {
    flex: 1;
    overflow-y: auto;
    padding: 10px 12px;
}

/* D-13 (Phase 109): the "Nog N leden toevoegen" member-add prompt, rendered inside
   _SubscriptionSummaryCard's rail body. Accent-coloured (a call-to-continue), never the
   brand-500 primary treatment the ordinary "Voeg toe aan winkelwagen" action below it uses. */
.member-prompt-container {
    margin: 10px 0;
}

.member-prompt-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 6px;
    width: 100%;
    background: color-mix(in srgb, var(--tm-accent-500, #D4920A) 12%, #fff);
    border: 1px solid var(--tm-accent-500, #D4920A);
    color: var(--tm-accent-500, #D4920A);
    border-radius: 9px;
    padding: 10px 12px;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: background 0.15s;
}

.member-prompt-btn:hover {
    background: color-mix(in srgb, var(--tm-accent-500, #D4920A) 20%, #fff);
}

.member-prompt-btn:disabled {
    opacity: 0.6;
    cursor: default;
}

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

.rail-empty {
    text-align: center;
    color: #94A0AC;
    font-size: 13px;
    padding: 26px 10px;
    line-height: 1.5;
}

/* ===== Seat card (shared: rail + bottom sheet) ===== */

.seat-card {
    padding: 10px 11px;
    border-radius: 9px;
    background: #F6F9FD;
    margin-bottom: 7px;
    list-style: none;
}

.seat-card-top {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-bottom: 8px;
}

.seat-card-label {
    font-size: 13px;
    font-weight: 700;
    color: #16202B;
}

.seat-card-remove {
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    border: 1px solid #E4A0A6;
    background: #fff;
    color: #D64550;
    border-radius: 50%;
    font-size: 15px;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
    transition: background 0.15s, color 0.15s;
}

.seat-card-remove:hover {
    background: #D64550;
    color: #fff;
}

.seat-card-bottom {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
}

.ticket-type-select {
    border: 1px solid #CFD6DD;
    border-radius: 7px;
    font-size: 12px;
    font-weight: 600;
    color: #3E4A56;
    padding: 5px 6px;
    background: #fff;
    cursor: pointer;
    max-width: 170px;
    flex: 1;
}

/* Secondary text on a standing card: the per-spot price next to the stepper, and the fallback
   tier label when a section exposes no selectable tiers. Same typography as .ticket-type-select
   so both card kinds read as one family. */
.seat-card-meta {
    font-size: 12px;
    font-weight: 600;
    color: #3E4A56;
    flex: 1;
    min-width: 0;
}

/* Quantity row on a standing card. A standing group is N spots on ONE card (a spot has no seat
   identity to name), so it gets the stepper a seat card has no use for. The control itself is
   allocation-buy.css's shipped .alloc-buy-qty-* — the same one the map's standing buy panel
   uses — scaled down here because the rail is ~300px wide and the shipped 36px buttons crowd
   it. Scoped to this row so the map panel's own stepper is untouched. */
.seat-card-qty {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    margin-top: 8px;
}

.seat-card-qty .alloc-buy-qty-btn {
    width: 28px;
    height: 28px;
    font-size: 1rem;
}

.seat-card-qty .alloc-buy-qty-value {
    font-size: 0.875rem;
    min-width: 1.5rem;
}

.seat-card-qty .seat-card-meta {
    flex: 0 0 auto;
    text-align: right;
}

.seat-card-price {
    font-size: 14px;
    font-weight: 800;
    color: #16202B;
    white-space: nowrap;
}

/* Rail footer */
.rail-footer {
    border-top: 1px solid #EEF1F4;
    padding: 14px 16px;
}

.rail-total {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-bottom: 12px;
}

.rail-total-label {
    font-size: 13px;
    color: #5B6B7B;
}

.rail-total-amount {
    font-size: 24px;
    font-weight: 800;
    color: #16202B;
}

.rail-checkout-btn {
    display: block;
    width: 100%;
    background: var(--vendor-primary, #1668C0);
    color: #fff;
    border: none;
    border-radius: 9px;
    padding: 13px;
    font-weight: 700;
    font-size: 14px;
    text-align: center;
    text-decoration: none;
    cursor: pointer;
}

.rail-checkout-btn:hover {
    color: #fff;
    filter: brightness(0.95);
}

/* Rail notice variant (sale not open) */
.selection-rail--notice {
    padding: 20px 16px;
    text-align: center;
}

.rail-notice-text {
    margin: 0;
    color: #5B6B7B;
    font-size: 13px;
}

/* ===== Mobile sticky bottom bar ===== */

.mobile-sticky-bar {
    display: none;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 40;
    background: #fff;
    border-top: 1px solid #E2E7EC;
    box-shadow: 0 -4px 16px rgba(16, 40, 70, 0.1);
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0px));
    align-items: center;
    gap: 12px;
}

.sticky-bar-info {
    flex: 1;
    min-width: 0;
}

.sticky-bar-total-row {
    display: flex;
    align-items: center;
    gap: 8px;
}

.sticky-bar-total {
    font-size: 20px;
    font-weight: 800;
    color: #16202B;
}

.sticky-bar-count {
    font-size: 12px;
    color: #5B6B7B;
}

.sticky-bar-expiry {
    font-size: 11px;
    font-weight: 700;
    color: #B4790A;
    margin-top: 1px;
}

.sticky-bar-btn {
    background: var(--vendor-primary, #1668C0);
    color: #fff;
    border: none;
    border-radius: 10px;
    padding: 13px 22px;
    font-weight: 700;
    font-size: 14px;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
}

.sticky-bar-btn:hover {
    color: #fff;
    filter: brightness(0.95);
}

/* ===== Mobile bottom sheet ===== */

.seat-bottom-sheet {
    position: fixed;
    bottom: 0;
    left: 0;
    right: 0;
    z-index: 1050;
    background: #fff;
    border-radius: 18px 18px 0 0;
    box-shadow: 0 -8px 26px rgba(16, 40, 70, 0.18);
    transform: translateY(100%);
    transition: transform 0.3s ease;
    max-height: 78vh;
    display: flex;
    flex-direction: column;
}

.seat-bottom-sheet.open {
    transform: translateY(0);
}

.bottom-sheet-drag-handle {
    width: 38px;
    height: 4px;
    background: #D8DEE4;
    border-radius: 2px;
    margin: 9px auto 4px;
    flex-shrink: 0;
    cursor: grab;
}

.bottom-sheet-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 16px 10px;
    border-bottom: 1px solid #EEF1F4;
    flex-shrink: 0;
}

.bottom-sheet-title {
    font-weight: 800;
    font-size: 15px;
    margin: 0;
    color: #16202B;
}

.bottom-sheet-avail {
    font-size: 12px;
    color: #2E8B57;
    font-weight: 600;
}

.bottom-sheet-close {
    width: 30px;
    height: 30px;
    flex: 0 0 auto;
    border: none;
    background: #F0F3F6;
    border-radius: 50%;
    font-size: 17px;
    color: #5B6B7B;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0;
    line-height: 1;
}

.bottom-sheet-close:hover {
    color: #16202B;
}

.bottom-sheet-body {
    overflow-y: auto;
    padding: 14px 16px;
    flex: 1;
    -webkit-overflow-scrolling: touch;
}

.sheet-seat-list {
    list-style: none;
    padding: 0;
    margin: 14px 0 0;
}

.bottom-sheet-footer {
    border-top: 1px solid #EEF1F4;
    padding: 11px 16px;
    flex-shrink: 0;
}

.bottom-sheet-done {
    width: 100%;
    background: #EAF1FB;
    color: var(--vendor-primary, #1668C0);
    border: none;
    border-radius: 9px;
    padding: 11px;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
}

.bottom-sheet-overlay {
    position: fixed;
    inset: 0;
    z-index: 1040;
    background: rgba(16, 40, 70, 0.4);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.3s ease;
}

.bottom-sheet-overlay.visible {
    opacity: 1;
    pointer-events: auto;
}

/* ===== Seat grid (bottom sheet + zoomed section) ===== */

.bottom-sheet-seat-grid {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.grid-row {
    display: flex;
    align-items: center;
    gap: 7px;
}

.grid-row-label {
    width: 18px;
    font-size: 12px;
    font-weight: 700;
    color: #5B6B7B;
    text-align: right;
    flex-shrink: 0;
}

.grid-seats {
    display: flex;
    flex-wrap: wrap;
    gap: 4px;
}

.grid-seat {
    width: 27px;
    height: 27px;
    flex: 0 0 auto;
    border-radius: 6px;
    font-size: 11px;
    font-weight: 600;
    cursor: pointer;
    transition: transform 0.1s, background 0.15s;
    display: flex;
    align-items: center;
    justify-content: center;
}

.grid-seat:active {
    transform: scale(0.92);
}

.grid-seat.seat-available {
    background: #E9F1FC;
    color: var(--vendor-primary, #1668C0);
    border: 1px solid #C4D8F2;
}

.grid-seat.seat-available:hover {
    background: var(--vendor-primary, #1668C0);
    color: #fff;
}

.grid-seat.seat-mine {
    background: var(--vendor-primary, #1668C0);
    color: #fff;
    border: 1px solid #0F4E92;
}

.grid-seat.seat-unavailable {
    background: #EEF1F4;
    color: #B0B8C1;
    border: 1px solid #DDE1E6;
    cursor: not-allowed;
}

.grid-seat.seat-preview {
    background: rgba(22, 104, 192, 0.35);
    color: var(--vendor-primary, #1668C0);
    border: 1px solid var(--vendor-primary, #1668C0);
}

/* ===== Countdown warning state ===== */

.countdown-warning .countdown-timer {
    animation: countdown-pulse 2s ease-in-out infinite;
}

@keyframes countdown-pulse {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.55; }
}

/* ===== Toast Notifications =====
 *
 * The base rules moved to css/toast.css, which _Layout loads on EVERY page. They lived here, and
 * only here, while cart.js also depended on them ("Reuse seat-selection toast styles") from a
 * page that never loads this file — so every cart-page toast was invisible. One home, loaded
 * globally, fixes that class of bug rather than the one instance.
 *
 * Only the page-specific mobile override remains, further down in the 767.98px media query:
 * this page has a sticky seat bar the toast has to clear, which is nothing the other pages need.
 */

/* ===== SVG seat transition (SignalR updates) ===== */

[data-seat-id] {
    transition: fill 300ms ease-in-out;
}

/* D-28 (Phase 109): every seat the family already holds (the parent plus any member
   reserved earlier in this same add-flow), painted while picking the next member's seat —
   the brand-500 outline variant of the "Geselecteerd" dot, reusing SeatingRenderer's own
   seat elements (no new renderer plumbing — this file only adds the attribute + this rule).
   `!important` on fill is required: SeatingRenderer.setSeatColor writes an INLINE
   `style.fill` on every seat on each repaint (mine/available/unavailable), which otherwise
   always outranks a plain CSS rule regardless of selector specificity. `stroke` needs no
   `!important` — it is never set as an inline style, only ever a presentation attribute,
   which a plain CSS rule already beats. */
[data-seat-id][data-seat-family="true"] {
    fill: #fff !important;
    stroke: var(--tm-brand-500, #3C60A8);
    stroke-width: 2px;
}

/* Same family paint state on the mobile bottom-sheet grid — a `<button>`, not an SVG shape,
   so background/border rather than fill/stroke. */
.grid-seat[data-seat-family="true"] {
    background: #fff;
    color: var(--tm-brand-500, #3C60A8);
    border: 2px solid var(--tm-brand-500, #3C60A8);
}

/* ===== Single-section zoom panel (desktop, rendered by venue-map.js) ===== */

.section-zoom-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    padding: 10px 14px;
}

.section-zoom-back {
    border: 1px solid #CFD6DD;
    background: #fff;
    border-radius: 7px;
    padding: 6px 12px;
    font-size: 12px;
    font-weight: 600;
    color: #3E4A56;
    cursor: pointer;
}

.section-zoom-back:hover {
    border-color: var(--vendor-primary, #1668C0);
}

/* ===== Responsive ===== */

@media (max-width: 767.98px) {
    .seat-layout-grid {
        grid-template-columns: 1fr;
        gap: 12px;
    }

    /* Rail is replaced by the sticky bar + bottom sheet on mobile */
    .selection-rail {
        display: none;
    }

    /* height: auto and aspect-ratio cascade through from the desktop rule above
       unchanged (equal specificity, later in the file overrides only the
       properties it redeclares). Same D-01b rule as desktop: the cap is a runaway
       guard, not a viewport fit. It rarely binds here anyway — the card is narrow on
       a phone, so width / ratio lands around 400px for a typical plan. Lower floor
       than desktop's 320px so a wide landscape plan does not get needless letterbox
       padding on a small screen. */
    .seat-layout-grid .venue-map-container {
        max-height: 200vh;
        max-height: 200svh;
        min-height: 260px;
    }

    .mobile-sticky-bar {
        display: flex;
    }

    /* Keep the map from hiding under the fixed sticky bar */
    .event-detail--map-first {
        padding-bottom: 92px;
    }

    .seat-toast-container {
        top: auto;
        bottom: 6rem;
        right: 0.5rem;
        left: 0.5rem;
    }

    .seat-toast {
        max-width: 100%;
    }
}

/* Hide mobile-only surfaces on desktop */
@media (min-width: 768px) {
    .seat-bottom-sheet,
    .bottom-sheet-overlay {
        display: none;
    }
}
