/* ============================================================
 * Discovery Desktop — module-specific styles.
 *
 * Self-contained: does NOT import gallery.css / home.css. The few
 * patterns we want from those (header, chips, search input) are
 * re-implemented here under the dd- prefix so the live gallery
 * pages cannot be affected by edits in this file.
 *
 * Design tokens mirror the /gallery and / pages for consistency.
 * ============================================================ */

:root {
    --dd-brand:       #510EA8;
    --dd-brand-lite:  #761CEA;
    --dd-brand-dark:  #3F0B83;
    --dd-brand-soft:  #E5D0FF;

    --dd-bg:          #F7F6FA;
    --dd-surface:     #FFFFFF;
    --dd-border:      #E6E4EC;
    --dd-text:        #1A1A1F;
    --dd-text-muted:  #6B6B6B;
    --dd-shadow-sm:   0 1px 2px rgba(20, 12, 40, 0.05);
    --dd-shadow-md:   0 8px 24px rgba(20, 12, 40, 0.08);

    --dd-radius:      14px;
    --dd-radius-sm:   10px;
    --dd-header-h:    64px;
    --dd-sidebar-w:   260px;
    --dd-max-w:       1320px;

    /* Typography scale — mirrors mobile module.css per CLAUDE.md.
       --text-xs … --text-lg are in rem so they grow with the fluid
       root font-size (clamped 16px → 18px across viewport widths).
       --text-xl and up are fixed px because display tiers shouldn't
       scale arbitrarily on accessibility font preferences. */
    --text-xs:    0.75rem;     /* 12px @ root */
    --text-sm:    0.875rem;    /* 14px */
    --text-base:  1rem;        /* 16px */
    --text-md:    1.25rem;     /* 20px */
    --text-lg:    1.5rem;      /* 24px */
    --text-xl:    28px;        /* fixed — display tier */
    --text-2xl:   40px;        /* fixed — display tier */
    --text-hero:  56px;        /* fixed — hero numbers */
}

* { box-sizing: border-box; }

html, body {
    margin: 0;
    padding: 0;
    background: var(--dd-bg);
    color: var(--dd-text);
    font-family: -apple-system, BlinkMacSystemFont, "SF Pro Text", "Segoe UI",
                 system-ui, "Helvetica Neue", Arial, sans-serif;
    /* Fluid base size: 16px on phone-web, scaling smoothly to 18px on
       wide monitors. Anything that uses rem (or relative em on icons)
       scales with it automatically; px-sized elements stay fixed. The
       0.25vw slope reaches 18px around a 1440px viewport. */
    font-size: clamp(16px, calc(15px + 0.25vw), 18px);
    line-height: 1.55;
    -webkit-font-smoothing: antialiased;
}

a { color: inherit; text-decoration: none; }
button { font: inherit; cursor: pointer; }

/* ── Header ─────────────────────────────────────────────────── */
.dd-header {
    height: var(--dd-header-h);
    background: var(--dd-surface);
    border-bottom: 1px solid var(--dd-border);
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 32px;
    position: sticky;
    top: 0;
    z-index: 10;
}

.dd-header-left { display: flex; align-items: center; gap: 28px; }

.dd-logo-link {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: opacity 0.15s ease;
}
.dd-logo-link:hover { opacity: 0.8; }

.dd-logo { width: 32px; height: 32px; border-radius: 8px; }

.dd-nav { display: flex; gap: 24px; }

.dd-nav-link {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--dd-text-muted);
    padding: 6px 2px;
    border-bottom: 2px solid transparent;
    transition: color 0.15s ease, border-color 0.15s ease;
}
.dd-nav-link:hover { color: var(--dd-text); }
.dd-nav-link--active {
    color: var(--dd-brand);
    border-bottom-color: var(--dd-brand);
}

.dd-header-right { display: flex; align-items: center; gap: 12px; flex: 0 1 620px; }

/* ── Header search ─────────────────────────────────────────── */
.dd-header-search {
    position: relative;
    flex: 1;
    min-width: 0;
}
.dd-header-search__icon {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--dd-text-muted);
    pointer-events: none;
}
.dd-header-search input {
    width: 100%;
    padding: 8px 12px 8px 36px;
    border: 1px solid var(--dd-border);
    border-radius: 10px;
    font-size: var(--text-sm);
    background: var(--dd-bg);
    color: var(--dd-text);
    transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}
.dd-header-search input:focus {
    outline: none;
    background: var(--dd-surface);
    border-color: var(--dd-brand);
    box-shadow: 0 0 0 4px var(--dd-brand-soft);
}

.dd-city-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 12px;
    border: 1px solid var(--dd-border);
    background: var(--dd-surface);
    color: var(--dd-text);
    border-radius: 999px;
    font-size: var(--text-sm);
    font-weight: 500;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.dd-city-chip:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
}

/* ── Mobile search toggle ──────────────────────────────────────
   Hidden on desktop; on small screens it replaces the inline
   search box + near/city chips and reveals a full-width search
   bar below the header. Styled to match the language picker chip. */
.dd-search-toggle {
    display: none;
    align-items: center;
    justify-content: center;
    padding: 6px 10px;
    border: 1px solid var(--dd-border);
    background: var(--dd-surface);
    color: var(--dd-text);
    border-radius: 999px;
    line-height: 1;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.dd-search-toggle:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
}

/* ── Language picker ───────────────────────────────────────────
   Header chip showing the active locale's flag + caret. Click
   opens a dropdown of supported content languages. */
.dd-lang-picker {
    position: relative;
}
.dd-lang-picker__btn {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 6px 10px;
    border: 1px solid var(--dd-border);
    background: var(--dd-surface);
    color: var(--dd-text);
    border-radius: 999px;
    line-height: 1;
    transition: background 0.15s ease, border-color 0.15s ease;
}
.dd-lang-picker__btn:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
}
.dd-lang-picker__flag {
    /* Emoji flags render bigger than the surrounding 14px label
       text — clamp the size so the chip stays in-line with the
       city chip next to it. */
    font-size: 18px;
    line-height: 1;
}
.dd-lang-picker__caret {
    color: var(--dd-text-muted);
    flex-shrink: 0;
}
.dd-lang-picker__menu {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    min-width: 200px;
    padding: 4px;
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius-sm);
    box-shadow: var(--dd-shadow-md);
    z-index: 50;
}
.dd-lang-picker__item {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    background: transparent;
    border: 0;
    border-radius: 6px;
    text-align: left;
    color: var(--dd-text);
    font-size: var(--text-base);
}
.dd-lang-picker__item:hover {
    background: var(--dd-brand-soft);
}
.dd-lang-picker__item.is-active {
    font-weight: 600;
    background: var(--dd-brand-soft);
}
.dd-lang-picker__item-flag {
    font-size: 18px;
    line-height: 1;
}
.dd-lang-picker__item-name {
    flex: 1;
}

/* ── Layout ─────────────────────────────────────────────────── */
.dd-layout {
    /* --dd-page-pad is the side padding of the content container. The
       hero banner reads it so its full-bleed flush-pull and form
       alignment track the layout at every breakpoint. */
    --dd-page-pad: 32px;
    max-width: var(--dd-max-w);
    margin: 0 auto;
    padding: var(--dd-page-pad);
    display: grid;
    grid-template-columns: var(--dd-sidebar-w) 1fr;
    gap: 32px;
    min-height: calc(100vh - var(--dd-header-h));
}

.dd-sidebar { position: sticky; top: calc(var(--dd-header-h) + 32px); align-self: start; }
.dd-content { min-width: 0; /* prevent grid blow-out from long children */ }

/* ── Bootstrap loading state ────────────────────────────────── */
.dd-bootstrap {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    padding: 80px 0;
    color: var(--dd-text-muted);
    gap: 16px;
}

.dd-spinner {
    width: 28px;
    height: 28px;
    border: 3px solid var(--dd-border);
    border-top-color: var(--dd-brand);
    border-radius: 50%;
    animation: dd-spin 0.8s linear infinite;
}
@keyframes dd-spin { to { transform: rotate(360deg); } }

/* ── Sidebar ────────────────────────────────────────────────── */
.dd-sidebar__block {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    padding: 18px 16px;
    box-shadow: var(--dd-shadow-sm);
}
.dd-sidebar__block-title {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--dd-text-muted);
    margin-bottom: 12px;
}
.dd-sidebar__cta {
    display: block;
    padding: 8px 0;
    color: var(--dd-brand);
    font-weight: 600;
}

.dd-sidebar__block--compact {
    padding: 8px;
}

.dd-sidebar__near-btn {
    width: 100%;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    border: none;
    /* Solid purple CTA from the start — matches the mobile convention
       (CTAs are var(--brand), never the light tint) and the desktop
       "Book" CTA. Light purple is reserved for passive hover/active
       tints, not default button fills. */
    background: var(--dd-brand);
    color: #fff;
    border-radius: 10px;
    font-weight: 600;
    font-size: var(--text-sm);
    cursor: pointer;
    transition: background 0.15s ease, transform 0.12s ease;
}
.dd-sidebar__near-btn:hover {
    background: var(--dd-brand-dark);
    transform: translateY(-1px);
}
.dd-sidebar__near-icon { display: inline-flex; align-items: center; }

