/* ============================================================
   enhancements.css — YallaTonight Professional Polish Layer
   Loaded LAST (after premium.css) so it can refine the final paint.

   Purpose: small, additive, theme-aware fixes & polish that close
   real gaps in the existing design system. Every rule here is
   reversible by removing the <link> in components/header.php.

   Theme support:
     • Light (default, theme-light.v2.css)
     • Night (html.night, premium.css)
     • RTL (html[dir="rtl"]) and reduced-motion safe.
   ============================================================ */

/* ------------------------------------------------------------
   1. FIX — anchor links hidden under the sticky navbar.
   The navbar is position:sticky (~64–72px tall). Without
   scroll-padding the browser scrolls in-page #anchors to the
   very top, leaving the heading tucked behind the bar.
   ------------------------------------------------------------ */
html {
    scroll-padding-top: 90px;
}
@media (max-width: 1024px) {
    html { scroll-padding-top: 76px; }
}

/* ------------------------------------------------------------
   2. FIX (a11y) — guard smooth scrolling for users who request
   reduced motion. style.css sets `html { scroll-behavior: smooth }`
   unconditionally, which can trigger vestibular discomfort.
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto !important; }
    * , *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ------------------------------------------------------------
   3. POLISH — crisper text rendering across the site.
   ------------------------------------------------------------ */
body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* ------------------------------------------------------------
   4. FIX (UX) — consistent disabled state for buttons & inputs.
   The codebase had no global :disabled styling, so disabled
   controls looked identical to active ones (misleading).
   ------------------------------------------------------------ */
button:disabled,
button[disabled],
.btn-primary:disabled,
.btn-solid:disabled,
.nav-cta-btn:disabled,
input:disabled,
select:disabled,
textarea:disabled,
[aria-disabled="true"] {
    opacity: 0.55 !important;
    cursor: not-allowed !important;
    filter: grayscale(0.15);
    box-shadow: none !important;
    transform: none !important;
}
/* A spinner-friendly "busy" state for async form submits */
button.is-loading {
    pointer-events: none;
    opacity: 0.7;
}

/* ------------------------------------------------------------
   5. POLISH — tactile press feedback on primary actions.
   A subtle press makes buttons feel responsive (additive: only
   touches :active, leaves existing :hover rules intact).
   ------------------------------------------------------------ */
.nav-cta-btn:active,
.btn-primary:active,
.btn-solid:active,
.hero-search-btn:active,
button.primary:active {
    transform: translateY(1px) scale(0.99);
    transition: transform 0.08s ease;
}

/* ------------------------------------------------------------
   6. POLISH — refined, theme-aware text selection.
   Light: violet wash with dark text. Night: brighter for contrast.
   ------------------------------------------------------------ */
::selection {
    background: rgba(124, 58, 237, 0.22);
    color: #1c1c1c;
    -webkit-text-fill-color: #1c1c1c;
}
html.night ::selection {
    background: rgba(167, 139, 250, 0.35);
    color: #ffffff;
    -webkit-text-fill-color: #ffffff;
}

/* ------------------------------------------------------------
   7. POLISH — theme-aware scrollbar.
   Light gets a soft track; night gets a dark track. Thumb keeps
   the brand violet in both. (Firefox via scrollbar-color.)
   ------------------------------------------------------------ */