/* ── Shared location pin (purple SVG reused from mobile) ────────
   `<span class="dd-pin">${MAP_PIN_SVG}</span>` — the SVG uses
   currentColor so we just paint the wrapper purple here and size
   the child SVG to the surrounding text. */
.dd-pin {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    color: var(--dd-brand);
    flex: 0 0 auto;
}
.dd-pin > svg {
    width: 1em;
    height: 1em;
    display: block;
}
/* The sidebar Near-me button is a solid-purple CTA, so its pin SVG is
   white throughout (default + hover) to stay legible on the fill. */
.dd-sidebar__near-btn .dd-pin { color: #fff; }
/* In the page H1, the pin scales with the heading. */
.dd-list__title .dd-pin > svg { width: 22px; height: 22px; }
/* In a section title (search-results "Cities" header etc.), scale to
   the heading's effective size — 24px at base, fluid via rem above. */
.dd-section__title .dd-pin > svg { width: 22px; height: 22px; }
/* In the modal title, scale to the H2's effective size. */
.dd-modal__title .dd-pin > svg { width: 20px; height: 20px; }
/* In the suggestion row, slightly larger than the body text. */
.dd-modal__suggestion-pin.dd-pin > svg { width: 18px; height: 18px; }

.dd-cat-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 2px;
    /* No internal scroll — the list grows as tall as it needs to fit every
       category. The sticky sidebar simply extends down and the page scrolls. */
}
.dd-cat-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 8px 10px;
    border-radius: 8px;
    font-size: var(--text-sm);
    color: var(--dd-text);
    cursor: pointer;
    transition: background 0.12s ease;
}
.dd-cat-row:hover { background: var(--dd-brand-soft); }
/* "All" reset row — pinned at the top of the list, set apart from the
   real categories with a divider + brand-coloured label. */
.dd-cat-row--all {
    font-weight: 600;
    color: var(--dd-brand);
    margin-bottom: 4px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--dd-border);
    border-radius: 8px 8px 0 0;
}
.dd-cat-row__name { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.dd-cat-row__count {
    margin-left: 12px;
    padding: 2px 8px;
    border-radius: 999px;
    background: var(--dd-bg);
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
}
.dd-cat-list__empty {
    padding: 8px 10px;
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
}

/* ── Hero (city + country landing pages) ───────────────────── */
.dd-hero {
    margin-bottom: 28px;
    padding-bottom: 24px;
    border-bottom: 1px solid var(--dd-border);
}
.dd-hero__title {
    /* Display tier — fluid via rem so the city/country H1 reads as
       the page's primary signal without being so big it dwarfs the
       grids below. Matches detail-page H1 weight. */
    font-size: 1.75rem;
    font-weight: 700;
    letter-spacing: -0.01em;
    margin: 0 0 6px;
    line-height: 1.2;
}
.dd-hero__sub {
    margin: 0;
    color: var(--dd-text-muted);
    font-size: var(--text-base);
    line-height: 1.5;
}

/* ── Hero banner (global main page) ─────────────────────────────
   Full-width landscape photo leading the landing page, with the
   heading + search + Near-me overlaid on the left ~60%. One of the
   four hero photos is chosen at random per load (JS sets --dd-hero-img).
   The brand gradient is the BASE layer so a missing/404 image still
   renders a branded hero instead of an empty box. */
.dd-hero-banner {
    position: relative;
    margin-bottom: 36px;
    /* Full-bleed: break out of the centered content column and span the
       whole viewport width. The negative top margin cancels the
       layout's top padding so the banner sits flush under the sticky
       header. The inner wrapper re-establishes the page container so the
       overlay/form stays aligned with the content columns. */
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-top: calc(-1 * var(--dd-page-pad, 32px));
    overflow: hidden;
    min-height: 450px;
    display: flex;
    align-items: center;
    /* image layer over a brand-gradient fallback */
    background-image: var(--dd-hero-img, none),
        linear-gradient(135deg, var(--dd-brand), var(--dd-brand-dark));
    background-size: cover, cover;
    background-position: center, center;
    background-repeat: no-repeat, no-repeat;
}
/* Re-establishes the page's max-width + side padding inside the
   full-bleed banner so the overlay's left edge lines up with the
   content columns below it. */
.dd-hero-banner__inner {
    position: relative;
    width: 100%;
    max-width: var(--dd-max-w);
    margin: 0 auto;
    padding: 0 var(--dd-page-pad, 32px);
}
/* Dark scrim — a full-height rectangle behind the form (the left
   portion), fading out just past it so the rest of the photo stays
   clear. Solid behind the form for legibility, transparent on the
   right. */
.dd-hero-banner__scrim {
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        rgba(20, 12, 40, 0.60) 0%,
        rgba(20, 12, 40, 0.60) 42%,
        rgba(20, 12, 40, 0) 62%
    );
}
.dd-hero-banner__overlay {
    position: relative;     /* above the scrim */
    width: 60%;
    min-width: min(100%, 440px);
    /* Vertical padding only — horizontal alignment comes from the inner
       wrapper's --dd-page-pad, so the form's left edge lines up with the
       content columns below. */
    padding: 44px 0;
    color: #fff;
}
.dd-hero-banner__title {
    font-size: 2rem;
    font-weight: 800;
    letter-spacing: -0.02em;
    line-height: 1.2;
    margin: 0 0 24px;
    text-shadow: 0 1px 12px rgba(0, 0, 0, 0.3);
    /* Keep the prefix + rotating word on ONE line — the rotating words
       can be long ("bezienswaardigheden", "stadswandelingen"); the hero
       has the width for it. (Mobile re-enables wrapping.) */
    white-space: nowrap;
}
/* Animated last word.
   GUARANTEED baseline alignment: the word is a normal inline-block in the
   text flow, so it shares the prefix's baseline automatically. We clip
   the vertical slide with clip-path — which, unlike overflow:hidden, does
   NOT resynthesize the inline baseline (that resynthesis was the whole
   bug). No em heights, no pixel nudges. Negative left/right insets keep
   the word from being clipped sideways. */
.dd-hero-banner__rotator {
    display: inline-block;
    position: relative;
    clip-path: inset(0 -40px);
}
.dd-hero-banner__rotator-word {
    display: inline-block;
    white-space: nowrap;
    will-change: transform, opacity;
}
.dd-hero-banner__search {
    position: relative;
    max-width: 520px;
}
.dd-hero-banner__search-icon {
    position: absolute;
    left: 16px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--dd-text-muted);
    pointer-events: none;
}
.dd-hero-banner__search input {
    width: 100%;
    padding: 14px 16px 14px 46px;
    /* Match the picker search: rounded rectangle, not a pill. */
    border: 1px solid var(--dd-border);
    border-radius: 12px;
    font-size: var(--text-base);
    background: var(--dd-surface);
    color: var(--dd-text);
    box-shadow: var(--dd-shadow-sm);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dd-hero-banner__search input:focus {
    outline: none;
    border-color: var(--dd-brand);
    box-shadow: 0 0 0 4px var(--dd-brand-soft);
}

/* ── Search autocomplete popover ────────────────────────────────
   Dropdown of top city + product matches below a search input. */
.dd-suggest {
    /* Fixed + appended to <body> + JS-positioned against the input, so
       the hero's overflow:hidden can't clip it. */
    position: fixed;
    z-index: 1000;
    /* Expand to fit the results; only scroll if they'd run off-screen. */
    max-height: calc(100vh - 120px);
    overflow-y: auto;
    padding: 6px;
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: 12px;
    box-shadow: var(--dd-shadow-md);
    /* The hero scrim/overlay text is white; the popover is its own
       surface, so reset color to the normal body text. */
    color: var(--dd-text);
    text-align: left;
}
.dd-suggest__label {
    padding: 8px 10px 4px;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dd-text-muted);
}
.dd-suggest__row {
    display: flex;
    align-items: center;
    gap: 10px;
    width: 100%;
    padding: 8px 10px;
    border: 0;
    background: transparent;
    border-radius: 8px;
    text-align: left;
    color: var(--dd-text);
}
.dd-suggest__row:hover { background: var(--dd-brand-soft); }
.dd-suggest__pin.dd-pin { flex: 0 0 auto; }
.dd-suggest__pin.dd-pin > svg { width: 18px; height: 18px; }
.dd-suggest__thumb {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    object-fit: cover;
    background: var(--dd-bg);
}
.dd-suggest__thumb--empty { display: inline-block; }
.dd-suggest__text {
    display: flex;
    flex-direction: column;
    min-width: 0;
}
.dd-suggest__name {
    font-size: var(--text-sm);
    font-weight: 600;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dd-suggest__meta {
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.dd-suggest__empty {
    padding: 16px 12px;
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}
/* Compact purple "Near me" pill — shared by the hero overlay and the
   picker (replaced the picker's big wide card). Solid --dd-brand CTA. */
.dd-near-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 9px 16px;
    border: 1px solid var(--dd-brand);
    background: var(--dd-brand);
    color: #fff;
    border-radius: 999px;
    font-weight: 600;
    font-size: var(--text-sm);
    box-shadow: 0 4px 14px rgba(20, 12, 40, 0.30);
    transition: background 0.15s ease, border-color 0.15s ease;
}
.dd-near-pill:hover {
    background: var(--dd-brand-dark);
    border-color: var(--dd-brand-dark);
}
.dd-near-pill .dd-pin { color: #fff; }
/* Hero overlay stacks title / search / near with equal gaps — match the
   pill's top margin to the title's bottom margin (24px). */
.dd-hero-banner__overlay .dd-near-pill { margin-top: 24px; }

/* Tablet / narrow desktop — overlay widens, image still peeks. */
@media (max-width: 860px) {
    .dd-hero-banner__overlay { width: 78%; }
    .dd-hero-banner__title { font-size: 2rem; }
}
/* Mobile — image becomes a full-bleed background; the overlay spans the
   whole width over a full darkening scrim so text stays legible. */
@media (max-width: 600px) {
    .dd-hero-banner { min-height: 375px; }
    .dd-hero-banner__overlay { width: 100%; padding: 28px 0; }
    .dd-hero-banner__scrim {
        background: linear-gradient(
            180deg,
            rgba(20, 12, 40, 0.22) 0%,
            rgba(20, 12, 40, 0.43) 100%
        );
    }
    .dd-hero-banner__title { font-size: 1.7rem; white-space: normal; }
}

/* ── SSR crawlable lists (city page / products index) ──────────
   Visible to crawlers + no-JS visitors; the SPA wipes #dd-mount and
   repaints the interactive grid for everyone else. */
.dd-citypage__title {
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 20px;
}
.dd-citypage__curator {
    margin: 24px 0 0;
    font-size: var(--text-sm);
    color: var(--dd-text-muted, #6b7280);
}
.dd-ssr-city-list {
    list-style: none;
    margin: 0 0 16px;
    padding: 0;
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.dd-ssr-city-list li a {
    display: inline-block;
    padding: 4px 12px;
    border-radius: var(--pill, 999px);
    background: var(--dd-surface-2, rgba(0,0,0,0.04));
    font-size: var(--text-sm);
    color: var(--dd-brand);
}
.dd-ssr-city-list li a:hover { text-decoration: underline; }

.dd-ssr-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    gap: 10px;
}
.dd-ssr-list__item {
    display: flex;
    flex-direction: column;
    gap: 2px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--dd-border);
}
.dd-ssr-list__link {
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--dd-brand);
}
.dd-ssr-list__link:hover { text-decoration: underline; }
.dd-ssr-list__desc {
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}
.dd-ssr-list__reviews {
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
}
.dd-ssr-list__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
}
.dd-ssr-list__tag {
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
    background: var(--dd-surface-2, rgba(0,0,0,0.04));
    border-radius: var(--pill, 999px);
    padding: 2px 8px;
}

/* ── Ranked "Best things to do" section (GEO-C1) ───────────────
   Answer-shaped, annotated Top-N rendered above the flat product list.
   SSR-only (the SPA repaints the interactive grid). */
.dd-citypage__best {
    margin: 0 0 28px;
}
.dd-citypage__best-title {
    font-size: var(--text-md);
    font-weight: 700;
    margin: 0 0 14px;
}
.dd-citypage__best-list {
    margin: 0;
    padding-left: 1.4em;
    display: grid;
    gap: 10px;
}
.dd-citypage__best-item {
    display: flex;
    flex-direction: column;
    gap: 2px;
}
.dd-citypage__best-link {
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--dd-brand);
}
.dd-citypage__best-link:hover { text-decoration: underline; }
.dd-citypage__best-why {
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}
.dd-citypage__compare {
    margin: 0 0 28px;
    font-size: var(--text-sm);
    font-weight: 600;
}
.dd-citypage__compare a { color: var(--dd-brand); }
.dd-citypage__compare a:hover { text-decoration: underline; }
.dd-citypage__intents {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 28px;
}
.dd-citypage__intent {
    font-size: var(--text-sm);
    font-weight: 600;
    color: var(--dd-brand);
    background: var(--dd-surface-2, rgba(0,0,0,0.04));
    border-radius: var(--pill, 999px);
    padding: 6px 14px;
}
.dd-citypage__intent:hover { text-decoration: underline; }

/* ── Comparison page (GEO-C2) ──────────────────────────────────
   Server-rendered static content: H1 + intro + side-by-side facts table.
   The SPA leaves this body in place (no hydration). */
.dd-compare {
    max-width: 760px;
    margin: 0 auto;
    padding: 8px 0 40px;
}
.dd-compare__title {
    font-size: var(--text-xl);
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 12px;
}
.dd-compare__intro {
    color: var(--dd-text-muted);
    font-size: var(--text-base);
    line-height: 1.5;
    margin: 0 0 24px;
}
.dd-compare__table {
    width: 100%;
    border-collapse: collapse;
    font-size: var(--text-sm);
}
.dd-compare__table th,
.dd-compare__table td {
    text-align: left;
    padding: 12px 14px;
    border-bottom: 1px solid var(--dd-border);
    vertical-align: top;
}
.dd-compare__col {
    font-size: var(--text-base);
    font-weight: 700;
}
.dd-compare__col a { color: var(--dd-brand); }
.dd-compare__col a:hover { text-decoration: underline; }
.dd-compare__rowhead {
    font-weight: 600;
    color: var(--dd-text-muted);
    width: 30%;
}
.dd-compare__cell { color: var(--dd-text); }

/* ── Countries directory ────────────────────────────────────── */
.dd-countries__title {
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: -0.01em;
    margin: 0 0 24px;
}
.dd-countries__group { margin-bottom: 32px; }
.dd-countries__name {
    font-size: var(--text-lg);
    font-weight: 700;
    margin: 0 0 12px;
    padding-bottom: 8px;
    border-bottom: 1px solid var(--dd-border);
}
.dd-countries__name a { color: var(--dd-text); }
.dd-countries__name a:hover { color: var(--dd-brand); }
.dd-countries__n {
    font-size: var(--text-sm);
    font-weight: 500;
    color: var(--dd-text-muted);
}
.dd-countries__cities {
    list-style: none;
    margin: 0;
    padding: 0;
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 6px 16px;
}
.dd-countries__city {
    color: var(--dd-brand);
    font-size: var(--text-sm);
}
.dd-countries__city:hover { text-decoration: underline; }

/* ── Section headings ───────────────────────────────────────── */
.dd-section { margin-bottom: 40px; }
/* Generic hide utility — used by sections that mount empty and only
   reveal once their data lands (e.g. featured venues for partner-light
   cities, where the section should not render at all). */
.dd-hidden { display: none; }
.dd-section__heading {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 16px;
}
.dd-section__title {
    font-size: var(--text-lg);
    font-weight: 700;
    margin: 0;
    letter-spacing: -0.01em;
}
.dd-section__sub {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
}

/* ── Product grid ───────────────────────────────────────────── */
.dd-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
    gap: 20px;
}
.dd-grid--small {
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
}

/* ── Card ───────────────────────────────────────────────────── */
.dd-card {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    overflow: hidden;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    text-decoration: none;
    color: inherit;
    transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
    box-shadow: var(--dd-shadow-sm);
}
.dd-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--dd-shadow-md);
    border-color: var(--dd-brand-soft);
}
.dd-card--sold-out { opacity: 0.72; }

.dd-card__art {
    position: relative;
    width: 100%;
    /* 16:9 hero — modern desktop feel, matches mobile and the YouTube
       tile on the detail page. de Stoep posters get a moderate crop
       (object-fit: cover keeps the centre of the frame, which is what
       theatre poster artists tend to weight toward anyway). */
    aspect-ratio: 16 / 9;
    background: linear-gradient(135deg, var(--dd-brand-soft), var(--dd-bg));
    overflow: hidden;
}
/* After we parameterized mobile's productCard with a class prefix,
   the image class became `<prefix>__art-img` to match mobile's
   naming. The old `.dd-card__img` rule no longer matched any
   element, so images rendered at their intrinsic size (tiny). */
.dd-card__art-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

.dd-card__promo {
    position: absolute;
    top: 10px;
    right: 10px;
    background: var(--dd-brand);
    color: #fff;
    padding: 4px 10px;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    letter-spacing: 0.02em;
}
/* Close-partner pill structure lives in discovery-shared.css (both
   surfaces' badges are pixel-identical now). Desktop adds only the
   font-size override here — mobile uses --text-xs via its own scale,
   desktop uses --text-xs from its own scale (same rem value, but the
   shared file deliberately doesn't bind to either to avoid coupling). */
.dd-card__partner { font-size: var(--text-xs); }