html {
    scrollbar-width: thin;
    scrollbar-color: rgba(124, 58, 237, 0.45) transparent;
}
::-webkit-scrollbar { width: 9px; height: 9px; }
::-webkit-scrollbar-track { background: #f1f1f4; }
::-webkit-scrollbar-thumb {
    background: rgba(124, 58, 237, 0.40);
    border-radius: 10px;
    border: 2px solid #f1f1f4;
}
::-webkit-scrollbar-thumb:hover { background: rgba(124, 58, 237, 0.70); }
html.night ::-webkit-scrollbar-track { background: #0d0b1a; }
html.night ::-webkit-scrollbar-thumb {
    background: rgba(167, 139, 250, 0.45);
    border-color: #0d0b1a;
}
html.night ::-webkit-scrollbar-thumb:hover { background: rgba(167, 139, 250, 0.80); }
html.night { scrollbar-color: rgba(167, 139, 250, 0.50) transparent; }

/* ------------------------------------------------------------
   8. POLISH — calmer mobile tap highlight (default is a harsh
   grey/blue box on iOS/Android).
   ------------------------------------------------------------ */
a, button, [role="button"], input, select, textarea,
.event-card, .category-card, .nav-cta-btn {
    -webkit-tap-highlight-color: rgba(124, 58, 237, 0.12);
}

/* ------------------------------------------------------------
   9. POLISH — stronger, theme-aware keyboard focus ring on the
   primary CTAs (keyboard users only). Complements the generic
   ring in premium.css with a branded halo on the gold buttons.
   ------------------------------------------------------------ */
.nav-cta-btn:focus-visible,
.btn-primary:focus-visible,
.hero-search-btn:focus-visible {
    outline: 3px solid rgba(124, 58, 237, 0.55);
    outline-offset: 3px;
    box-shadow: 0 0 0 6px rgba(124, 58, 237, 0.18);
}
html.night .nav-cta-btn:focus-visible,
html.night .btn-primary:focus-visible,
html.night .hero-search-btn:focus-visible {
    outline-color: rgba(167, 139, 250, 0.75);
    box-shadow: 0 0 0 6px rgba(167, 139, 250, 0.22);
}

/* ------------------------------------------------------------
   10. POLISH — prevent media overflow on small screens (safety
   net for inline-styled images/iframes/videos across views).
   ------------------------------------------------------------ */
img, svg, video, iframe { max-width: 100%; }

/* ------------------------------------------------------------
   11. FEATURE — `.skip-to-content` link for keyboard / screen
   reader users. Visually hidden until focused. Pairs with an
   optional id="main" target added in header.php.
   ------------------------------------------------------------ */
.skip-to-content {
    position: fixed;
    top: -60px;
    inset-inline-start: 16px;
    z-index: 100000;
    background: #7C3AED;
    color: #fff;
    padding: 10px 18px;
    border-radius: 0 0 12px 12px;
    font-weight: 700;
    text-decoration: none;
    transition: top 0.2s ease;
}
.skip-to-content:focus-visible {
    top: 0;
    outline: 3px solid rgba(255, 255, 255, 0.85);
    outline-offset: 2px;
}

/* ------------------------------------------------------------
   12. FEATURE — site-wide clean print / "Save as PDF" output.
   Strips interactive chrome (nav, footer, chat bubble, install
   banner, bottom bar, scroll-top, cursor effects), forces black
   text on white, expands links, and avoids awkward card breaks.
   Page-specific styles (e.g. invoice.php) still win where defined.
   ------------------------------------------------------------ */
@media print {
    /* Always print on a clean light canvas regardless of night mode */
    html, html.night, body {
        background: #ffffff !important;
        background-image: none !important;
        color: #000000 !important;
    }
    body { overflow: visible !important; }

    /* Hide non-content chrome & overlays */
    .site-navbar,
    .site-footer,
    .mobile-bottom-bar,
    .ai-chat-widget,
    .mobile-nav-overlay,
    #pwaInstallBanner,
    .premium-scroll-top,
    .skip-to-content,
    .theme-toggle,
    [data-no-print],
    .no-print {
        display: none !important;
    }

    /* Crisp ink: drop heavy shadows, glows and dark fills on surfaces */
    .card, .glass-card, .event-card, .venue-card, .pricing-card,
    .panel, .summary-card, .info-card, .ticket-card, [class*="glass"] {
        box-shadow: none !important;
        border: 1px solid #cccccc !important;
        background: #ffffff !important;
        color: #000000 !important;
    }

    /* Make link targets useful on paper */
    a { color: #000000 !important; text-decoration: underline; }
    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: 0.8em;
        color: #555;
        word-break: break-all;
    }
    /* …but don't dump URLs for in-page anchors, JS or tel/mailto chips */
    a[href^="#"]::after,
    a[href^="javascript"]::after,
    a[href^="mailto"]::after,
    a[href^="tel"]::after { content: ""; }

    /* Keep cards & sections from splitting mid-element across pages */
    .card, .event-card, .pricing-card, .ticket-card,
    .summary-card, table, figure, img { break-inside: avoid; page-break-inside: avoid; }
    h1, h2, h3, h4 { break-after: avoid; page-break-after: avoid; }
}

/* ------------------------------------------------------------
   12b. Bottom-floating stack — de-clutter on phones.
   The mobile bottom nav (.mobile-bottom-bar) appears < 768px and
   reserves ~80px at the page bottom. Lift the dismissible PWA install
   banner clear of it, and hide the social-proof ticker on phones —
   the screen is too narrow to carry the nav + banner + a rotating
   toast at once. Desktop is unaffected. (The duplicate "Install app"
   button #pmInstallBtn was removed in premium.js → initInstall.)
   ------------------------------------------------------------ */
@media (max-width: 768px) {
    #pwaInstallBanner { bottom: 90px !important; }
    .booking-ticker-container { display: none !important; }

    /* FAB anti-collision stack (Claude): the scroll-to-top button sits ABOVE the
       AI-concierge launcher on the inline-end (right) side. Previously both lived
       in the bottom-right corner and overlapped each other + the Profile tab of
       the mobile bottom bar. Concierge bottom = calc(74px + safe); this clears it
       by the launcher height + a gap. Forced to the right in RTL too so it never
       lands on top of the bottom-left support launcher. */
    .premium-scroll-top,
    html[dir="rtl"] .premium-scroll-top {
        /* !important is needed to beat premium.css's themed
           `html[dir="rtl"] .premium-scroll-top { right: auto !important }`. */
        left: auto !important;
        right: 14px !important;
        bottom: calc(130px + env(safe-area-inset-bottom)) !important;
    }
}

/* ------------------------------------------------------------
   13. POLISH (UX) — inline form validation feedback.
   `:user-invalid` only styles a field AFTER the user has
   interacted with it (no red borders on a pristine form), so
   it's friendly. Pairs with the existing focus styles.
   ------------------------------------------------------------ */
input:user-invalid,
select:user-invalid,
textarea:user-invalid {
    border-color: #ef4444 !important;
    box-shadow: 0 0 0 2px rgba(239, 68, 68, 0.18) !important;
}
/* Green "valid" confirmation only on fields that actually have a
   constraint (required / email / tel / url / pattern) — avoids
   greening every plain text box the user happens to touch. */
input[required]:user-valid,
input[type="email"]:user-valid,
input[type="tel"]:user-valid,
input[type="url"]:user-valid,
input[pattern]:user-valid,
select[required]:user-valid,
textarea[required]:user-valid {
    border-color: #10b981 !important;
}

/* ------------------------------------------------------------
   14. FIX — `.no-results` (search "No events found") had ZERO
   CSS, so it rendered as unstyled, left-aligned default text.
   Give it the same polished, centred treatment as .empty-state.
   Theme-aware (light + night).
   ------------------------------------------------------------ */
.no-results {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 14px;
    padding: clamp(48px, 7vw, 80px) 20px;
    max-width: 520px;
    margin-inline: auto;
}
/* The wrapping <div> around the icon → soft violet halo circle */
.no-results > div {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 88px;
    height: 88px;
    border-radius: 50%;
    background: radial-gradient(circle at 30% 25%,
                rgba(139, 92, 246, 0.18),
                rgba(124, 58, 237, 0.10) 70%);
    border: 1px solid rgba(124, 58, 237, 0.16);
    box-shadow: 0 10px 30px -12px rgba(124, 58, 237, 0.45);
    margin: 0 auto 4px;
    animation: ytEmptyFloat 4.5s ease-in-out infinite;
}
.no-results > div > i {
    font-size: 2.2rem;
    color: #7C3AED;
    line-height: 1;
}
.no-results h2 {
    font-family: var(--font-heading, 'Space Grotesk', sans-serif);
    font-size: clamp(1.3rem, 3vw, 1.7rem);
    font-weight: 700;
    color: #1c1c1c;
    margin: 4px 0 0;
}
.no-results p {
    font-size: 0.97rem;
    line-height: 1.65;
    color: #5a5a5a;
    max-width: 420px;
    margin: 0 auto;
}
html.night .no-results h2 { color: #f4f4f6; }
html.night .no-results p { color: #b6b9c6; }
html.night .no-results > div > i { color: #a78bfa; }

@keyframes ytEmptyFloat {
    0%, 100% { transform: translateY(0); }
    50% { transform: translateY(-8px); }
}
@media (prefers-reduced-motion: reduce) {
    .no-results > div { animation: none; }
}

/* ------------------------------------------------------------
   15. FIX (a11y / WCAG AA) — faint text contrast on light theme.
   theme-light set `--text-dim: #9a9a9a` (~2.85:1 on white → fails
   AA) and placeholders at #9a9a9a. Darken to AA-compliant values
   in the LIGHT theme only. `html.night` keeps premium.css's own
   dim token (higher specificity), so night mode is untouched.
   ------------------------------------------------------------ */
:root {
    --text-dim: #6b6b6b;   /* ~5.3:1 on #fff — passes AA for normal text */
}
input::placeholder,
textarea::placeholder {
    color: #767676 !important;   /* ~4.54:1 on #fff — AA */
    opacity: 1;                  /* Firefox lowers placeholder opacity by default */
}
html.night input::placeholder,
html.night textarea::placeholder {
    color: #8a8fa3 !important;   /* readable on dark surfaces */
}

/* ------------------------------------------------------------
   16. FEATURE — unified "submitting" spinner on form buttons.
   Styling here; behaviour wired by /js/enhancements.js, which adds
   `.is-loading` to a form's submit button on submit. Opt out with
   data-no-loading on the <form>.
   ------------------------------------------------------------ */
button.is-loading,
.btn-primary.is-loading,
.nav-cta-btn.is-loading,
input[type="submit"].is-loading {
    position: relative;
    color: transparent !important;
    -webkit-text-fill-color: transparent !important;
    pointer-events: none;
    cursor: progress;
}
button.is-loading > *,
.btn-primary.is-loading > * { visibility: hidden; }
button.is-loading::after,
.btn-primary.is-loading::after,
.nav-cta-btn.is-loading::after,
input[type="submit"].is-loading::after {
    content: "";
    position: absolute;
    top: 50%;
    inset-inline-start: 50%;
    width: 18px;
    height: 18px;
    margin-top: -9px;
    margin-inline-start: -9px;
    border: 2px solid currentColor;
    border-top-color: transparent;
    border-radius: 50%;
    color: #ffffff;
    -webkit-text-fill-color: #ffffff;
    animation: ytBtnSpin 0.6s linear infinite;
}
@keyframes ytBtnSpin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
    button.is-loading::after,
    .btn-primary.is-loading::after,
    .nav-cta-btn.is-loading::after,
    input[type="submit"].is-loading::after { animation-duration: 1.4s; }
}

/* ------------------------------------------------------------
   17. POLISH (mobile) — comfortable tap targets (>= 44px, per
   Apple HIG / WCAG 2.5.5) on the main actionable controls, plus
   a touch of breathing room on small screens.
   ------------------------------------------------------------ */
@media (max-width: 600px) {
    .btn-book,
    .btn-primary,
    .btn-solid,
    .nav-cta-btn,
    .btn-back,
    .btn-clear-filters,
    .lang-toggle-btn,
    button[type="submit"],
    input[type="submit"] {
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
    /* Footer social & icon buttons → full 44px touch area */
    .site-footer .footer-social a,
    .theme-toggle {
        min-width: 44px;
        min-height: 44px;
    }
    /* A little more vertical rhythm between stacked cards */
    .events-grid,
    .search-results-grid,
    .results-grid { gap: 18px; }
}

/* ------------------------------------------------------------
   18. POLISH — smooth cross-page (MPA) view transitions.
   Progressive enhancement: Chromium fades between full-page
   navigations; unsupported browsers ignore the at-rule entirely.
   Disabled under reduced-motion.
   ------------------------------------------------------------ */
@view-transition { navigation: auto; }
@media (prefers-reduced-motion: reduce) {
    @view-transition { navigation: none; }
}
::view-transition-old(root),
::view-transition-new(root) {
    animation-duration: 0.22s;
}

/* ------------------------------------------------------------
   19. POLISH — clearer keyboard focus inside the dropdown menus
   and a soft glow on the hero search form when any field is
   focused (`:focus-within`), so the active search stands out.
   ------------------------------------------------------------ */
.lang-dropdown-menu a:focus-visible {
    outline: 2px solid rgba(124, 58, 237, 0.6);
    outline-offset: -2px;
    background: rgba(124, 58, 237, 0.10);
}
.hero-search-form:focus-within {
    box-shadow: 0 12px 44px rgba(0, 0, 0, 0.14),
                0 0 0 2px rgba(124, 58, 237, 0.35) !important;
}

/* ------------------------------------------------------------
   20. A11y — keyboard focus ring on interactive cards.
   Card grids are reachable by keyboard (links inside), but the
   card itself gave no focus cue. Add a branded ring when a card
   (or its inner link) receives keyboard focus.
   ------------------------------------------------------------ */
.event-card:focus-visible,
.event-card a:focus-visible,
.category-card:focus-visible,
.category-card a:focus-visible,
.liquid-glass-card:focus-visible,
.venue-card:focus-visible {
    outline: 3px solid rgba(124, 58, 237, 0.55);
    outline-offset: 3px;
    border-radius: 16px;
}
html.night .event-card:focus-visible,
html.night .category-card:focus-visible,
html.night .liquid-glass-card:focus-visible,
html.night .venue-card:focus-visible {
    outline-color: rgba(167, 139, 250, 0.75);
}

/* ------------------------------------------------------------
   21. A11y — Windows High Contrast / forced-colors support.
   Keep focus indicators and the gradient-text brand visible when
   the OS overrides colours (otherwise focus rings can vanish and
   `-webkit-text-fill-color: transparent` headings disappear).
   ------------------------------------------------------------ */
@media (forced-colors: active) {
    a:focus-visible,
    button:focus-visible,
    input:focus-visible,
    select:focus-visible,
    textarea:focus-visible,
    .nav-cta-btn:focus-visible,
    .event-card:focus-visible,
    .category-card:focus-visible {
        outline: 3px solid Highlight !important;
        outline-offset: 2px;
    }
    /* Gradient-clipped text would be invisible — restore system colour */
    .grad-text, .yt-grad-text, .text-gradient, .gradient-text,
    .shimmer-text, .footer-brand-name {
        -webkit-text-fill-color: currentColor !important;
        color: CanvasText !important;
    }
    /* Ensure disabled controls are still perceivable */
    button:disabled, input:disabled, select:disabled, textarea:disabled {
        opacity: 1 !important;
        color: GrayText !important;
    }
}

/* ------------------------------------------------------------
   22. POLISH — tidy the clunky default WebKit search "X" cancel
   button. (Number-field spinners left untouched so quantity
   steppers keep their native arrows.)
   ------------------------------------------------------------ */
input[type="search"]::-webkit-search-cancel-button,
input[type="search"]::-webkit-search-decoration {
    -webkit-appearance: none;
    appearance: none;
}

/* ------------------------------------------------------------
   23. POLISH — professional typography niceties (progressive;
   ignored by browsers that don't support the property).
   - balance headings so they don't leave a lonely last word.
   - `pretty` paragraphs to avoid orphans/widows in body copy.
   - break overly-long unbreakable strings (URLs, ref codes,
     emails) so they never overflow their card on mobile.
   ------------------------------------------------------------ */
h1, h2, h3,
.section-title, .hero-content h1, .error-title {
    text-wrap: balance;
}
p, li, blockquote, figcaption, .footer-desc, .event-card p {
    text-wrap: pretty;
}
p, li, dd, .footer-desc, .ticket-info h4, .event-card p,
.no-results p, .empty-state p {
    overflow-wrap: break-word;
    word-break: break-word;
}

/* ============================================================
   BATCH 4 — page-level polish (checkout, event detail,
   dashboards). Theme-aware; targets existing class names only.
   ============================================================ */

/* ------------------------------------------------------------
   24. CHECKOUT — clearer payment-method selection.
   The radio "cards" gave weak feedback on which is chosen.
   Use :has() to highlight the selected card; hover/focus too.
   ------------------------------------------------------------ */
.payment-method-card {
    transition: border-color 0.2s ease, box-shadow 0.2s ease,
                background 0.2s ease, transform 0.08s ease;
    cursor: pointer;
}
.payment-method-card:hover {
    border-color: rgba(124, 58, 237, 0.45) !important;
}
.payment-method-card:has(input:checked) {
    border-color: #7C3AED !important;
    background: rgba(124, 58, 237, 0.06) !important;
    box-shadow: 0 0 0 2px rgba(124, 58, 237, 0.25) !important;
}
.payment-method-card:has(input:focus-visible) {
    outline: 3px solid rgba(124, 58, 237, 0.5);
    outline-offset: 2px;
}
.payment-method-card:active { transform: translateY(1px); }

/* Make the checkout error / sold-out notices stand out */
.checkout-page .error-box,
.checkout-page .soldout-box {
    border-inline-start: 4px solid #ef4444;
}

/* ------------------------------------------------------------
   25. EVENT DETAIL — control states + mobile sticky Book bar.
   ------------------------------------------------------------ */
/* Quantity & ticket-type controls: clearer interactive feedback */
.ed-qty-btn { transition: background 0.15s ease, transform 0.08s ease; }
.ed-qty-btn:hover { background: rgba(124, 58, 237, 0.18) !important; }
.ed-qty-btn:active { transform: scale(0.92); }
.ed-type-btn { transition: all 0.18s ease; }
.ed-type-btn.active {
    box-shadow: inset 0 0 0 1px rgba(124, 58, 237, 0.6);
}

/* The desktop booking card tracks the scroll (if not already sticky) */
@media (min-width: 993px) {
    .ed-booking-card { position: sticky; top: 96px; }
}

/* Mobile sticky Book bar (markup in event_detail.php).
   A3.1 — hidden until the shopper scrolls down; JS toggles `.is-visible`. */
.ed-mobile-book-bar { display: none; }
@media (max-width: 768px) {
    .ed-mobile-book-bar {
        display: flex;
        position: fixed;
        left: 0; right: 0;
        /* Sit directly above the global mobile bottom nav (~65px tall) */
        bottom: calc(65px + env(safe-area-inset-bottom));
        z-index: 999;
        align-items: center;
        justify-content: space-between;
        gap: 14px;
        padding: 12px 16px;
        background: rgba(255, 255, 255, 0.97);
        backdrop-filter: blur(14px);
        -webkit-backdrop-filter: blur(14px);
        border-top: 1px solid #e9e9ec;
        box-shadow: 0 -6px 24px rgba(0, 0, 0, 0.12);
        /* Off-screen until revealed (appears on scroll). */
        transform: translateY(130%);
        opacity: 0;
        visibility: hidden;
        pointer-events: none;
        transition: transform .32s cubic-bezier(.16, 1, .3, 1), opacity .32s ease, visibility .32s;
    }
    .ed-mobile-book-bar.is-visible {
        transform: translateY(0);
        opacity: 1;
        visibility: visible;
        pointer-events: auto;
    }
    html.night .ed-mobile-book-bar {
        background: rgba(13, 11, 26, 0.97);
        border-top-color: rgba(167, 139, 250, 0.22);
    }
    .ed-mbb-price { display: flex; flex-direction: column; line-height: 1.2; min-width: 0; }
    .ed-mbb-label { font-size: 0.7rem; color: #6b6b6b; text-transform: uppercase; letter-spacing: 0.5px; }
    html.night .ed-mbb-label { color: #b6b9c6; }
    .ed-mbb-total { font-size: 1.15rem; font-weight: 800; color: #1c1c1c; font-family: var(--font-heading, sans-serif); }
    html.night .ed-mbb-total { color: #f4f4f6; }
    .ed-mbb-btn {
        flex: 0 0 auto;
        margin: 0 !important;
        white-space: nowrap;
        min-height: 48px;
        display: inline-flex;
        align-items: center;
        gap: 8px;
        padding: 0 22px !important;
    }
    /* Reserve space so the sticky bar never hides page content
       (global body padding already clears the bottom nav). */
    .ed-page { padding-bottom: 96px; }
}
@media (prefers-reduced-motion: reduce) {
    .ed-mobile-book-bar { transition: none; }
}

/* ------------------------------------------------------------
   26. DASHBOARDS — stat cards & list items polish.
   ------------------------------------------------------------ */
.p-stat-card {
    transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.p-stat-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 12px 30px -14px rgba(124, 58, 237, 0.4);
}
.p-stat-value { font-variant-numeric: tabular-nums; letter-spacing: -0.01em; }
.notif-item, .ticket-item, .insight-item {
    transition: background 0.18s ease;
}
.notif-item:hover, .ticket-item:hover { background: rgba(124, 58, 237, 0.05); }
/* Unread notifications get a clear accent marker */
.notif-unread { position: relative; }
.notif-unread::before {
    content: "";
    position: absolute;
    inset-inline-start: 0; top: 0; bottom: 0;
    width: 3px;
    background: #7C3AED;
    border-radius: 3px;
}

/* ------------------------------------------------------------
   27. DASHBOARDS — let wide tables scroll on small screens
   instead of overflowing the viewport. Scoped to dashboard /
   partner containers so it never touches layout tables.
   ------------------------------------------------------------ */
@media (max-width: 768px) {
    .dash-container table,
    .p-stats-grid + * table,
    .chart-card table {
        display: block;
        width: 100%;
        overflow-x: auto;
        -webkit-overflow-scrolling: touch;
        white-space: nowrap;
    }
}

/* ============================================================
   28. DAY-MODE FIX — premium "Apple-Wallet" ticket cards.
   These cards (.apple-wallet-card / VIP .vip-obsidian-card) are
   hard-coded dark in the page's own <style>, so in day mode they
   appeared as dark cards floating on the light dashboard. Convert
   them (and their dark inner bits: header, divider notches,
   timeline track/dots, white labels) to a clean light treatment.
   `html:not(.night)` keeps NIGHT mode untouched; the higher
   specificity (vs the page's single-class inline rules) lets these
   win regardless of stylesheet order. White text inside uses theme
   vars (var(--text)…) which are already dark in day, so most inner
   copy needs no change.
   ------------------------------------------------------------ */
html:not(.night) .apple-wallet-card,
html:not(.night) .vip-obsidian-card:not(.loyalty-card) {
    background: #ffffff !important;
    border: 1px solid rgba(124, 58, 237, 0.18) !important;
    box-shadow: 0 6px 22px rgba(17, 12, 34, 0.08) !important;
    color: #1c1c1c !important;
}
/* Header divider + title */
html:not(.night) .apple-wallet-card .wallet-header,
html:not(.night) .vip-obsidian-card:not(.loyalty-card) .wallet-header {
    border-bottom-color: #ececec !important;
}
html:not(.night) .apple-wallet-card .wallet-header h3,
html:not(.night) .vip-obsidian-card:not(.loyalty-card) .wallet-header h3 {
    color: #1c1c1c !important;
}
/* Tear-off dashed divider + its punch-hole notches (were #000) */
html:not(.night) .apple-wallet-card .wallet-divider {
    border-top-color: #e3e3e8 !important;
}
html:not(.night) .apple-wallet-card .wallet-divider::before,
html:not(.night) .apple-wallet-card .wallet-divider::after {
    background: #f4f4f6 !important;
}
/* Journey timeline: track, inactive dots, active label */
html:not(.night) .apple-wallet-card .timeline-line {
    background: rgba(0, 0, 0, 0.10) !important;
}
html:not(.night) .apple-wallet-card .timeline-dot {
    background: #efedf6 !important;
    border-color: rgba(124, 58, 237, 0.22) !important;
    color: #6b6b6b !important;
}
html:not(.night) .apple-wallet-card .timeline-node.active .timeline-label {
    color: #1c1c1c !important;
}
html:not(.night) .apple-wallet-card .timeline-node.active .timeline-dot {
    color: #ffffff !important;   /* white glyph on the violet active dot */
}
/* The VIP foil-shimmer overlay uses color-dodge — bright on white,
   so drop it in day mode. */
html:not(.night) .vip-obsidian-card:not(.loyalty-card)::before {
    opacity: 0 !important;
}

/* ------------------------------------------------------------
   29. DAY-MODE FIX — hero search box.
   The homepage forces the search card dark (rgba(6,4,18,.92)) with
   white text via `.home-search-inner …` inline rules, so in day mode
   it stayed dark instead of the intended clean white Airbnb-style
   card. Restore the light card in day; NIGHT keeps the dark look.
   Selectors out-specify the page's inline rules so order doesn't
   matter.
   ------------------------------------------------------------ */
html:not(.night) .home-search-inner .hero-search-form {
    background: #ffffff !important;
    border-color: #ececec !important;
    box-shadow: 0 18px 50px rgba(17, 12, 34, 0.18),
                0 0 0 1px rgba(0, 0, 0, 0.02) !important;
}
html:not(.night) .home-search-inner .search-field label {
    color: #717171 !important;   /* was light violet — unreadable on white */
}
html:not(.night) .home-search-inner .search-field input,
html:not(.night) .home-search-inner .search-field select {
    color: #1c1c1c !important;
    color-scheme: light;          /* native date picker glyphs go dark-on-light */
}
html:not(.night) .home-search-inner .search-field input::placeholder {
    color: #9a9a9a !important;
}
html:not(.night) .home-search-inner .search-field input[type="date"]:invalid,
html:not(.night) .home-search-inner .search-field input[type="date"]:not(:focus):placeholder-shown {
    color: #9a9a9a !important;
}
html:not(.night) .home-search-inner .search-field select option {
    background: #ffffff !important;
    color: #1c1c1c !important;
}

/* ------------------------------------------------------------
   30. SEARCH BOX v2 — develop the hero search into an Airbnb-style
   segmented control. The .search-field-wrapper / .field-icon /
   .select-arrow-icon classes existed in markup but had NO CSS, so
   icons just flowed inline. Give them real layout, replace the hard
   dividers with hover/focus "segment" highlighting, align a custom
   chevron, and style the quick date-preset chips (markup added in
   home.php). Theme-aware (day + night).
   ------------------------------------------------------------ */
.home-search-inner .search-field-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    gap: 9px;
}
.home-search-inner .field-icon {
    color: #7C3AED;
    font-size: 0.95rem;
    flex-shrink: 0;
}
.home-search-inner .search-field input,
.home-search-inner .search-field select {
    flex: 1;
    min-width: 0;
    -webkit-appearance: none;
    appearance: none;
    padding-inline-end: 16px;          /* room for the custom chevron */
    background-image: none !important;  /* kill native select arrow */
}
.home-search-inner .select-arrow-icon {
    position: absolute;
    inset-inline-end: 0;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.7rem;
    color: var(--color-text-muted);
    pointer-events: none;
    transition: transform 0.2s ease;
}
.home-search-inner .search-field:focus-within .select-arrow-icon {
    transform: translateY(-50%) rotate(180deg);
}

/* Segmented control: drop the hard dividers, highlight active segment */
.home-search-inner .search-field {
    border-inline-end: none !important;
    border-radius: 14px;
    padding: 8px 16px !important;
    transition: background 0.2s ease;
}
.home-search-inner .search-field:hover,
.home-search-inner .search-field:focus-within {
    background: rgba(124, 58, 237, 0.06);
}
html.night .home-search-inner .search-field:hover,
html.night .home-search-inner .search-field:focus-within {
    background: rgba(255, 255, 255, 0.06);
}
html:not(.night) .home-search-inner .search-field:focus-within label,
html.night .home-search-inner .search-field:focus-within label {
    color: #7C3AED !important;
}

/* Quick date-preset chips (Tonight / Tomorrow / Weekend) */
.search-date-presets {
    display: flex;
    align-items: center;
    gap: 8px;
    justify-content: center;
    flex-wrap: wrap;
    margin-top: 14px;
}
.date-preset-chip {
    appearance: none;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text-muted);
    font-family: var(--font-body);
    font-size: 12.5px;
    font-weight: 600;
    padding: 6px 14px;
    border-radius: var(--radius-full);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s ease;
}
.date-preset-chip:hover {
    border-color: rgba(124, 58, 237, 0.5);
    color: #7C3AED;
}
.date-preset-chip.active {
    background: #7C3AED;
    border-color: #7C3AED;
    color: #fff;
}
html.night .date-preset-chip.active { color: #fff; }

/* ------------------------------------------------------------
   31. /search PAGE — consistency with the home search box.
   (a) Quick-filter chips were inline-styled with rgba(255,255,255,…)
   borders/bg → invisible on the light day-mode header. Move to a
   theme-aware class. (b) Lay out the field icons (the wrapper/icon
   classes were unstyled) so the leading icon aligns with the input.
   ------------------------------------------------------------ */
.sr-quick-chip {
    padding: 7px 14px;
    border-radius: 20px;
    font-size: 0.78rem;
    font-weight: 600;
    text-decoration: none;
    border: 1px solid var(--color-border);
    background: transparent;
    color: var(--color-text-muted);
    transition: all 0.25s ease;
}
.sr-quick-chip:hover {
    border-color: rgba(124, 58, 237, 0.5);
    color: #7C3AED;
}
.sr-quick-chip.on {
    border-color: #7C3AED;
    background: rgba(124, 58, 237, 0.12);
    color: #7C3AED;
}

/* Field icon layout (wrapper/icon classes were unstyled on /search) */
.search-bar .search-field-wrapper {
    position: relative;
    display: flex;
    align-items: center;
    gap: 9px;
}
.search-bar .field-icon { color: #7C3AED; flex-shrink: 0; font-size: 0.95rem; }
.search-bar .search-field-wrapper input,
.search-bar .search-field-wrapper select {
    flex: 1;
    min-width: 0;
}
.search-bar .search-field-wrapper select {
    -webkit-appearance: none;
    appearance: none;
    background-image: none !important;
    padding-inline-end: 22px !important;
}
.search-bar .select-arrow-icon {
    position: absolute;
    inset-inline-end: 14px;
    top: 50%;
    transform: translateY(-50%);
    font-size: 0.7rem;
    color: var(--color-text-muted);
    pointer-events: none;
}

/* ------------------------------------------------------------
   32. SEARCH TYPEAHEAD — suggestions dropdown (markup + JS in
   search_results.php; endpoint GET /api/search-suggest).
   Theme-aware (day + night).
   ------------------------------------------------------------ */
.search-suggest {
    position: absolute;
    top: calc(100% + 6px);
    inset-inline-start: 0;
    inset-inline-end: 0;
    z-index: 1200;
    margin: 0;
    padding: 6px;
    list-style: none;
    background: #ffffff;
    border: 1px solid #ececec;
    border-radius: 12px;
    box-shadow: 0 16px 40px rgba(17, 12, 34, 0.18);
    max-height: 320px;
    overflow-y: auto;
}
html.night .search-suggest {
    background: #14121f;
    border-color: rgba(167, 139, 250, 0.18);
    box-shadow: 0 16px 40px rgba(0, 0, 0, 0.55);
}
.search-suggest[hidden] { display: none; }
.search-suggest-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding: 9px 12px;
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.12s ease;
}
.search-suggest-item:hover,
.search-suggest-item.is-active {
    background: rgba(124, 58, 237, 0.10);
}
html.night .search-suggest-item:hover,
html.night .search-suggest-item.is-active {
    background: rgba(167, 139, 250, 0.16);
}
.search-suggest-item .sg-label {
    font-size: 0.9rem;
    font-weight: 600;
    color: #1c1c1c;
}
.search-suggest-item .sg-sub {
    font-size: 0.76rem;
    color: #6b6b6b;
}
html.night .search-suggest-item .sg-label { color: #f4f4f6; }
html.night .search-suggest-item .sg-sub { color: #b6b9c6; }

/* ------------------------------------------------------------
   33. DAY-MODE FIX + booking polish — event-detail quantity box.
   .ed-ticket-select was hard-coded dark (rgba(3,0,20,.5)) and the
   ± buttons had white glyphs, so in day mode the box was a dark
   slab with invisible +/−. Make them light in day (night intact),
   and add a clear disabled state for the stepper at min/max.
   ------------------------------------------------------------ */
html:not(.night) .ed-ticket-select {
    background: #f7f7f9 !important;
    border-color: #ececec !important;
}
html:not(.night) .ed-qty-btn {
    background: #ffffff !important;
    border-color: #d9d9e0 !important;
    color: #1c1c1c !important;
}
html:not(.night) .ed-qty-btn:hover {
    border-color: #7C3AED !important;
    background: rgba(124, 58, 237, 0.08) !important;
}
/* Stepper disabled state (toggled by adjustQty) — both themes */
.ed-qty-btn.is-disabled {
    opacity: 0.4;
    pointer-events: none;
    cursor: not-allowed;
}

/* ------------------------------------------------------------
   34b. TOUCH-TARGET ACCESSIBILITY (WCAG 2.5.5 — ≥44px hit area).
   Mobile QA found several controls under the 44px minimum: the
   hero / Top-5 carousel dots (~9px), the lightbox close ✕ glyphs
   (~25px), the lightbox arrows (~42px) and the floor-plan steppers
   (~30px). We grow only the TAP AREA, and only on coarse (touch)
   pointers — the visible glyph/dot is unchanged and desktop mouse
   UIs stay pixel-identical. Buttons use min-width/min-height so
   they win over any later per-page width/height rule regardless of
   source order; the tiny dots use a transparent ::before overlay
   sized to the inter-dot spacing so neighbours never overlap.
   ------------------------------------------------------------ */
@media (pointer: coarse) {
    /* Carousel / slider pagination dots — 44px-tall tap area, width capped to the
       spacing so each dot stays individually tappable (no overlapping hit zones). */
    .hero-dots, .top5-dots { gap: 16px; }
    .hero-dot, .top5-dot { position: relative; }
    .hero-dot::before, .top5-dot::before {
        content: "";
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate(-50%, -50%);
        width: calc(100% + 16px);
        height: 44px;
    }

    /* Standalone circular close (✕) buttons that were under 44px. */
    .reels-close-btn,
    .vibe-close-btn { min-width: 44px; min-height: 44px; }

    /* Lightbox prev / next arrows (42px on small screens). */
    .ed-lb-nav { min-width: 44px; min-height: 44px; }

    /* Floor-plan zoom / reset steppers (±, ⟳) — were 30–32px. */
    .floor-controls button { min-width: 44px; min-height: 44px; }

    /* Bare ✕ close glyphs in the venue / portfolio lightboxes (~25px <span>) —
       give them a real 44px centred hit box (the .a11y-close class is added in
       the markup; positioning stays on the element's own inline style). */
    .a11y-close {
        min-width: 44px;
        min-height: 44px;
        display: inline-flex;
        align-items: center;
        justify-content: center;
    }
}

/* ============================================================
   A-FDN · MOTION & STATE FOUNDATION  (slice A0.1–A0.8)
   Reusable interaction primitives consumed site-wide and by the
   later design slices (A-PUB-CONVERT, A-PUB-HOME, A-PARTNER,
   A-ADMIN-POLISH). Everything below is additive and gated on
   `prefers-reduced-motion`. Behaviour is wired by /js/enhancements.js.

   Safety model: rules that HIDE content until JS acts are gated
   behind a root class the engine adds on init (`html.reveal-ready`,
   `html.blurup-ready`). If JS never runs, nothing is hidden — the
   page degrades to fully-visible, un-animated content.
   ============================================================ */

/* ------------------------------------------------------------
   34. A0.1 — SCROLL-REVEAL ENGINE.
   Add class `reveal` to any element; the engine adds `.is-revealed`
   when it scrolls into view. `--i` gives a stagger index for lists
   (e.g. style="--i:2"). Cooperates with the legacy `.active` class
   (home.php uses it) so both observers reveal the same element.
   Only hides once the engine has flagged the document ready.
   ------------------------------------------------------------ */
html.reveal-ready .reveal {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity var(--dur-slow, 420ms) var(--ease-out, cubic-bezier(.16, 1, .3, 1)),
                transform var(--dur-slow, 420ms) var(--ease-out, cubic-bezier(.16, 1, .3, 1));
    transition-delay: calc(var(--i, 0) * 60ms);
}
/* Directional / scale variants (opt-in reusable hooks). */
html.reveal-ready .reveal[data-reveal="left"]  { transform: translateX(-24px); }
html.reveal-ready .reveal[data-reveal="right"] { transform: translateX(24px); }
html.reveal-ready .reveal[data-reveal="scale"] { transform: scale(.96); }
html.reveal-ready .reveal[data-reveal="fade"]  { transform: none; }
/* Revealed state — matches whichever class fires first. */
html.reveal-ready .reveal.is-revealed,
html.reveal-ready .reveal.active {
    opacity: 1;
    transform: none;
}
@media (prefers-reduced-motion: reduce) {
    html.reveal-ready .reveal {
        opacity: 1 !important;
        transform: none !important;
        transition: none !important;
    }
}

/* ------------------------------------------------------------
   35. A0.2 — SKELETON / SHIMMER KIT.
   Server-render a placeholder with these classes; JS swaps it for
   real content on load. `.sk` is the shimmering base; the `-*`
   helpers are common shapes. Theme-aware (light + night).
   ------------------------------------------------------------ */
.sk {
    position: relative;
    overflow: hidden;
    background: var(--sk-base, rgba(124, 58, 237, 0.08));
    border-radius: 8px;
}
html.night .sk { background: var(--sk-base, rgba(255, 255, 255, 0.06)); }
.sk::after {
    content: "";
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, var(--sk-shine, rgba(255, 255, 255, 0.45)), transparent);
    animation: ytSkShimmer 1.5s ease-in-out infinite;
}
html.night .sk::after { background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.10), transparent); }
html[dir="rtl"] .sk::after { transform: translateX(100%); animation-name: ytSkShimmerRtl; }
@keyframes ytSkShimmer    { 100% { transform: translateX(100%); } }
@keyframes ytSkShimmerRtl { 100% { transform: translateX(-100%); } }
.sk-text   { height: .8em; margin: .4em 0; border-radius: 4px; width: 100%; }
.sk-text.sk-sm { width: 40%; }
.sk-text.sk-md { width: 65%; }
.sk-text.sk-lg { width: 90%; }
.sk-title  { height: 1.4em; width: 60%; border-radius: 6px; }
.sk-card   { height: 320px; border-radius: 16px; }
.sk-chart  { height: 200px; border-radius: 12px; }
.sk-avatar { width: 44px; height: 44px; border-radius: 50%; }
.sk-thumb  { width: 100%; aspect-ratio: 16 / 10; border-radius: 12px; }
.sk-btn    { height: 44px; width: 120px; border-radius: 12px; }
@media (prefers-reduced-motion: reduce) {
    .sk::after { animation: none; }
}

/* ------------------------------------------------------------
   36. A0.3 — BLUR-UP IMAGES.
   Wrap an <img> in `.img-blur` (or put the class on the <img>).
   The image renders blurred until it loads, then clears. JS adds
   `.is-loaded`. Gated on `html.blurup-ready` so a JS-less page
   never gets stuck showing a permanently-blurred image.
   ------------------------------------------------------------ */
.img-blur { position: relative; overflow: hidden; background: var(--sk-base, rgba(124, 58, 237, 0.08)); }
html.blurup-ready .img-blur:not(.is-loaded) > img,
html.blurup-ready img.img-blur:not(.is-loaded) {
    filter: blur(14px);
    transform: scale(1.04);
}
html.blurup-ready .img-blur > img,
html.blurup-ready img.img-blur {
    transition: filter .6s var(--ease-out, ease), transform .6s var(--ease-out, ease);
}
@media (prefers-reduced-motion: reduce) {
    html.blurup-ready .img-blur:not(.is-loaded) > img,
    html.blurup-ready img.img-blur:not(.is-loaded) { filter: none; transform: none; }
    html.blurup-ready .img-blur > img,
    html.blurup-ready img.img-blur { transition: none; }
}

/* ------------------------------------------------------------
   37. A0.6 — GLOBAL PRESS FEEDBACK.
   A subtle tactile scale on press. Magnetic / primary buttons are
   already handled (JS magnetic follow + section-5 :active), so they
   are excluded to keep their snappy feel. `[data-press]` is the
   universal opt-in hook for any element (cards etc.).
   ------------------------------------------------------------ */
@media (prefers-reduced-motion: no-preference) {
    .btn:not(.magnetic):not(.btn-primary):not(.btn-submit):not(.btn-book-now),
    .p-btn,
    [data-press] {
        transition: transform var(--dur-fast, 140ms) var(--ease-out, ease);
    }
    .btn:not(.magnetic):not(.btn-primary):not(.btn-submit):not(.btn-book-now):active,
    .p-btn:active,
    [data-press]:active {
        transform: scale(.97);
    }
    [data-press]:disabled:active,
    [data-press][aria-disabled="true"]:active { transform: none; }
}

/* ------------------------------------------------------------
   38. A0.7 — INLINE FORM VALIDATION FEEDBACK.
   Section 13 already reddens `:user-invalid` fields. Here we add a
   shake on a failed submit (wired in JS via the `invalid` event)
   and a reusable `.field-error` message element for async / custom
   validation (`YT.fieldError(input, msg)`).
   ------------------------------------------------------------ */
@keyframes ytFieldShake {
    10%, 90% { transform: translateX(-1px); }
    20%, 80% { transform: translateX(2px); }
    30%, 50%, 70% { transform: translateX(-4px); }
    40%, 60% { transform: translateX(4px); }
}
.field-shake { animation: ytFieldShake .4s cubic-bezier(.36, .07, .19, .97) both; }
.field-error {
    display: flex;
    align-items: flex-start;
    gap: 6px;
    margin-top: 6px;
    font-size: .82rem;
    line-height: 1.45;
    color: #ef4444;
}
.field-error::before {
    content: "\f06a"; /* fa-circle-exclamation */
    font-family: "Font Awesome 6 Free";
    font-weight: 900;
    font-size: .9em;
    line-height: 1.5;
    flex: none;
}
html.night .field-error { color: #f87171; }
@media (prefers-reduced-motion: reduce) {
    .field-shake { animation: none; }
}

/* ------------------------------------------------------------
   39. A0.5 — TOAST refinements + a11y.
   The visual toast lives in premium-ui.css (`.premium-toast`). Here
   we add the action/undo button, an info variant, and RTL-safe
   layout so `YT.toast(msg,{type,undo,action})` renders cleanly.
   ------------------------------------------------------------ */
.premium-toast .toast-action {
    background: transparent;
    border: 1px solid var(--border, rgba(255, 255, 255, 0.15));
    color: var(--accent-gold, #f59e0b);
    border-radius: 8px;
    padding: 4px 12px;
    margin-inline-start: auto;
    font: 600 .85rem/1 var(--font-body, inherit);
    cursor: pointer;
    white-space: nowrap;
    transition: background var(--dur-fast, 140ms) var(--ease-out, ease),
                border-color var(--dur-fast, 140ms) var(--ease-out, ease);
}
.premium-toast .toast-action:hover {
    background: rgba(124, 58, 237, 0.14);
    border-color: rgba(124, 58, 237, 0.4);
}
.premium-toast.toast-info { border-color: rgba(124, 58, 237, 0.4); }
.premium-toast.toast-info i { color: #a78bfa; font-size: 1.2rem; }
.premium-toast.toast-warning { border-color: rgba(245, 158, 11, 0.4); }
.premium-toast.toast-warning i { color: #f59e0b; font-size: 1.2rem; }
html[dir="rtl"] .premium-toast { text-align: start; }
/* Dedicated auto-dismiss bar — custom duration via inline style; reuses
   premium-ui.css's toastProgress keyframe (scaleX 1→0). */
.premium-toast .yt-toast-bar {
    height: 3px;
    width: 100%;
    border-radius: 2px;
    background: var(--accent-gold, #f59e0b);
    transform-origin: left center;
    animation-name: toastProgress;
    animation-timing-function: linear;
    animation-fill-mode: forwards;
}
html[dir="rtl"] .premium-toast .yt-toast-bar { transform-origin: right center; }
@media (prefers-reduced-motion: reduce) { .premium-toast .yt-toast-bar { display: none; } }

/* ------------------------------------------------------------
   40. A0.4 — button spinner (behaviour already in js/enhancements.js).
   `.is-loading` styling lives in section 16. `YT.buttonLoading(btn,
   bool)` (JS) toggles it for AJAX actions that don't navigate away.
   No extra CSS needed — this note documents the pairing.
   ------------------------------------------------------------ */