.dd-card__body {
    padding: 14px 16px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    flex: 1;
}
.dd-card__title {
    margin: 0;
    font-size: var(--text-base);
    font-weight: 600;
    line-height: 1.35;
    color: var(--dd-text);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.dd-card__tagline {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.dd-card__pill {
    align-self: flex-start;
    padding: 3px 8px;
    border-radius: 999px;
    background: var(--dd-brand-soft);
    color: var(--dd-brand-dark);
    font-size: var(--text-xs);
    font-weight: 600;
}
.dd-card__meta {
    margin-top: auto;
    padding-top: 8px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 8px;
    font-size: var(--text-sm);
}
.dd-card__rating { color: var(--dd-text-muted); }
.dd-card__price { font-weight: 600; color: var(--dd-text); }
.dd-card__price del { color: var(--dd-text-muted); font-weight: 400; margin-right: 4px; }
.dd-card__price-from {
    color: var(--dd-text-muted);
    font-weight: 400;
    margin-right: 4px;
}
.dd-card__unavailable { color: var(--dd-text-muted); }

/* ── Horizontal rail (temporary events) ─────────────────────── */
.dd-rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(220px, 1fr);
    gap: 16px;
    overflow-x: auto;
    padding-bottom: 8px;
    scrollbar-width: thin;
}
.dd-rail__item {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    padding: 14px 16px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    box-shadow: var(--dd-shadow-sm);
}
.dd-rail__type {
    text-transform: uppercase;
    letter-spacing: 0.06em;
    font-size: var(--text-xs);
    font-weight: 600;
    color: var(--dd-brand);
}
.dd-rail__title { font-weight: 600; font-size: var(--text-sm); }
.dd-rail__dates { color: var(--dd-text-muted); font-size: var(--text-sm); }

/* ── Skeleton ───────────────────────────────────────────────── */
.dd-skeleton-block,
.dd-skeleton-line {
    background: linear-gradient(90deg, #ECE9F2 0%, #F4F2F8 50%, #ECE9F2 100%);
    background-size: 200% 100%;
    animation: dd-shimmer 1.2s ease infinite;
    border-radius: 6px;
}
.dd-skeleton-line { height: 12px; margin: 6px 0; }
.dd-skeleton-line--title { width: 70%; height: 14px; }
.dd-skeleton-line--sub   { width: 45%; height: 11px; }
.dd-card--skeleton { cursor: default; }
.dd-card--skeleton:hover { transform: none; box-shadow: var(--dd-shadow-sm); border-color: var(--dd-border); }
.dd-card--skeleton .dd-card__art { background: #ECE9F2; }
@keyframes dd-shimmer { 0% { background-position: 200% 0; } 100% { background-position: -200% 0; } }

/* ── Empty state ────────────────────────────────────────────── */
.dd-empty {
    grid-column: 1 / -1;
    text-align: center;
    padding: 48px 24px;
    color: var(--dd-text-muted);
}
/* .dd-empty__icon stays in px — it's an emoji glyph, the size is
   independent of the body type scale. */
.dd-empty__icon { font-size: 40px; margin-bottom: 12px; }
.dd-empty__title { font-size: var(--text-base); font-weight: 600; color: var(--dd-text); margin-bottom: 4px; }
.dd-empty__sub { font-size: var(--text-sm); }


/* ── Picker ─────────────────────────────────────────────────── */

/* On the picker route the sidebar collapses so the picker can use the
   full content width. app.js stamps `.dd-route-picker` on <body>. */
body.dd-route-picker .dd-layout {
    grid-template-columns: 1fr;
}
body.dd-route-picker .dd-sidebar { display: none; }

/* Home route — single column so the hero banner + popular grid use the
   full content width (the hero carries search + Near-me, so no sidebar). */
body.dd-route-home .dd-layout {
    grid-template-columns: 1fr;
}
body.dd-route-home .dd-sidebar { display: none; }

.dd-picker { max-width: 880px; margin: 0 auto; }
.dd-picker__header { margin-bottom: 32px; }
.dd-picker__title {
    /* Display tier — kept in px so it doesn't scale further with
       the fluid root. Sits between --text-xl (28px) and --text-2xl
       (40px); a one-off size for the picker hero. */
    font-size: 32px;
    font-weight: 700;
    margin: 0 0 8px;
    letter-spacing: -0.02em;
}
.dd-picker__sub {
    color: var(--dd-text-muted);
    margin: 0 0 20px;
    font-size: var(--text-base);
}
.dd-picker__search {
    position: relative;
    display: flex;
    align-items: center;
}
.dd-picker__search-icon {
    position: absolute;
    left: 16px;
    color: var(--dd-text-muted);
    pointer-events: none;
}
.dd-picker__search input {
    width: 100%;
    padding: 14px 16px 14px 44px;
    border: 1px solid var(--dd-border);
    border-radius: 12px;
    font-size: var(--text-base);
    background: var(--dd-surface);
    color: var(--dd-text);
    box-shadow: var(--dd-shadow-sm);
    transition: border-color 0.15s ease, box-shadow 0.15s ease;
}
.dd-picker__search input:focus {
    outline: none;
    border-color: var(--dd-brand);
    box-shadow: 0 0 0 4px var(--dd-brand-soft);
}

/* Picker search "Search all products for X →" CTA — appears above
   the city results so a user typing a product name has an obvious
   pivot to the global product search. */
.dd-picker__search-cta {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 14px 18px;
    margin-bottom: 20px;
    /* Solid purple CTA from the start (mobile convention) — was light
       purple → purple on hover, which read as secondary. */
    background: var(--dd-brand);
    border: 1px solid var(--dd-brand);
    border-radius: var(--dd-radius);
    color: #fff;
    font-weight: 600;
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
}
.dd-picker__search-cta:hover {
    background: var(--dd-brand-dark);
    border-color: var(--dd-brand-dark);
    transform: translateY(-1px);
}
.dd-picker__search-cta-arrow {
    margin-left: auto;
    font-size: var(--text-md);
    line-height: 1;
}

/* ── Country filter chips (picker) ──────────────────────────── */
.dd-country-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.dd-country-chip {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 14px;
    border: 1px solid var(--dd-border);
    background: var(--dd-surface);
    color: var(--dd-text);
    border-radius: 999px;
    font-size: var(--text-sm);
    font-weight: 500;
    transition: background 0.15s ease, border-color 0.15s ease, color 0.15s ease;
}
.dd-country-chip:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
}
.dd-country-chip.is-active {
    background: var(--dd-brand);
    border-color: var(--dd-brand);
    color: #fff;
}
.dd-country-chip__n {
    font-size: var(--text-xs);
    opacity: 0.65;
}
.dd-country-chip.is-active .dd-country-chip__n { opacity: 0.8; }

.dd-city-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 14px;
}

.dd-city-card {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    padding: 18px 16px;
    display: flex;
    flex-direction: column;
    gap: 4px;
    text-align: left;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
    box-shadow: var(--dd-shadow-sm);
}
.dd-city-card:hover {
    transform: translateY(-2px);
    border-color: var(--dd-brand);
    box-shadow: var(--dd-shadow-md);
}
.dd-city-card.is-picking { opacity: 0.6; transform: none; }
.dd-city-card__name {
    font-size: var(--text-base);
    font-weight: 600;
    color: var(--dd-text);
}
.dd-city-card__country {
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
}
.dd-city-card__count {
    margin-top: 6px;
    font-size: var(--text-xs);
    color: var(--dd-brand);
    font-weight: 600;
}

.dd-city-list {
    list-style: none;
    margin: 0;
    padding: 0;
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    overflow: hidden;
    box-shadow: var(--dd-shadow-sm);
}
.dd-city-row {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 18px;
    border-top: 1px solid var(--dd-border);
    cursor: pointer;
    text-decoration: none;
    color: inherit;
    transition: background 0.12s ease;
}
.dd-city-row:first-child { border-top: none; }
.dd-city-row:hover { background: var(--dd-brand-soft); }
.dd-city-row__name { flex: 1; font-weight: 500; }
.dd-city-row__country { color: var(--dd-text-muted); font-size: var(--text-sm); }
.dd-city-row__count {
    padding: 2px 10px;
    border-radius: 999px;
    background: var(--dd-bg);
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
}


/* ── Search-page city banner ───────────────────────────────── */
.dd-search-cities {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
}
.dd-search-city {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 14px;
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: 999px;
    color: var(--dd-text);
    transition: background 0.12s ease, border-color 0.12s ease, transform 0.12s ease;
    box-shadow: var(--dd-shadow-sm);
}
.dd-search-city:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand);
    transform: translateY(-1px);
}
.dd-search-city__name {
    font-weight: 600;
}
.dd-search-city__country {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
}
.dd-search-city__count {
    background: var(--dd-bg);
    color: var(--dd-text-muted);
    padding: 1px 8px;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
}

/* ── List page (search + category) ──────────────────────────── */
.dd-list__title {
    /* Display tier — fluid via rem so the list-page H1 matches the
       detail-page H1 in feel across viewport sizes. */
    font-size: 1.625rem;
    font-weight: 700;
    margin: 0;
    letter-spacing: -0.01em;
}


/* ── Detail page ────────────────────────────────────────────── */

/* Detail uses the full content area — sidebar hides for breathing room. */
body.dd-route-detail .dd-layout { grid-template-columns: 1fr; }
body.dd-route-detail .dd-sidebar { display: none; }

.dd-detail-loading {
    display: flex;
    justify-content: center;
    padding: 80px 0;
}

.dd-detail { max-width: 1180px; margin: 0 auto; }

.dd-detail__back {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 8px 12px;
    margin-bottom: 16px;
    background: transparent;
    border: none;
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
    border-radius: 8px;
    transition: background 0.12s ease, color 0.12s ease;
}
.dd-detail__back:hover { background: var(--dd-brand-soft); color: var(--dd-text); }

/* ── Expired-event banner ────────────────────────────────────
 * Shown at the top of the detail page when every showtime is in
 * the past. The right-panel price card is dimmed so the user
 * doesn't reach for a CTA that no longer makes sense. Page stays
 * readable — title / description / venue still legible — so the
 * page works as a "this is what this event was about" archive. */
.dd-detail__expired-banner {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    padding: 14px 18px;
    margin-bottom: 20px;
    background: #FFF4E5;
    border: 1px solid #FFD9A8;
    border-radius: var(--dd-radius);
    color: #8A4B00;
}
.dd-detail__expired-icon {
    font-size: 22px;
    /* Line-height matches the title so the emoji sits on the title's
       baseline rather than the centered axis. */
    line-height: 1.35;
    flex: 0 0 auto;
}
.dd-detail__expired-body { flex: 1; min-width: 0; }
.dd-detail__expired-title {
    font-weight: 600;
    font-size: var(--text-base);
    color: #6F3D00;
    margin-bottom: 2px;
}
.dd-detail__expired-sub {
    font-size: var(--text-sm);
    color: #A56A1E;
}
.dd-detail__expired-link {
    color: inherit;
    font-weight: 600;
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
    transition: color 0.12s ease;
}
.dd-detail__expired-link:hover { color: #6F3D00; }

/* When the page is in the expired state, dim the right-panel price
   card so it reads as "no longer available" rather than as an
   actionable CTA region. The banner above carries the explanation. */
.dd-detail--expired .dd-detail__price-card {
    opacity: 0.55;
    filter: grayscale(0.4);
    pointer-events: none;
}

.dd-detail__layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 360px;
    gap: 32px;
    align-items: start;
}

.dd-detail__main { min-width: 0; }

.dd-detail__hero {
    position: relative;
    width: 100%;
    aspect-ratio: 16 / 10;
    border-radius: var(--dd-radius);
    overflow: hidden;
    background: linear-gradient(135deg, var(--dd-brand-soft), var(--dd-bg));
    box-shadow: var(--dd-shadow-sm);
}
.dd-detail__hero-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.dd-detail__hero-fallback { width: 100%; height: 100%; }

/* Video hero — the large frame is clickable (opens YouTube) and carries a
   big play badge. Photo heroes are inert (no badge, default cursor). */
.dd-detail__hero--video { cursor: pointer; }
.dd-detail__hero-play {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%) scale(1);
    width: 76px;
    height: 76px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
    transition: transform 0.18s ease, box-shadow 0.18s ease;
    pointer-events: none;
}
.dd-detail__hero--video:hover .dd-detail__hero-play {
    transform: translate(-50%, -50%) scale(1.12);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.45);
}
.dd-detail__hero-play[hidden] { display: none; }
.dd-detail__hero-play::after {
    content: '';
    width: 0;
    height: 0;
    border-left: 22px solid var(--dd-brand);
    border-top: 14px solid transparent;
    border-bottom: 14px solid transparent;
    margin-left: 6px;  /* visually centre the triangle */
}
.dd-card__partner--lg {
    top: 16px;
    left: 16px;
    padding: 6px 14px 6px 8px;
    font-size: var(--text-xs);
}

.dd-detail__photo-credit {
    margin: 16px 2px 0;
    font-size: var(--text-xs);
    color: var(--dd-text-muted);
    font-style: italic;
}

.dd-detail__thumbs {
    display: flex;
    gap: 10px;
    margin-top: 12px;
    overflow-x: auto;
    padding-bottom: 4px;
}
.dd-detail__thumb {
    flex: 0 0 96px;
    width: 96px;
    height: 72px;
    border: 2px solid transparent;
    background: var(--dd-bg);
    border-radius: 10px;
    overflow: hidden;
    padding: 0;
    cursor: pointer;
    transition: border-color 0.12s ease, transform 0.12s ease;
}
.dd-detail__thumb img {
    width: 100%; height: 100%; object-fit: cover; display: block;
}
.dd-detail__thumb:hover { transform: translateY(-1px); }
.dd-detail__thumb.is-active { border-color: var(--dd-brand); }

/* ── Video tile (YouTube promo, grouped as the first photo tile) ─── */
.dd-detail__thumb--video { position: relative; display: block; background: #000; }
.dd-detail__thumb--video img { opacity: 0.85; transition: opacity 0.12s ease; }
.dd-detail__thumb--video:hover img { opacity: 1; }
.dd-detail__thumb-play {
    position: absolute;
    left: 50%; top: 50%;
    transform: translate(-50%, -50%) scale(1);
    width: 30px;
    height: 30px;
    border-radius: 50%;
    background: rgba(255, 255, 255, 0.95);
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 3px 10px rgba(0, 0, 0, 0.35);
    transition: transform 0.12s ease;
    pointer-events: none;
}
.dd-detail__thumb--video:hover .dd-detail__thumb-play {
    transform: translate(-50%, -50%) scale(1.1);
}
.dd-detail__thumb-play::after {
    content: '';
    width: 0;
    height: 0;
    border-left: 10px solid var(--dd-brand);
    border-top: 6px solid transparent;
    border-bottom: 6px solid transparent;
    margin-left: 3px;  /* visually centre the triangle */
}

.dd-detail__section { margin-top: 32px; }
.dd-detail__section-title {
    font-size: var(--text-md);
    font-weight: 700;
    margin: 0 0 12px;
}
.dd-detail__description {
    font-size: var(--text-base);
    line-height: 1.7;
    color: var(--dd-text);
}
.dd-detail__para { margin: 0 0 14px; }
.dd-detail__para:last-child { margin-bottom: 0; }
.dd-detail__description strong { font-weight: 600; }
.dd-detail__description em { font-style: italic; }

/* ── Cancellation line under the price (price card) ─────────── */
.dd-detail__cancel {
    margin: -6px 0 12px;
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}

/* ── Close-partner notice ("tickets land in Close app") ─────── */
.dd-detail__close-notice {
    display: flex;
    align-items: flex-start;
    gap: 14px;
    margin-top: 24px;
    padding: 16px 18px;
    background: var(--dd-brand-soft);
    border-radius: var(--dd-radius);
}
.dd-detail__close-notice-icon {
    width: 36px;
    height: 36px;
    border-radius: 8px;
    flex: 0 0 auto;
}
.dd-detail__close-notice-body { min-width: 0; }
.dd-detail__close-notice-title {
    font-weight: 700;
    color: var(--dd-brand-dark);
    margin-bottom: 2px;
}
.dd-detail__close-notice-text {
    color: var(--dd-text);
    font-size: var(--text-sm);
    line-height: 1.5;
}

/* ── News-channel CTA (Stay up to date) ─────────────────────── */
.dd-detail__news-channel {
    display: flex;
    align-items: center;
    gap: 14px;
    margin-top: 14px;
    padding: 14px 18px;
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    box-shadow: var(--dd-shadow-sm);
    transition: border-color 0.15s ease, transform 0.12s ease, box-shadow 0.15s ease;
}
.dd-detail__news-channel:hover {
    border-color: var(--dd-brand);
    transform: translateY(-1px);
    box-shadow: var(--dd-shadow-md);
}
.dd-detail__news-channel-icon {
    width: 36px; height: 36px; border-radius: 8px; flex: 0 0 auto;
}
.dd-detail__news-channel-body { flex: 1; min-width: 0; }
.dd-detail__news-channel-title {
    font-weight: 600;
    font-size: var(--text-sm);
    color: var(--dd-text);
}
.dd-detail__news-channel-cta {
    color: var(--dd-brand);
    font-size: var(--text-sm);
    font-weight: 600;
}
/* Chevron glyph — kept in px per the audit (glyph, not body text). */
.dd-detail__news-channel-chevron {
    color: var(--dd-text-muted);
    font-size: 24px;
    line-height: 1;
}

/* ── Performances list (overrides; structure in shared) ────────
 * Skeleton (list reset, item border-top, link layout, when column,
 * date weight, time muted color) lives in discovery-shared.css.
 * Below: only desktop's panel chrome (border, shadow, hover state)
 * and explicit colour + font-size overrides where desktop diverges
 * from the shared neutral. */
.dd-perf-list {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    overflow: hidden;
    box-shadow: var(--dd-shadow-sm);
}
/* Border colour binds to desktop palette (shared file uses a fallback). */
.dd-perf-item { border-top: 1px solid var(--dd-border); }

/* Sold-out rows (no <a> wrapper) take the padding on the li itself;
   bookable rows pass it through to the inner <a>. */
.dd-perf-item,
.dd-perf-item__link {
    gap: 12px;
    padding: 14px 18px;
}
.dd-perf-item:has(.dd-perf-item__link) { padding: 0; }
.dd-perf-item__link {
    transition: background 0.12s ease;
}
.dd-perf-item__link:hover { background: var(--dd-brand-soft); }
.dd-perf-item__when { gap: 2px; }
.dd-perf-item__date {
    color: var(--dd-text);
    font-size: var(--text-base);
}
.dd-perf-item__time {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
}
/* Chevron glyph — kept in px per the audit (glyph, not body text). */
.dd-perf-item__chevron {
    color: var(--dd-text-muted);
    font-size: 22px;
    line-height: 1;
}
.dd-perf-item__sold-out {
    background: var(--dd-bg);
    color: var(--dd-text-muted);
    padding: 4px 10px;
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.dd-perf-item--sold-out .dd-perf-item__date { color: var(--dd-text-muted); }

/* ── "What's included" bullet list (overrides; structure in shared) ──
 * The skeleton (list-style/padding/flex/direction, item flex, icon
 * sizing, text flex) lives in discovery-shared.css. Below: only
 * desktop's spacing, font-size, line-height, and colour treatments. */
.dd-bullet-list { margin: 0; gap: 10px; }
.dd-bullet-item {
    gap: 12px;
    font-size: var(--text-base);
    line-height: 1.55;
    color: var(--dd-text);
}
.dd-bullet-icon { line-height: 1.55; }
.dd-bullet-text strong { font-weight: 600; }

/* Right side panel */
.dd-detail__panel {
    background: var(--dd-surface);
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    padding: 24px;
    box-shadow: var(--dd-shadow-sm);
    position: sticky;
    top: calc(var(--dd-header-h) + 32px);
}
.dd-detail__title {
    /* Display tier — fluid via rem so the detail H1 matches the
       list-page H1 in weight across viewport sizes. Sits between
       --text-lg (24px) and --text-xl (28px) at the root base. */
    font-size: 1.75rem;
    font-weight: 700;
    margin: 0 0 8px;
    letter-spacing: -0.01em;
    line-height: 1.25;
}
.dd-detail__rating {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
    display: flex;
    gap: 6px;
    align-items: center;
    margin-bottom: 8px;
}
.dd-detail__rating strong { color: var(--dd-text); font-weight: 600; }
.dd-detail__tagline {
    color: var(--dd-text-muted);
    margin: 0 0 14px;
    /* Subtitle-style copy in the right panel — bumped above
       --text-base so it reads as a subtitle, not a footnote.
       One-off between base (16px) and md (20px); kept as a
       fluid rem so it scales with the root. */
    font-size: 1.0625rem;
    line-height: 1.5;
}

/* Quotable factual lede (GEO-B4) — one citable sentence of hard facts under
   the title. SSR-only (the SPA repaints its own panel); kept compact and
   muted so it reads as a factual summary line, not body copy. */
.dd-detail__lede {
    color: var(--dd-text-muted);
    margin: 0 0 14px;
    font-size: var(--text-sm);
    line-height: 1.5;
}

/* ── Tag chips (clickable → /category/<id>) ─────────────────── */
.dd-detail__tags {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 14px;
}
.dd-detail__tag {
    display: inline-block;
    padding: 4px 10px;
    background: var(--dd-bg);
    border: 1px solid var(--dd-border);
    border-radius: 999px;
    font-size: var(--text-xs);
    font-weight: 500;
    color: var(--dd-text-muted);
    transition: background 0.12s ease, color 0.12s ease, border-color 0.12s ease;
}
.dd-detail__tag:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
    color: var(--dd-brand-dark);
}

.dd-detail__pill { margin-bottom: 14px; }

/* Date summary near the title — longer than a pill ("Sundays in June",
   "12 – 18 Jun", "12 Jun – 26 Jul · 8 dates"). Reads as a calendar line,
   not a chip. */
.dd-detail__dates {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0 0 14px;
    padding: 8px 12px;
    background: var(--dd-brand-soft);
    border-radius: 10px;
    color: var(--dd-brand-dark);
    font-weight: 600;
    font-size: var(--text-sm);
}
.dd-detail__dates::before {
    content: '🗓';
    font-size: 14px;
    line-height: 1;
}

/* ── Tour span — "From {city} to {city}" below the date count ──────
   For touring acts that visit 2+ cities. The date count and the span
   read as ONE rounded brand-soft box split by a hairline:

       🗓  12 Jun – 26 Jul · 38 dates
       ──────────────────────────────
       📍  From Alphen aan den Rijn to Zevenhuizen
*/
.dd-detail__dateblock {
    margin: 0 0 14px;
}
/* When joined to a span below, the date pill loses its own margin and
   its bottom corners square off so the two rows merge seamlessly. */
.dd-detail__dates--joined {
    margin: 0;
    border-bottom-left-radius: 0;
    border-bottom-right-radius: 0;
}
.dd-detail__tour-span {
    display: flex;
    align-items: center;
    gap: 6px;
    padding: 7px 12px;
    background: var(--dd-brand-soft);
    /* The hairline IS the separator line from the spec. */
    border-top: 1px solid rgba(63, 11, 131, 0.18);
    border-radius: 0 0 10px 10px;
    color: var(--dd-brand-dark);
    font-weight: 600;
    font-size: var(--text-xs);
}
.dd-detail__tour-span-pin {
    flex-shrink: 0;
    display: inline-flex;
}
.dd-detail__tour-span-pin > svg {
    width: 12px;
    height: 12px;
}

/* Clickable date summary — scrolls to the Performances list. Subtle
   hover lift so it reads as interactive without shouting. */
.dd-detail__dates--clickable {
    cursor: pointer;
    transition: filter 0.15s ease, transform 0.05s ease;
}
.dd-detail__dates--clickable:hover {
    filter: brightness(0.97);
}
.dd-detail__dates--clickable:active {
    transform: translateY(1px);
}
.dd-detail__dates--clickable:focus-visible {
    outline: 2px solid var(--dd-brand);
    outline-offset: 2px;
}

.dd-detail__price-card {
    background: var(--dd-bg);
    border-radius: 12px;
    padding: 16px;
    margin-top: 8px;
}

/* ── Live booking flow (Tiqets): date → timeslot → tickets → book ──
   Sits in the left column below the photos, above About. */
.dd-book {
    margin: 24px 0 8px;
    padding: 20px;
    border: 1px solid var(--dd-border);
    border-radius: var(--dd-radius);
    background: var(--dd-surface);
    box-shadow: var(--dd-shadow-sm);
}
.dd-book__title {
    font-size: var(--text-md);
    font-weight: 700;
    margin: 0 0 4px;
}
.dd-book__sub {
    margin: 0 0 14px;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dd-text-muted);
}
.dd-book__sub:empty { display: none; }
/* Month label above the date strip — updates as the strip is scrolled
   (JUN 2026 → JUL 2026). Mirrors the mobile calendar's month label. */
.dd-cal-month {
    margin: 0 0 8px;
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dd-text-muted);
}
.dd-cal-month:empty { display: none; }
.dd-book__soldout {
    margin: 0;
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}
.dd-book__label {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    color: var(--dd-text-muted);
    margin: 28px 0 8px;
}
/* date grid — wraps into rows (mouse-friendly; no horizontal scroll) */
/* Horizontal date strip — single scrollable row of equal-width cells,
   mirroring the mobile discovery calendar (discovery.html). The old 7×2
   `1fr` grid stretched cells to the container width, so a 14-day strip
   gave two rows of wide, mismatched cells; a fixed-width flex row keeps
   every day the same size and scrolls when they overflow. */
.dd-cal {
    display: flex;
    gap: 8px;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    scroll-snap-type: x proximity;
    /* Bleed to the card's border: negative margins cancel .dd-book's 20px
       padding, the matching inner padding keeps the first cell aligned
       with the title above. Net effect — cells run flush to the card edge
       and clip there as you scroll (the "more this way" affordance). */
    margin: 0 -20px;
    padding: 4px 20px;
    scroll-padding-left: 20px;
    scrollbar-width: none;        /* Firefox — hide the bar */
}
.dd-cal::-webkit-scrollbar { display: none; }
/* Desktop scroll affordances for the date strip. The shell is a
   content-width, relatively-positioned box; the strip inside still bleeds
   to the card edge. Prev/next arrows overlay the shell's left/right edges
   so a mouse user (no swipe, hidden scrollbar) can step through the dates. */
.dd-cal-shell { position: relative; }
.dd-cal-arrow {
    display: none;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 2;
    width: 34px;
    height: 34px;
    border-radius: 50%;
    /* Brand styling: light-purple fill, dark-purple border + chevron,
       soft purple-tinted shadow for lift. */
    border: 1px solid var(--dd-brand-dark, #3F0B83);
    background: var(--dd-brand-soft, #E5D0FF);
    box-shadow: 0 2px 8px rgba(63, 11, 131, 0.28);
    color: var(--dd-brand-dark, #3F0B83);
    cursor: pointer;
    align-items: center;
    justify-content: center;
    padding: 0;
    transition: opacity 0.15s ease, background 0.15s ease, box-shadow 0.15s ease;
}
/* SVG chevron centres perfectly inside the circle (text glyphs have
   asymmetric side-bearings that throw them off). */
.dd-cal-arrow svg {
    display: block;
    width: 16px;
    height: 16px;
}
.dd-cal-arrow--prev { left: -2px; }
.dd-cal-arrow--next { right: -2px; }
.dd-cal-arrow:hover {
    background: var(--dd-brand, #510EA8);
    color: #fff;
    box-shadow: 0 4px 12px rgba(63, 11, 131, 0.36);
}
/* Collapsed at an extreme (or when the strip doesn't overflow) — no dead
   control left hanging. */
.dd-cal-arrow--hidden { opacity: 0; pointer-events: none; }
@media (hover: hover) and (pointer: fine) {
    .dd-cal-shell--scrollable .dd-cal-arrow { display: flex; }
}
.dd-cal-cell {
    flex: 0 0 60px;               /* equal width, never shrink */
    height: 72px;
    scroll-snap-align: start;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    padding: 8px 4px;
    border: 1px solid var(--dd-border);
    border-radius: 10px;
    background: var(--dd-surface);
    color: var(--dd-text);
    line-height: 1.1;
    font-variant-numeric: tabular-nums;
}
.dd-cal-cell--bookable {
    border-color: var(--dd-brand);
    color: var(--dd-brand-dark);
    cursor: pointer;
    transition: background 0.12s ease;
}
/* Light-purple hover only on non-selected days; the selected day stays
   solid brand even on hover. */
.dd-cal-cell--bookable:not(.dd-cal-cell--selected):hover {
    background: var(--dd-brand-soft);
}
.dd-cal-cell--selected,
.dd-cal-cell--selected:hover {
    background: var(--dd-brand);
    border-color: var(--dd-brand);
    color: #fff;
}
.dd-cal-cell--muted {
    color: var(--dd-text-muted);
    opacity: 0.55;
    cursor: default;
}
.dd-cal-cell__weekday {
    font-size: var(--text-xs);
    text-transform: uppercase;
    letter-spacing: 0.03em;
    white-space: nowrap;          /* keep "VANDAAG" on one line in a 60px cell */
}
.dd-cal-cell__day { font-size: var(--text-md); font-weight: 700; }
/* trailing "Later →" cell — links out to Tiqets */
.dd-cal-cell--later {
    border-color: var(--dd-brand);
    color: var(--dd-brand-dark);
    cursor: pointer;
    text-decoration: none;
    transition: background 0.12s ease;
}
.dd-cal-cell--later:hover { background: var(--dd-brand-soft); }
.dd-cal-cell--later .dd-cal-cell__day { color: var(--dd-brand); }
/* timeslots */
.dd-book__slots { display: flex; flex-wrap: wrap; gap: 8px; }
.dd-book__slot {
    padding: 7px 14px;
    border: 1px solid var(--dd-border);
    border-radius: 999px;
    background: var(--dd-surface);
    color: var(--dd-text);
    font-size: var(--text-sm);
    font-weight: 600;
}
.dd-book__slot:hover { background: var(--dd-brand-soft); }
.dd-book__slot.is-active {
    background: var(--dd-brand);
    border-color: var(--dd-brand);
    color: #fff;
}
/* ticket variants + steppers */
.dd-book__tickets { list-style: none; margin: 0; padding: 0; }
.dd-book__variant {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--dd-border);
}
.dd-book__variant:last-child { border-bottom: 0; }
.dd-book__variant-info { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.dd-book__variant-label { font-weight: 600; font-size: var(--text-base); }
.dd-book__variant-desc { font-size: var(--text-xs); color: var(--dd-text-muted); }
.dd-book__variant-price { font-size: var(--text-sm); color: var(--dd-text-muted); }
/* Joined pill stepper — mirrors mobile's: brand border, square −/+
   buttons on a surface, brand-filled centre value. */
.dd-book__stepper {
    display: inline-flex;
    align-items: stretch;
    flex: 0 0 auto;
    min-height: 32px;
    border: 1px solid var(--dd-brand);
    border-radius: 999px;
    overflow: hidden;
}
.dd-book__step {
    appearance: none;
    -webkit-appearance: none;
    width: 32px;
    border: 0;
    background: var(--dd-surface);
    color: var(--dd-text);
    font-size: var(--text-base);
    font-weight: 600;
    line-height: 1;
    cursor: pointer;
    user-select: none;
    -webkit-user-select: none;
    touch-action: manipulation;
}
.dd-book__step:not(:disabled):active { background: var(--dd-brand-soft); }
.dd-book__step:disabled { color: var(--dd-text-muted); opacity: 0.5; cursor: default; }
.dd-book__qty {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 32px;
    padding: 0 4px;
    background: var(--dd-brand);
    color: #fff;
    font-size: var(--text-base);
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}
.dd-book__cta { width: 100%; margin-top: 18px; }
.dd-detail__price {
    /* Hero money — kept in px so it reads as a price headline
       independent of the body type scale. */
    font-size: 22px;
    font-weight: 700;
    color: var(--dd-text);
    margin-bottom: 12px;
    display: flex;
    align-items: baseline;
    gap: 6px;
    flex-wrap: wrap;
}
/* Visible rating stat (GEO-B3) — matches the AggregateRating schema. */
.dd-detail__rating-line {
    margin: 0 0 12px; color: var(--dd-text-muted); font-size: var(--text-sm);
}
.dd-detail__price--unavailable {
    color: var(--dd-text-muted);
    font-size: var(--text-base);
    font-weight: 500;
}
.dd-detail__price del { color: var(--dd-text-muted); font-weight: 400; font-size: var(--text-base); }
.dd-detail__price .dd-card__price-from {
    color: var(--dd-text-muted);
    font-weight: 400;
    font-size: var(--text-sm);
}

.dd-detail__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    width: 100%;
    padding: 12px 16px;
    background: var(--dd-brand);
    color: #fff;
    border-radius: 10px;
    font-size: var(--text-base);
    font-weight: 600;
    transition: background 0.15s ease, transform 0.12s ease;
}
.dd-detail__cta:hover { background: var(--dd-brand-dark); transform: translateY(-1px); }
.dd-detail__reopens {
    margin: 8px 0 0;
    font-size: var(--text-sm);
    color: var(--dd-text-muted);
}

.dd-detail__venue {
    margin-top: 16px;
    padding-top: 16px;
    border-top: 1px solid var(--dd-border);
    display: flex;
    gap: 12px;
}
.dd-detail__venue-icon { color: var(--dd-brand); flex: 0 0 auto; padding-top: 2px; }
.dd-detail__venue-text { min-width: 0; }
.dd-detail__venue-name { font-weight: 600; font-size: var(--text-sm); }
.dd-detail__venue-addr { color: var(--dd-text-muted); font-size: var(--text-sm); line-height: 1.7; }
/* City / country in the address loop back into the catalogue. */
.dd-detail__addr-link { color: var(--dd-brand); text-decoration: none; }
.dd-detail__addr-link:hover { text-decoration: underline; }

/* Audio-guide languages in the About block — label + flag chips. */
.dd-detail__audio-guide {
    margin: 14px 0 0; display: flex; flex-wrap: wrap; align-items: center;
    gap: 6px; color: var(--dd-text); font-size: var(--text-sm);
}
.dd-detail__audio-guide-label { color: var(--dd-text-muted); }
.dd-detail__lang-flag { font-size: var(--text-md); line-height: 1; cursor: default; }

/* "Good to know" consolidated practical info (GEO-B2). Label → value rows. */
.dd-detail__practical-list { margin: 0; display: flex; flex-direction: column; gap: 10px; }
.dd-detail__practical-row {
    display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap;
}
.dd-detail__practical-label {
    flex: 0 0 160px; color: var(--dd-text-muted);
    font-size: var(--text-sm); font-weight: 600;
}
.dd-detail__practical-icon { margin-right: 4px; }
.dd-detail__practical-value {
    flex: 1 1 200px; min-width: 0; color: var(--dd-text); font-size: var(--text-sm);
    display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
}

/* FAQ (GEO-B1) — auto-generated Q&A. Same DOM in SSR + SPA. */
.dd-detail__faq { margin: 0; }
.dd-detail__faq-q {
    font-weight: 600; color: var(--dd-text); font-size: var(--text-base);
    margin-top: 16px;
}
.dd-detail__faq-q:first-child { margin-top: 0; }
.dd-detail__faq-a {
    margin: 4px 0 0; color: var(--dd-text-muted); font-size: var(--text-sm);
    line-height: 1.5;
}

/* GEO-D2: "More things to do in <city>" sibling list on detail SSR body. */
.dd-detail__more-heading {
    font-size: var(--text-md); font-weight: 600; margin: 28px 0 8px;
}
.dd-detail__more-heading a { color: inherit; text-decoration: none; }
.dd-detail__more-heading a:hover { text-decoration: underline; }

/* Packages this product is part of — horizontal scroll strip of cards. */
.dd-detail__packages-desc {
    color: var(--dd-text-muted); font-size: var(--text-sm); margin: 0 0 14px;
}
.dd-detail__packages {
    display: flex; gap: 14px; overflow-x: auto; padding-bottom: 8px;
    scroll-snap-type: x proximity;
}
/* Exactly 3 cards fill the column width (2 × 14px gaps); the rest scroll. */
.dd-detail__packages > * { flex: 0 0 calc((100% - 28px) / 3); scroll-snap-align: start; }
/* SSR placeholder cards — replaced by real product cards on hydrate. */
.dd-detail__pkg-card {
    display: flex; flex-direction: column; gap: 6px;
    text-decoration: none; color: var(--dd-text);
    border: 1px solid var(--dd-border); border-radius: var(--dd-radius);
    overflow: hidden; background: var(--dd-surface);
}
.dd-detail__pkg-card-img {
    width: 100%; aspect-ratio: 16 / 10; object-fit: cover; display: block;
}
.dd-detail__pkg-card-title {
    padding: 0 10px; font-weight: 600; font-size: var(--text-sm);
}
.dd-detail__pkg-card-price {
    padding: 0 10px 10px; color: var(--dd-brand); font-size: var(--text-sm);
}


/* ── Near-me modal ──────────────────────────────────────────── */
.dd-modal-overlay {
    position: fixed;
    inset: 0;
    background: rgba(20, 12, 40, 0.45);
    backdrop-filter: blur(3px);
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    animation: dd-modal-fade 0.15s ease-out;
}
@keyframes dd-modal-fade { from { opacity: 0; } to { opacity: 1; } }

.dd-modal {
    width: 100%;
    max-width: 480px;
    background: var(--dd-surface);
    border-radius: 18px;
    padding: 28px 28px 24px;
    box-shadow: 0 20px 60px rgba(20, 12, 40, 0.25);
    position: relative;
    animation: dd-modal-up 0.18s ease-out;
}
@keyframes dd-modal-up {
    from { transform: translateY(12px); opacity: 0; }
    to   { transform: translateY(0);    opacity: 1; }
}

.dd-modal__close {
    position: absolute;
    top: 14px; right: 14px;
    width: 32px; height: 32px;
    display: inline-flex; align-items: center; justify-content: center;
    background: transparent;
    border: none;
    color: var(--dd-text-muted);
    border-radius: 8px;
    cursor: pointer;
    transition: background 0.12s ease, color 0.12s ease;
}
.dd-modal__close:hover { background: var(--dd-bg); color: var(--dd-text); }

.dd-modal__title {
    font-size: var(--text-md);
    font-weight: 700;
    margin: 0 0 6px;
    letter-spacing: -0.01em;
}
.dd-modal__sub {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
    margin: 0 0 18px;
    line-height: 1.5;
}

.dd-modal__search {
    position: relative;
    display: flex;
    align-items: center;
    margin-bottom: 12px;
}
.dd-modal__search svg {
    position: absolute;
    left: 14px;
    color: var(--dd-text-muted);
    pointer-events: none;
}
.dd-modal__search input {
    width: 100%;
    padding: 12px 14px 12px 42px;
    border: 1px solid var(--dd-border);
    border-radius: 10px;
    font-size: var(--text-base);
    background: var(--dd-bg);
    color: var(--dd-text);
}
.dd-modal__search input:focus {
    outline: none;
    background: var(--dd-surface);
    border-color: var(--dd-brand);
    box-shadow: 0 0 0 4px var(--dd-brand-soft);
}

.dd-modal__suggestion-btn {
    width: 100%;
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 12px 14px;
    border: 1px solid var(--dd-border);
    background: var(--dd-bg);
    border-radius: 10px;
    cursor: pointer;
    text-align: left;
    transition: background 0.12s ease, border-color 0.12s ease;
}
.dd-modal__suggestion-btn:hover {
    background: var(--dd-brand-soft);
    border-color: var(--dd-brand-soft);
}
/* Pin glyph in the modal suggestion row — kept in px (glyph, not body text). */
.dd-modal__suggestion-pin { font-size: 18px; }
.dd-modal__suggestion-text { font-weight: 600; }
.dd-modal__status {
    margin-top: 10px;
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
    min-height: 16px;
}

/* ── Toast (used by Near-me "Locating…") ───────────────────── */
.dd-toast {
    position: fixed;
    left: 50%;
    bottom: 32px;
    transform: translateX(-50%);
    background: var(--dd-text);
    color: #fff;
    padding: 10px 16px;
    border-radius: 999px;
    font-size: var(--text-sm);
    box-shadow: var(--dd-shadow-md);
    z-index: 90;
    animation: dd-toast-up 0.18s ease-out;
}
@keyframes dd-toast-up {
    from { transform: translate(-50%, 8px); opacity: 0; }
    to   { transform: translate(-50%, 0);   opacity: 1; }
}


/* ── Footer ─────────────────────────────────────────────────── */
.dd-footer {
    margin-top: 64px;
    background: var(--dd-surface);
    border-top: 1px solid var(--dd-border);
    color: var(--dd-text);
}
.dd-footer__inner {
    max-width: var(--dd-max-w);
    margin: 0 auto;
    padding: 36px 32px 24px;
    display: grid;
    grid-template-columns: minmax(280px, 1fr) auto;
    gap: 40px;
    align-items: start;
}
.dd-footer__brand {
    display: flex;
    align-items: center;
    gap: 14px;
    min-width: 0;
}
.dd-footer__logo {
    width: 44px; height: 44px; border-radius: 10px; flex: 0 0 auto;
}
.dd-footer__brand-name {
    font-weight: 700;
    font-size: var(--text-md);
    letter-spacing: -0.01em;
}
.dd-footer__tagline {
    color: var(--dd-text-muted);
    font-size: var(--text-sm);
    margin-top: 2px;
}

.dd-footer__nav {
    display: flex;
    gap: 56px;
    align-items: flex-start;
}
.dd-footer__col {
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 110px;
}
.dd-footer__col-title {
    font-size: var(--text-xs);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--dd-text-muted);
    margin: 0 0 6px;
}
.dd-footer__link {
    color: var(--dd-text);
    font-size: var(--text-sm);
    padding: 2px 0;
    transition: color 0.12s ease;
}
.dd-footer__link:hover { color: var(--dd-brand); }

.dd-footer__bottom {
    max-width: var(--dd-max-w);
    margin: 0 auto;
    padding: 16px 32px 32px;
    color: var(--dd-text-muted);
    font-size: var(--text-xs);
    border-top: 1px solid var(--dd-border);
    display: flex;
    align-items: center;
    gap: 8px;
    flex-wrap: wrap;
}
.dd-footer__sep { opacity: 0.5; }


/* ── Responsive ─────────────────────────────────────────────── */

/* iPad and small laptops: keep sidebar but narrower, fewer columns. */
@media (max-width: 1024px) {
    :root { --dd-sidebar-w: 220px; }
    .dd-grid { grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); }
}

/* Tablet / large phone: collapse sidebar to a horizontal strip above
   the content, keep grid at 2 columns minimum. */
@media (max-width: 720px) {
    .dd-layout {
        --dd-page-pad: 20px;
        grid-template-columns: 1fr;
        gap: 20px;
    }
    .dd-sidebar { position: static; }
    .dd-cat-list { max-height: none; }
    .dd-header { padding: 0 16px; gap: 10px; }
    .dd-header-left { gap: 16px; }
    .dd-nav { gap: 12px; }
    /* Drop the inline search box + chips; the toggle button takes over. */
    .dd-header-right { flex: 0 0 auto; }
    .dd-header-search,
    .dd-near-chip,
    .dd-city-chip { display: none; }
    .dd-search-toggle { display: inline-flex; }
    /* Revealed full-width search bar, slides out just below the header. */
    .dd-header.dd-search-open .dd-header-search {
        display: block;
        position: absolute;
        top: 100%;
        left: 0;
        right: 0;
        padding: 10px 16px;
        background: var(--dd-surface);
        border-bottom: 1px solid var(--dd-border);
        box-shadow: var(--dd-shadow-md);
        z-index: 9;
    }
    /* The toggle button already shows a magnifier — hide the in-field
       icon and let the input use its full padded width. */
    .dd-header.dd-search-open .dd-header-search__icon { display: none; }
    .dd-header.dd-search-open .dd-header-search input { padding-left: 12px; }
    .dd-section__title { font-size: var(--text-md); }
    .dd-grid { grid-template-columns: repeat(auto-fill, minmax(170px, 1fr)); gap: 14px; }
    /* Detail layout collapses: panel drops below the hero/main column
       and loses its sticky positioning so it doesn't fight the scroll. */
    .dd-detail__layout {
        grid-template-columns: 1fr;
        gap: 20px;
    }
    .dd-detail__panel { position: static; }
    /* Mobile reading order in the main column: media → About → What's
       included → the inline booking widget ("When do you want to go?") →
       packages / showtimes. The booking widget (#dd-detail-avail) sits above
       About in DOM (right under the photos, which reads well on desktop next
       to the sticky CTA), but on a narrow screen the descriptive content
       should come first. Flex `order` reorders without touching the DOM. */
    .dd-detail__main { display: flex; flex-direction: column; }
    .dd-detail__main > * { order: 3; }
    .dd-detail__main > .dd-detail__hero,
    .dd-detail__main > .dd-detail__thumbs { order: 1; }
    .dd-detail__main > .dd-detail__about-section,
    .dd-detail__main > .dd-detail__included-section { order: 2; }
    .dd-footer__inner {
        grid-template-columns: 1fr;
        gap: 28px;
        padding: 28px 20px 20px;
    }
    .dd-footer__nav { gap: 32px; flex-wrap: wrap; }
    .dd-footer__bottom { padding: 14px 20px 24px; }
}

/* Phone-web: tighten paddings, single-col rail, larger touch targets. */
@media (max-width: 480px) {
    .dd-layout { --dd-page-pad: 14px; gap: 16px; }
    .dd-section { margin-bottom: 28px; }
    .dd-grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
    .dd-card__body { padding: 10px 12px 12px; }
    .dd-card__title { font-size: var(--text-sm); }
    .dd-card__tagline { font-size: var(--text-xs); }
    .dd-rail { grid-auto-columns: minmax(180px, 1fr); }
    .dd-city-chip { padding: 6px 10px; font-size: var(--text-xs); }
}
