/* ============================================================
   Direo-style Directory Listing Theme (Bootstrap 5 companion)
   UI-only recreation — original CSS
   ============================================================ */

:root {
    --dl-primary: #3d52a8;
    --dl-primary-dark: #2e3f85;
    --dl-primary-light: #e9edfb;
    --dl-accent: #fa7c50;
    --dl-dark: #272b41;
    --dl-body: #5a6779;
    --dl-muted: #9299b8;
    --dl-border: #e4e8f1;
    --dl-bg-soft: #f6f7fb;
    --dl-star: #ffb400;
}

body {
    font-family: "Segoe UI", system-ui, -apple-system, sans-serif;
    color: var(--dl-body);
    background: #fff;
}

h1, h2, h3, h4, h5, h6 { color: var(--dl-dark); font-weight: 700; }

a { text-decoration: none; }

.btn-dl-primary {
    background: var(--dl-primary);
    border: 1px solid var(--dl-primary);
    color: #fff;
    font-weight: 600;
    border-radius: 6px;
    padding: .65rem 1.4rem;
}
.btn-dl-primary:hover { background: var(--dl-primary-dark); color: #fff; }

/*
 * Leaflet ships `.leaflet-container a { color: #0078A8 }`, which out-specifies
 * .btn-dl-primary and renders the label blue on a blue button — invisible
 * inside map popups. Restate the colour at matching specificity.
 */
.leaflet-container a.btn-dl-primary,
.leaflet-popup-content a.btn-dl-primary {
    color: #fff;
}

/*
 * "View Listing" — white ground, blue outline, black label; fills solid blue
 * with the glow on hover. Its own class rather than a change to
 * .btn-dl-primary, which would restyle every primary button on the site.
 */
.btn-view-listing,
.leaflet-container a.btn-view-listing,
.leaflet-popup-content a.btn-view-listing {
    background: #fff;
    border: 1.5px solid var(--dl-primary);
    color: #17181d;
    font-weight: 600;
    border-radius: 6px;
    transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
}

.btn-view-listing:hover,
.btn-view-listing:focus-visible,
.leaflet-container a.btn-view-listing:hover,
.leaflet-popup-content a.btn-view-listing:hover {
    background: var(--dl-primary);
    color: #fff;
    border-color: var(--dl-primary);
    box-shadow: 0 0 0 3px rgba(61, 82, 168, .22), 0 0 16px 2px rgba(61, 82, 168, .55);
}

@media (prefers-reduced-motion: reduce) {
    .btn-view-listing { transition: none; }
}

/* Outer glow on hover, for the popup button and everywhere else alike */
.btn-dl-primary,
.leaflet-container a.btn-dl-primary {
    transition: background-color .2s ease, box-shadow .2s ease;
}
.btn-dl-primary:hover,
.btn-dl-primary:focus-visible,
.leaflet-container a.btn-dl-primary:hover,
.leaflet-popup-content a.btn-dl-primary:hover {
    color: #fff;
    box-shadow: 0 0 0 3px rgba(61, 82, 168, .22), 0 0 16px 2px rgba(61, 82, 168, .55);
}

@media (prefers-reduced-motion: reduce) {
    .btn-dl-primary,
    .leaflet-container a.btn-dl-primary { transition: none; }
}

.btn-dl-outline {
    background: transparent;
    border: 1px solid rgba(255, 255, 255, .6);
    color: #fff;
    font-weight: 600;
    border-radius: 6px;
    padding: .65rem 1.4rem;
}
.btn-dl-outline:hover { background: #fff; color: var(--dl-primary); }

/* The light-background cousin of .btn-dl-outline.

   .btn-dl-outline is white text on a translucent white border, which only
   works on the dark hero. Used on a white card - as the related-category and
   town chips were - it is white on white and simply cannot be seen. */
.btn-dl-chip {
    background: #fff;
    border: 1px solid var(--dl-border);
    color: var(--dl-primary);
    font-weight: 500;
    border-radius: 999px;
    padding: .4rem 1rem;
    transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}

.btn-dl-chip:hover,
.btn-dl-chip:focus-visible {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    color: #fff;
}

.btn-dl-chip:focus-visible {
    outline: 2px solid var(--dl-dark);
    outline-offset: 2px;
}

.section-pad { padding: 90px 0; }
.section-title h2 { font-size: 2.1rem; margin-bottom: .6rem; }
.section-title p { color: var(--dl-muted); max-width: 560px; margin: 0 auto; }

/* ---------- Navbar ---------- */
.dl-navbar {
    position: absolute;
    top: 0; left: 0; right: 0;
    z-index: 1030;
    background: transparent;
    padding: 1rem 0;
}
.dl-navbar .navbar-brand {
    color: #fff;
    font-size: 1.6rem;
    font-weight: 800;
    letter-spacing: .5px;
}
.dl-navbar .navbar-brand i { color: var(--dl-accent); }
.brand-logo {
    height: 46px;
    width: 46px;
    object-fit: cover;
    border-radius: 12px;
    background: #fff;
    box-shadow: 0 4px 14px rgba(0, 0, 0, .18);
}
.dl-navbar .nav-link {
    color: rgba(255, 255, 255, .85);
    font-weight: 600;
    margin: 0 .35rem;
}
.dl-navbar .nav-link:hover,
.dl-navbar .nav-link.active { color: #fff; }
.dl-navbar .dropdown-menu {
    border: none;
    border-radius: 8px;
    box-shadow: 0 12px 34px rgba(39, 43, 65, .15);
}
.dl-navbar.solid {
    position: sticky;
    background: var(--dl-dark);
}

/* ---------- Navbar: follows the page once you scroll ----------
 *
 * At the top of a hero page the bar stays transparent and overlays the image;
 * past the fold it turns solid and rides along.
 *
 * Desktop swaps absolute -> fixed. Both are out of normal flow, so the bar
 * detaching costs the page no height and the content underneath never jumps.
 * Mobile is the case that bites: there the bar is `relative` and therefore in
 * flow, so the same swap would yank it out and pull the page up by its height.
 * That breakpoint uses native sticky instead (see the media query below), which
 * holds its space and needs no compensation at all.
 */
.dl-navbar {
    transition: background-color .25s ease, box-shadow .25s ease, padding .25s ease;
}
.dl-navbar.is-stuck {
    position: fixed;
    background: var(--dl-dark);
    padding: .55rem 0;
    box-shadow: 0 6px 24px rgba(39, 43, 65, .22);
}

/* Slide in rather than appear, so the switch to fixed doesn't read as a flicker. */
@media (prefers-reduced-motion: no-preference) {
    .dl-navbar.is-stuck {
        animation: dl-navbar-drop .28s ease-out;
    }
}
@keyframes dl-navbar-drop {
    from { transform: translateY(-100%); }
    to   { transform: translateY(0); }
}

/* NOTE: no overflow on .navbar-collapse at desktop widths.
 *
 * It briefly carried `overflow-y: auto` here to stop a tall opened menu running
 * off the bottom of the shrunken bar. But the signed-in profile dropdown lives
 * inside that same element and is absolutely positioned below it, so the scroll
 * container clipped it — the menu opened and was invisible, but only once the
 * header had stuck. At desktop widths the collapse is a single flex row that
 * never needs to scroll, so there is nothing to constrain. The mobile case,
 * where the menu really does expand vertically, is handled in the breakpoint
 * below along with making its dropdowns render in flow. */

/* ---------- Hero ---------- */
.dl-hero {
    position: relative;
    min-height: 640px;
    display: flex;
    align-items: center;
    background:
        linear-gradient(rgba(24, 33, 78, .8), rgba(24, 33, 78, .8)),
        url("../images/hero-bg.png") center/cover no-repeat;
    padding: 140px 0 100px;
}

/* With slides the static image is redundant, and the tint moves onto the
 * slides themselves so it fades along with them. Extra bottom padding makes
 * room for the caption pinned at the foot of the section. */
.dl-hero.has-slides {
    background: var(--dl-dark);
    padding: 130px 0 230px;
    overflow: hidden;
    flex-direction: column;
    justify-content: center;
}
.dl-hero.has-slides > .container { position: relative; z-index: 2; }

.hero-slides { position: absolute; inset: 0; z-index: 0; }
.hero-slide {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center;
    opacity: 0;
    /* Slow, wide fade: a hard cut between two photographs behind text is
     * jarring, and a long overlap reads as one continuous backdrop. */
    transition: opacity 1.2s ease-in-out;
    /* Held on the layer itself so the crossfade dissolves the tint too. */
    box-shadow: inset 0 0 0 100vmax rgba(24, 33, 78, .72);
}
.hero-slide.is-active { opacity: 1; }

/* A photograph can be light anywhere, so the caption gets its own gradient
 * rather than relying on the flat tint to guarantee contrast. */
.dl-hero.has-slides::after {
    content: '';
    position: absolute;
    left: 0; right: 0; bottom: 0;
    height: 62%;
    background: linear-gradient(to bottom, rgba(16, 22, 52, 0), rgba(16, 22, 52, .92));
    z-index: 1;
    pointer-events: none;
}

/* ---------- Hero: the showcased listing ---------- */
.hero-showcase {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    z-index: 3;
    padding-bottom: 2rem;
}
.hero-showcase-inner {
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 1.5rem;
    flex-wrap: wrap;
}

/* Slides are stacked so the block keeps the height of its tallest caption and
 * the dots never jump as names of different lengths come round. */
.hero-showcase-card { position: relative; flex: 1 1 auto; min-height: 132px; }
.hero-showcase-item {
    position: absolute;
    left: 0; bottom: 0;
    width: 100%;
    opacity: 0;
    transform: translateY(10px);
    transition: opacity .5s ease, transform .5s ease;
    pointer-events: none;   /* only the visible caption is clickable */
}
.hero-showcase-item.is-active {
    opacity: 1;
    transform: translateY(0);
    pointer-events: auto;
}

.hero-showcase-meta {
    display: flex;
    align-items: center;
    gap: .4rem;
    flex-wrap: wrap;
    margin-bottom: .55rem;
}
.hs-cat, .hs-sub {
    display: inline-flex;
    align-items: center;
    gap: .35rem;
    font-size: .74rem;
    font-weight: 700;
    letter-spacing: .02em;
    padding: .28rem .7rem;
    border-radius: 30px;
    white-space: nowrap;
}
/* The category carries its own colour; sub-categories stay quiet so the pair
 * reads as one primary plus its qualifiers, not three competing labels. */
.hs-cat { background: var(--cat, var(--dl-primary)); color: #fff; }
.hs-sub {
    background: rgba(255, 255, 255, .16);
    color: #fff;
    border: 1px solid rgba(255, 255, 255, .3);
    font-weight: 600;
}

.hero-showcase-name {
    color: #fff;
    font-size: 2rem;
    font-weight: 800;
    line-height: 1.15;
    margin: 0 0 .45rem;
    text-shadow: 0 2px 18px rgba(0, 0, 0, .45);
    text-wrap: balance;
}

.hero-showcase-rating {
    display: flex;
    align-items: center;
    gap: .45rem;
    color: #fff;
    font-size: .9rem;
    margin-bottom: 1rem;
}
.hs-stars { color: var(--dl-star); letter-spacing: .06em; }
.hs-count { color: rgba(255, 255, 255, .75); }

.btn-hero-view {
    display: inline-flex;
    align-items: center;
    background: #fff;
    color: var(--dl-dark);
    border: 2px solid #fff;
    font-weight: 700;
    padding: .6rem 1.4rem;
    border-radius: 8px;
    transition: background-color .18s ease, color .18s ease, box-shadow .18s ease;
}
.btn-hero-view:hover,
.btn-hero-view:focus-visible {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    color: #fff;
    box-shadow: 0 8px 26px rgba(0, 0, 0, .3);
}

.hero-dots { display: flex; gap: .5rem; padding-bottom: .4rem; }
.hero-dot {
    width: 34px;
    height: 4px;
    border: none;
    padding: 0;
    border-radius: 4px;
    background: rgba(255, 255, 255, .35);
    cursor: pointer;
    transition: background-color .2s ease, width .2s ease;
}
.hero-dot:hover { background: rgba(255, 255, 255, .6); }
.hero-dot.is-active { background: #fff; width: 52px; }
.hero-dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* A slideshow that moves on its own is exactly what reduced-motion is for:
 * the JS stops advancing, so this only has to drop the transitions. */
@media (prefers-reduced-motion: reduce) {
    .hero-slide,
    .hero-showcase-item { transition: none; }
}
.dl-hero h1 {
    color: #fff;
    font-size: 2.9rem;
    font-weight: 800;
}
.dl-hero .lead { color: rgba(255, 255, 255, .8); }

.dl-search-box {
    background: #fff;
    border-radius: 10px;
    padding: 10px;
    box-shadow: 0 18px 48px rgba(0, 0, 0, .25);
}
.dl-search-box .form-control,
.dl-search-box .form-select {
    border: none;
    box-shadow: none;
    padding: .9rem 1rem;
    color: var(--dl-dark);
}

/* Slimmer than the original: with listings showing behind it, a full-width
 * slab of white form was taking the eye first and burying the photographs. */
.dl-search-box.compact { padding: 6px; border-radius: 8px; }
.dl-search-box.compact .form-control,
.dl-search-box.compact .form-select {
    padding: .62rem .85rem;
    font-size: .92rem;
}
.dl-search-box.compact .btn { padding: .62rem 1rem; font-size: .92rem; }
.dl-hero.has-slides h1 { font-size: 2.35rem; }
.dl-hero.has-slides .lead { font-size: 1rem; }
.dl-search-box .divider { border-left: 1px solid var(--dl-border); }
.dl-hero .filter-link {
    color: rgba(255, 255, 255, .85);
    font-weight: 600;
    font-size: .9rem;
}
.dl-hero .filter-link:hover { color: #fff; }

.dl-hero .hero-cats a {
    color: rgba(255, 255, 255, .9);
    background: rgba(255, 255, 255, .12);
    border: 1px solid rgba(255, 255, 255, .25);
    border-radius: 30px;
    padding: .45rem 1.1rem;
    font-size: .875rem;
    font-weight: 600;
    display: inline-block;
    margin: .25rem;
}
.dl-hero .hero-cats a:hover { background: #fff; color: var(--dl-primary); }

/* ---------- Category cards ---------- */
/* Deliberately compact. There are nine of these and the point of the section
   is to let someone take in the whole menu at a glance - at 2.2rem of padding
   and a 2.2rem icon each card ran to 244px and the grid needed a scroll to
   read. Nothing was removed; the air was. */
.cat-card {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    text-align: center;
    padding: 1.15rem .7rem;
    transition: all .25s ease;
    display: block;
    height: 100%;
}
.cat-card i {
    font-size: 1.65rem;
    /* The per-category colour arrives as --cat-colour from the template.
       Kept in a custom property rather than an inline colour so the hover
       state below can actually win. */
    color: var(--cat-colour, var(--dl-primary));
    display: block;
    margin-bottom: .4rem;
    line-height: 1;
    transition: inherit;
}
.cat-card h6 {
    margin-bottom: .1rem;
    font-size: .92rem;
    line-height: 1.3;
}
.cat-card span { color: var(--dl-muted); font-size: .78rem; }

/* The sub-category line is a hint, not a list: two lines is the most it may
   add before it starts setting the height of every card in the row. */
.cat-card .cat-subs {
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    font-size: .69rem;
    line-height: 1.35;
    margin-top: .3rem;
}
.cat-card:hover {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    transform: translateY(-6px);
    box-shadow: 0 16px 34px rgba(61, 82, 168, .35);
}
/* On hover the card fills with the brand blue, so everything on it inverts -
   including the icon, which used to keep its category colour and disappear. */
.cat-card:hover i,
.cat-card:hover h6,
.cat-card:hover span,
.cat-card:focus-visible i,
.cat-card:focus-visible h6,
.cat-card:focus-visible span {
    color: #fff;
}

/* Keyboard users get the same treatment as the mouse. */
.cat-card:focus-visible {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    outline: 2px solid var(--dl-dark);
    outline-offset: 2px;
}

/* ---------- Listing cards ---------- */
.listing-card {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    overflow: hidden;
    transition: all .25s ease;
    height: 100%;
    display: flex;
    flex-direction: column;
}
.listing-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 18px 40px rgba(39, 43, 65, .12);
}
.listing-card .thumb {
    position: relative;
    height: 210px;
    background-size: cover;
    background-position: center;
}
.listing-card .badge-featured {
    position: absolute;
    top: 14px; left: 14px;
    background: var(--dl-accent);
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
    text-transform: uppercase;
    padding: .35rem .7rem;
    border-radius: 4px;
}
.listing-card .badge-open {
    position: absolute;
    top: 14px; right: 14px;
    background: #23c58a;
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
    padding: .35rem .7rem;
    border-radius: 4px;
}
.listing-card .avatar {
    position: absolute;
    bottom: -22px; left: 18px;
    width: 46px; height: 46px;
    border-radius: 50%;
    border: 3px solid #fff;
    background: var(--dl-primary);
    color: #fff;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 4px 12px rgba(0, 0, 0, .2);
}
.listing-card .body { padding: 2rem 1.25rem 1rem; flex: 1; }
.listing-card .body h5 { font-size: 1.1rem; margin-bottom: .4rem; }
.listing-card .body h5 a { color: var(--dl-dark); }
.listing-card .body h5 a:hover { color: var(--dl-primary); }
.listing-card .rating { color: var(--dl-star); font-size: .85rem; }
.listing-card .rating .count { color: var(--dl-muted); margin-left: .3rem; }
.listing-card .meta {
    list-style: none;
    padding: 0;
    margin: .8rem 0 0;
    font-size: .875rem;
    color: var(--dl-body);
}
.listing-card .meta li { margin-bottom: .35rem; }
/* inline-block, or the width is simply ignored — which is why the location and
   phone text sat hard against their icons. The fixed box also keeps the two
   rows' text starting at the same x, whatever the glyph's own width. */
.listing-card .meta i {
    color: var(--dl-primary);
    display: inline-block;
    width: 1.05rem;
    margin-right: .45rem;
    text-align: center;
}
.listing-card .foot {
    border-top: 1px solid var(--dl-border);
    padding: .8rem 1.25rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    font-size: .85rem;
}
.listing-card .foot .cat { color: var(--dl-body); font-weight: 600; }
.listing-card .foot .cat i { color: var(--dl-primary); margin-right: .35rem; }
.listing-card .price { color: var(--dl-primary); font-weight: 700; }

/* ---------- Destination cards ---------- */
.dest-card {
    position: relative;
    border-radius: 10px;
    overflow: hidden;
    display: block;
    height: 260px;
    background-size: cover;
    background-position: center;
}
.dest-card::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 30%, rgba(20, 15, 48, .85));
    transition: background .25s ease;
}
.dest-card:hover::after { background: rgba(61, 82, 168, .75); }
.dest-card .info {
    position: absolute;
    bottom: 18px; left: 20px;
    z-index: 2;
    color: #fff;
}
.dest-card .info h5 { color: #fff; margin-bottom: .15rem; }
.dest-card .info span { font-size: .85rem; opacity: .85; }
.dest-card.tall { height: 545px; }

/* ---------- Why us ---------- */
.why-card {
    background: #fff;
    border-radius: 10px;
    padding: 2.5rem 2rem;
    height: 100%;
    box-shadow: 0 6px 24px rgba(39, 43, 65, .06);
    text-align: center;
}
.why-card .icon {
    width: 76px; height: 76px;
    border-radius: 50%;
    background: var(--dl-primary-light);
    color: var(--dl-primary);
    font-size: 1.9rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.2rem;
}
.why-card p { font-size: .925rem; }
.why-card a { color: var(--dl-primary); font-weight: 700; font-size: .9rem; }

/* ---------- Testimonials ---------- */
.testimonial-section {
    /*
     * The overlay stays at .87. It looks heavy, and it is: under it the photo
     * reads as texture rather than a picture. That is deliberate — white body
     * text over this navy at .87 clears 5:1 contrast, and lightening it to
     * show more of the photo drops normal-size text under the 4.5:1 minimum.
     */
    background:
        linear-gradient(rgba(24, 33, 78, .87), rgba(24, 33, 78, .87)),
        url("../images/testimonials-bg.png") center/cover no-repeat;
    color: #fff;
}
.testimonial-section .section-title h2,
.testimonial-section .section-title p { color: #fff; }
.testi-card {
    background: rgba(255, 255, 255, .08);
    border: 1px solid rgba(255, 255, 255, .18);
    border-radius: 10px;
    padding: 2rem;
    height: 100%;
}
.testi-card .quote { font-style: italic; color: rgba(255, 255, 255, .9); }
.testi-card .who { display: flex; align-items: center; margin-top: 1.4rem; }
.testi-card .who .avatar {
    width: 52px; height: 52px;
    border-radius: 50%;
    background: var(--dl-accent);
    color: #fff;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    margin-right: .9rem;
}
.testi-card .who h6 { color: #fff; margin: 0; }
.testi-card .who span { font-size: .82rem; opacity: .8; }
.testi-card .stars { color: var(--dl-star); margin-bottom: .8rem; }

/* ---------- CTA ---------- */
.dl-cta {
    background: linear-gradient(120deg, var(--dl-primary), #5d78d8);
    border-radius: 14px;
    padding: 3.5rem 2.5rem;
    color: #fff;
}
.dl-cta h2 { color: #fff; }
.dl-cta .btn-light { font-weight: 700; color: var(--dl-primary); }

/* ---------- Footer ---------- */
.dl-footer {
    background: #1b1e2f;
    color: #a3aac2;
    padding: 80px 0 0;
    font-size: .925rem;
}
.dl-footer h6 {
    color: #fff;
    text-transform: uppercase;
    font-size: .85rem;
    letter-spacing: 1px;
    margin-bottom: 1.3rem;
}
.dl-footer a { color: #a3aac2; display: block; margin-bottom: .6rem; }
.dl-footer a:hover { color: #fff; }
.dl-footer .brand { color: #fff; font-size: 1.5rem; font-weight: 800; }
.dl-footer .brand i { color: var(--dl-accent); }
.dl-footer .social a {
    display: inline-flex;
    width: 38px; height: 38px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .08);
    color: #fff;
    align-items: center;
    justify-content: center;
    margin-right: .5rem;
}
.dl-footer .social a:hover { background: var(--dl-primary); }
.dl-footer .copy {
    border-top: 1px solid rgba(255, 255, 255, .08);
    margin-top: 60px;
    padding: 1.4rem 0;
    text-align: center;
    font-size: .85rem;
}

/* ---------- Page header (inner pages) ---------- */
/*
 * The band at the top of every inner page.
 *
 * This used to be a flat navy wash over a random picsum photo, which made
 * fifteen different pages open on the same anonymous grey rectangle — and
 * pulled a placeholder image from a third party on every load. It is now built
 * entirely from the brand palette: a deep indigo base, two soft glows for
 * depth, and a fine dot grid that fades out before it reaches the text.
 */
.page-header {
    position: relative;
    overflow: hidden;
    padding: 170px 0 90px;
    color: #fff;
    text-align: center;
    background:
        radial-gradient(1100px 440px at 12% -15%, rgba(96, 118, 205, .55), transparent 62%),
        radial-gradient(820px 360px at 88% -5%, rgba(250, 124, 80, .26), transparent 60%),
        linear-gradient(158deg, #18214e 0%, #253168 48%, #1a2350 100%);
}

/* Dot grid, masked so it never competes with the heading. */
.page-header::before {
    content: "";
    position: absolute;
    inset: 0;
    background-image: radial-gradient(rgba(255, 255, 255, .11) 1px, transparent 1px);
    background-size: 22px 22px;
    -webkit-mask-image: linear-gradient(180deg, rgba(0, 0, 0, .7), transparent 72%);
    mask-image: linear-gradient(180deg, rgba(0, 0, 0, .7), transparent 72%);
    pointer-events: none;
}

/* A hairline of accent where the band meets the page below it. */
.page-header::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 3px;
    background: linear-gradient(90deg, var(--dl-primary), var(--dl-accent), var(--dl-primary));
    opacity: .85;
}

.page-header .container { position: relative; z-index: 1; }

.page-header h1 {
    color: #fff;
    font-weight: 800;
    letter-spacing: -.02em;
    text-shadow: 0 2px 18px rgba(0, 0, 0, .28);
    margin-bottom: 0;
}

/* Short accent rule under the title, so the heading has a base to sit on. */
.page-header h1::after {
    content: "";
    display: block;
    width: 62px;
    height: 4px;
    margin: .9rem auto 0;
    border-radius: 999px;
    background: linear-gradient(90deg, var(--dl-accent), #ffb894);
}

.page-header nav { display: flex; justify-content: center; margin-top: 1.15rem; }

/* The crumb trail reads as one object rather than loose text on a gradient. */
.page-header .breadcrumb {
    justify-content: center;
    margin: 0;
    padding: .42rem 1rem;
    border-radius: 999px;
    font-size: .82rem;
    background: rgba(255, 255, 255, .10);
    border: 1px solid rgba(255, 255, 255, .18);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
}
.page-header .breadcrumb-item, .page-header .breadcrumb-item a { color: rgba(255, 255, 255, .82); }
.page-header .breadcrumb-item a { text-decoration: none; transition: color .18s ease; }
.page-header .breadcrumb-item a:hover { color: #fff; }
.page-header .breadcrumb-item.active { color: #fff; font-weight: 600; }
.page-header .breadcrumb-item + .breadcrumb-item::before { color: rgba(255, 255, 255, .45); }

@media (max-width: 575.98px) {
    .page-header { padding: 140px 0 64px; }
    .page-header h1 { font-size: 1.85rem; }
}

@media (prefers-reduced-motion: reduce) {
    .page-header .breadcrumb-item a { transition: none; }
}

/* ---------- Listing detail ---------- */
.detail-hero {
    position: relative;
    min-height: 420px;
    display: flex;
    align-items: flex-end;
    background-size: cover;
    background-position: center;
    padding: 160px 0 40px;
}
.detail-hero::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, rgba(20, 24, 50, .35) 0%, rgba(20, 24, 50, .88) 100%);
}
.detail-hero .container { position: relative; z-index: 2; }
.detail-hero h1 { color: #fff; font-weight: 800; margin-bottom: .4rem; }
.detail-hero .meta-line { color: rgba(255, 255, 255, .85); font-size: .95rem; }
.detail-hero .meta-line i { margin-right: .35rem; }
.detail-hero .rating { color: var(--dl-star); }
.detail-hero .rating .count { color: rgba(255, 255, 255, .8); margin-left: .35rem; }
.detail-hero .badge-cat {
    background: var(--dl-primary);
    color: #fff;
    font-size: .78rem;
    font-weight: 700;
    padding: .4rem .85rem;
    border-radius: 4px;
    display: inline-block;
    margin-bottom: .8rem;
}

.info-card {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    padding: 1.75rem;
    margin-bottom: 1.5rem;
}
.info-card h4 {
    font-size: 1.15rem;
    margin-bottom: 1.1rem;
    padding-bottom: .8rem;
    border-bottom: 1px solid var(--dl-border);
}
.info-card .contact-list { list-style: none; padding: 0; margin: 0; }
.info-card .contact-list li {
    display: flex;
    align-items: flex-start;
    margin-bottom: .9rem;
    font-size: .925rem;
}
.info-card .contact-list li:last-child { margin-bottom: 0; }
.info-card .contact-list i {
    color: var(--dl-primary);
    width: 26px;
    flex-shrink: 0;
    margin-top: .1rem;
}

.amenity {
    display: inline-block;
    background: var(--dl-bg-soft);
    border: 1px solid var(--dl-border);
    border-radius: 30px;
    padding: .45rem 1rem;
    font-size: .85rem;
    color: var(--dl-body);
    margin: 0 .4rem .6rem 0;
}
.amenity i { color: #23c58a; margin-right: .4rem; }

.gallery-grid img {
    width: 100%;
    height: 170px;
    object-fit: cover;
    border-radius: 8px;
}

.hours-table { width: 100%; font-size: .9rem; }
.hours-table td { padding: .5rem 0; border-bottom: 1px dashed var(--dl-border); }
.hours-table tr:last-child td { border-bottom: none; }
.hours-table .day { color: var(--dl-dark); font-weight: 600; }
.hours-table .time { text-align: right; }
.hours-table .closed { color: #e05260; font-weight: 600; }

.review-item {
    display: flex;
    gap: 1rem;
    padding: 1.25rem 0;
    border-bottom: 1px solid var(--dl-border);
}
.review-item:last-of-type { border-bottom: none; }
.review-item .avatar {
    width: 52px; height: 52px;
    border-radius: 50%;
    background: var(--dl-primary-light);
    color: var(--dl-primary);
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}
.review-item h6 { margin-bottom: .1rem; }
.review-item .when { font-size: .8rem; color: var(--dl-muted); }
.review-item .stars { color: var(--dl-star); font-size: .8rem; margin: .25rem 0 .4rem; }
.review-item p { font-size: .925rem; margin: 0; }

.map-placeholder {
    height: 220px;
    border-radius: 8px;
    background:
        linear-gradient(rgba(61, 82, 168, .15), rgba(61, 82, 168, .15)),
        repeating-linear-gradient(0deg, #eef1f8 0 34px, #e2e7f3 34px 35px),
        repeating-linear-gradient(90deg, #eef1f8 0 34px, #e2e7f3 34px 35px);
    display: flex;
    align-items: center;
    justify-content: center;
    color: var(--dl-primary);
    font-weight: 600;
}
.map-placeholder i { font-size: 1.6rem; margin-right: .5rem; }

/* ---------- Articles ---------- */
.article-card {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    overflow: hidden;
    height: 100%;
    display: flex;
    flex-direction: column;
    transition: all .25s ease;
}
.article-card:hover {
    transform: translateY(-5px);
    box-shadow: 0 18px 40px rgba(39, 43, 65, .12);
}
.article-card .thumb {
    display: block;
    height: 200px;
    background-size: cover;
    background-position: center;
    position: relative;
}
.article-card .thumb .badge-cat {
    position: absolute;
    top: 14px; left: 14px;
    background: var(--dl-primary);
    color: #fff;
    font-size: .72rem;
    font-weight: 700;
    padding: .35rem .7rem;
    border-radius: 4px;
}
.article-card .body { padding: 1.4rem 1.25rem; flex: 1; }
.article-card .body h5 { font-size: 1.05rem; line-height: 1.45; }
.article-card .body h5 a { color: var(--dl-dark); }
.article-card .body h5 a:hover { color: var(--dl-primary); }
.article-card .excerpt { font-size: .9rem; color: var(--dl-body); margin: .5rem 0 0; }
.article-card .foot {
    border-top: 1px solid var(--dl-border);
    padding: .8rem 1.25rem;
    display: flex;
    justify-content: space-between;
    font-size: .8rem;
    color: var(--dl-muted);
}

.article-body p {
    font-size: 1.02rem;
    line-height: 1.85;
    margin-bottom: 1.4rem;
}
.article-meta {
    display: flex;
    align-items: center;
    gap: 1.2rem;
    font-size: .875rem;
    color: var(--dl-muted);
}
.article-meta .avatar {
    width: 44px; height: 44px;
    border-radius: 50%;
    background: var(--dl-primary);
    color: #fff;
    font-weight: 700;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

/* ---------- Team / values ---------- */
.team-card {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    text-align: center;
    padding: 2rem 1.5rem;
    height: 100%;
}
.team-card .avatar {
    width: 84px; height: 84px;
    border-radius: 50%;
    background: var(--dl-primary-light);
    color: var(--dl-primary);
    font-size: 1.6rem;
    font-weight: 800;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1rem;
}
.team-card span { color: var(--dl-muted); font-size: .85rem; }

/* ---------- Social sign-in buttons ---------- */
.social-login { margin-top: 1.25rem; }

/* Rule either side of the label, drawn with borders on the pseudo-elements so
 * it stays centred whatever the label says. */
.social-login-divider {
    display: flex;
    align-items: center;
    gap: .75rem;
    margin-bottom: .85rem;
    color: var(--dl-muted);
    font-size: .8rem;
}
.social-login-divider::before,
.social-login-divider::after {
    content: '';
    flex: 1 1 auto;
    border-top: 1px solid var(--dl-border);
}

.btn-social {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .6rem;
    font-weight: 600;
    padding: .6rem 1rem;
    border-radius: 8px;
    border: 1px solid var(--dl-border);
    background: #fff;
    color: var(--dl-dark);
    transition: box-shadow .15s ease, border-color .15s ease, background-color .15s ease;
}
.btn-social:hover,
.btn-social:focus-visible {
    background: #fff;
    color: var(--dl-dark);
    border-color: var(--dl-muted);
    box-shadow: 0 4px 14px rgba(39, 43, 65, .12);
}
.btn-social i { font-size: 1.05rem; line-height: 1; }

/* Brand colour on the mark only. Filling the whole button with it puts white
 * text on Google's red, which their brand terms don't allow. */
.btn-social-google i { color: #DB4437; }
.btn-social-facebook i { color: #1877F2; }

/* ---------- Explore (map + list) ---------- */
.explore-wrap {
    display: grid;
    /* Width of the list is a variable so the drag handle can write to it.
     * The floor is enforced here as well as in JS: the filter grid puts two
     * selects side by side, and below this they stop being usable. */
    --explore-list-w: 44%;
    /* 360 rather than the ~320 the filter grid alone survives: below this the
     * result cards start wrapping titles to three lines and breaking the
     * price/Compare row apart. Costs the map only ~40px to avoid. */
    --explore-list-min: 360px;
    grid-template-columns: minmax(var(--explore-list-min), var(--explore-list-w)) auto 1fr;
    gap: 0;
    height: calc(100vh - 0px);
}

/* ---------- Explore: draggable divider ---------- */
.explore-resizer {
    position: relative;
    width: 7px;
    cursor: col-resize;
    background: var(--dl-border);
    border: none;
    padding: 0;
    flex: 0 0 auto;
    transition: background-color .15s ease;
    /* A drag that crosses the map must not select list text or pan the map. */
    touch-action: none;
    user-select: none;
}
.explore-resizer:hover,
.explore-resizer:focus-visible,
.explore-resizer.is-dragging { background: var(--dl-primary); outline: none; }

/* The bar itself is deliberately thin; this widens only the pointer target so
 * it is grabbable without making the seam look heavy. */
.explore-resizer::before {
    content: '';
    position: absolute;
    inset: 0 -5px;
}
.explore-resizer-grip {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    width: 3px;
    height: 34px;
    border-radius: 2px;
    background: #fff;
    opacity: .85;
    pointer-events: none;
}

/* Dragging over an iframe-free page still loses the pointer to hover styles on
 * everything it crosses; freezing the cursor document-wide keeps it col-resize. */
body.is-resizing-explore,
body.is-resizing-explore * {
    cursor: col-resize !important;
    user-select: none !important;
}
.explore-list {
    overflow-y: auto;
    /* The filter panel is deliberately full-bleed via a negative margin, which
     * overshoots by a few pixels once the vertical scrollbar claims its width
     * and raises a horizontal scrollbar. Nothing here should ever scroll
     * sideways, so clip instead of chasing the arithmetic. */
    overflow-x: hidden;
    padding: 0 1.25rem 1.25rem;
    background: var(--dl-bg-soft);
}
.explore-filters.sticky-top-panel {
    position: sticky;
    top: 0;
    z-index: 900;
    margin: 0 -1.25rem 1rem;
    border-radius: 0;
    border-left: none;
    border-right: none;
    border-top: none;
    padding: 1rem 1.25rem;
    box-shadow: 0 6px 18px rgba(39, 43, 65, .08);
}
.explore-map-col { position: relative; }
#exploreMap { position: absolute; inset: 0; }

.explore-filters {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    padding: 1rem;
    margin-bottom: 1rem;
}
.explore-filters .form-control, .explore-filters .form-select { font-size: .9rem; }

.mini-card {
    display: flex;
    gap: .9rem;
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 10px;
    padding: .75rem;
    margin-bottom: .8rem;
    cursor: pointer;
    transition: all .2s ease;
}
.mini-card:hover, .mini-card.active {
    border-color: var(--dl-primary);
    box-shadow: 0 8px 22px rgba(61, 82, 168, .18);
}
.mini-card img {
    width: 110px;
    height: 86px;
    object-fit: cover;
    border-radius: 8px;
    flex-shrink: 0;
}
.mini-card h6 { margin-bottom: .15rem; font-size: .95rem; }
.mini-card h6 a { color: var(--dl-dark); }
.mini-card h6 a:hover { color: var(--dl-primary); }
.mini-card .rating { color: var(--dl-star); font-size: .78rem; }
.mini-card .meta { font-size: .78rem; color: var(--dl-muted); }
.mini-card .price { color: var(--dl-primary); font-weight: 700; font-size: .82rem; }
.mini-card .badges .badge { font-size: .62rem; }

/* Category-icon map pins */
.cat-pin {
    position: relative;
    width: 38px;
    height: 38px;
    background: var(--dl-primary);
    border: 3px solid #fff;
    border-radius: 50% 50% 50% 0;
    transform: rotate(-45deg);
    box-shadow: 0 4px 12px rgba(0, 0, 0, .35);
    display: flex;
    align-items: center;
    justify-content: center;
}
.cat-pin i {
    transform: rotate(45deg);
    color: #fff;
    font-size: 1rem;
}
.cat-pin.featured { background: var(--dl-accent); }
.leaflet-popup-content .mini-popup { min-width: 190px; }
.leaflet-popup-content .mini-popup img { width: 100%; height: 90px; object-fit: cover; border-radius: 6px; }

/*
 * Search and the 3D toggle, in one row along the top of the map.
 *
 * The left offset clears MapLibre's zoom/compass controls, which sit in the
 * top-left corner of the canvas.
 */
.map-topbar {
    position: absolute;
    top: 14px;
    left: 56px;
    right: 14px;
    z-index: 1001;
    display: flex;
    align-items: flex-start;
    gap: .5rem;
}

.map-search {
    /* Positioned by .map-topbar now. */
    width: min(360px, 100%);
    flex: 0 1 auto;
}
.map-search .form-control {
    border-radius: 8px 0 0 8px;
    box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
}
.map-search .btn { box-shadow: 0 6px 20px rgba(0, 0, 0, .18); }
.map-search .results {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 8px;
    margin-top: .4rem;
    max-height: 320px;
    overflow-y: auto;
    box-shadow: 0 12px 34px rgba(0, 0, 0, .22);
}
.map-search .results .group-label {
    font-size: .68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: .5px;
    color: var(--dl-muted);
    padding: .5rem .75rem .2rem;
}
.map-search .results button {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    border-bottom: 1px solid var(--dl-bg-soft);
    padding: .5rem .75rem;
    font-size: .82rem;
    color: var(--dl-dark);
    cursor: pointer;
}
.map-search .results button:hover { background: var(--dl-primary-light); }
.map-search .results button i { color: var(--dl-primary); margin-right: .4rem; }

.area-hint {
    background: var(--dl-primary-light);
    border: 1px dashed var(--dl-primary);
    border-radius: 8px;
    padding: .5rem .75rem;
    font-size: .8rem;
    color: var(--dl-primary-dark);
}

/* Compare cart tray */
.compare-tray {
    position: fixed;
    bottom: 22px;
    right: 22px;
    z-index: 1200;
    text-align: right;
}
.compare-tray .tray-panel {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 12px;
    box-shadow: 0 16px 44px rgba(0, 0, 0, .25);
    padding: .9rem;
    width: 290px;
    margin-bottom: .6rem;
    text-align: left;
}
.compare-tray .tray-item {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .4rem 0;
    border-bottom: 1px solid var(--dl-bg-soft);
}
.compare-tray .tray-item:last-child { border-bottom: none; }
.compare-tray .tray-item img {
    width: 44px; height: 34px;
    object-fit: cover;
    border-radius: 6px;
}
.compare-tray .tray-item .nm { font-size: .82rem; font-weight: 600; color: var(--dl-dark); flex: 1; }
.compare-tray .tray-item .rm {
    border: none; background: none;
    color: var(--dl-muted); cursor: pointer;
}
.compare-tray .tray-item .rm:hover { color: #e05260; }

.cmp-btn {
    border: 1px solid var(--dl-border);
    background: #fff;
    color: var(--dl-body);
    border-radius: 6px;
    font-size: .72rem;
    font-weight: 600;
    padding: .2rem .55rem;
    cursor: pointer;
}
.cmp-btn:hover { border-color: var(--dl-primary); color: var(--dl-primary); }
.cmp-btn.added {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    color: #fff;
}

@media (max-width: 991.98px) {
    /* Stacked, so there is no horizontal space to trade and nothing to drag.
     * The !important overrides the inline --explore-list-w the handle may have
     * written on a wider screen, which would otherwise survive a rotate to
     * portrait and squeeze the single column. */
    .explore-wrap { grid-template-columns: 1fr !important; height: auto; }
    .explore-map-col { height: 420px; }
    #exploreMap { position: relative; height: 100%; }
    .explore-resizer { display: none; }
}

/* ---------- Compare ---------- */
.searchable-select { position: relative; }
.searchable-select .results {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    z-index: 1050;
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 8px;
    margin-top: .3rem;
    max-height: 260px;
    overflow-y: auto;
    box-shadow: 0 12px 34px rgba(0, 0, 0, .18);
}
.searchable-select .results button {
    display: block;
    width: 100%;
    text-align: left;
    background: none;
    border: none;
    border-bottom: 1px solid var(--dl-bg-soft);
    padding: .5rem .75rem;
    font-size: .85rem;
    color: var(--dl-dark);
    cursor: pointer;
}
.searchable-select .results button:hover { background: var(--dl-primary-light); }
.searchable-select .results button .loc { color: var(--dl-muted); font-size: .75rem; display: block; }
.searchable-select .clear-pick {
    position: absolute;
    right: .6rem;
    top: 50%;
    transform: translateY(-50%);
    border: none;
    background: none;
    color: var(--dl-muted);
    cursor: pointer;
}
.searchable-select .clear-pick:hover { color: #e05260; }

.compare-table th, .compare-table td { vertical-align: middle; }
.compare-table .head-card img {
    width: 100%;
    height: 130px;
    object-fit: cover;
    border-radius: 8px;
}
.compare-table td.check i.yes { color: #23c58a; font-size: 1.1rem; }
.compare-table td.check i.no { color: var(--dl-border); font-size: 1.1rem; }

/* ---------- Misc ---------- */
.bg-soft { background: var(--dl-bg-soft); }
.stat-num { font-size: 2.4rem; font-weight: 800; color: var(--dl-primary); }

@media (max-width: 991.98px) {
    /* Sticky keeps the bar in flow, so it reserves its own space and the page
     * never lurches when it detaches — unlike the fixed swap used on desktop. */
    .dl-navbar { background: var(--dl-dark); position: sticky; top: 0; }

    /* Already sticky here; is-stuck only adds the lift, and re-animating a bar
     * that never actually moved would show up as a flicker on every scroll.
     *
     * Keep the resting padding too. An in-flow bar that shrinks also shortens
     * the page, so the desktop padding change would drag every element below it
     * up by ~14px the moment you scroll past the trigger. */
    .dl-navbar.is-stuck {
        position: sticky;
        animation: none;
        padding: 1rem 0;
    }

    /* Here the menu genuinely does expand down the screen, and a sticky bar
     * cannot be scrolled past — so the menu itself has to scroll. */
    .dl-navbar .navbar-collapse {
        max-height: calc(100vh - 6rem);
        overflow-y: auto;
    }

    /* Which means any dropdown inside it must open *in flow* rather than
     * floating out, or the same clipping that broke the desktop profile menu
     * would happen here instead. This is what Bootstrap does for dropdowns in
     * a collapsed navbar; the profile menu sits outside .navbar-nav, so it
     * needs saying explicitly. */
    .dl-navbar .navbar-collapse .dropdown-menu {
        position: static;
        float: none;
        width: 100%;
        margin-top: .25rem;
        box-shadow: none;
        border: 1px solid var(--dl-border);
    }
    .dl-hero { min-height: auto; padding-top: 90px; }
    .dl-hero h1 { font-size: 2.1rem; }

    /* The caption stops being an overlay on a phone — stacked under the search
     * there is no room for both, and absolute positioning would put the name
     * on top of the form. */
    .dl-hero.has-slides { padding: 90px 0 2rem; }
    .dl-hero.has-slides h1 { font-size: 1.85rem; }
    .hero-showcase { position: static; padding-top: 2rem; padding-bottom: 0; }
    .hero-showcase-inner { flex-direction: column; align-items: flex-start; gap: 1rem; }
    .hero-showcase-card { min-height: 152px; width: 100%; }
    .hero-showcase-name { font-size: 1.5rem; }
    .dl-hero.has-slides::after { height: 100%; }
    .dl-search-box .divider { border-left: none; border-top: 1px solid var(--dl-border); }
    .dest-card.tall { height: 260px; }
}

/* ---------- Map marker clusters ---------- */
/*
 * Hundreds of individual pins is what made the Explore map feel heavy; the
 * cluster group collapses them until you zoom in. These bubbles replace
 * Leaflet.markercluster's default green/yellow ones with the brand palette.
 */
.lg-cluster-wrap { background: none; border: 0; }

/*
 * Scoped under .lg-cluster-wrap on purpose. MarkerCluster.Default.css is loaded
 * after this file and styles `.marker-cluster div` (0,1,1) — a bare .lg-cluster
 * (0,1,0) loses to it, which left the counts as unreadable 12px grey text on no
 * background. Two classes beat one element+class.
 */
.lg-cluster-wrap .lg-cluster {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    background: var(--dl-primary);
    color: #fff;
    font-family: inherit;
    font-weight: 800;
    font-size: 1rem;
    line-height: 1;
    letter-spacing: -.01em;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 1px 2px rgba(0, 0, 0, .55), 0 0 3px rgba(0, 0, 0, .45);
    border: 3px solid #fff;
    box-shadow: 0 4px 16px rgba(24, 33, 78, .45), 0 0 0 1px rgba(24, 33, 78, .25);
}

.lg-cluster-wrap:hover .lg-cluster { background: var(--dl-primary-dark); }

/* The draggable figure at the centre of the map's area filter */
.area-person { background: none; border: 0; cursor: grab; }
.area-person:active { cursor: grabbing; }
.area-person svg { display: block; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .35)); }

/* =====================================================================
 * Explore map — MapLibre GL
 *
 * That one map dropped Leaflet so it could tilt, so the popup and marker
 * rules above (all scoped to .leaflet-*) no longer reach it. These are the
 * MapLibre equivalents; the Leaflet rules stay for the six maps that still
 * use it.
 * ===================================================================== */

.maplibregl-popup-content {
    padding: 10px 12px;
    border-radius: 10px;
    box-shadow: 0 6px 22px rgba(24, 33, 78, .22);
}

.maplibregl-popup-content .mini-popup { min-width: 190px; }

.maplibregl-popup-content .mini-popup img {
    width: 100%;
    height: 90px;
    object-fit: cover;
    border-radius: 6px;
}

.maplibregl-popup-close-button {
    font-size: 1.15rem;
    color: var(--dl-muted);
    padding: 0 6px;
}

.maplibregl-popup-close-button:hover { background: none; color: var(--dl-dark); }

/* The area-filter figure, as a MapLibre HTML marker */
.lg-area-pegman { cursor: grab; line-height: 0; }
.lg-area-pegman:active { cursor: grabbing; }
.lg-area-pegman svg { display: block; filter: drop-shadow(0 2px 3px rgba(0, 0, 0, .35)); }

/*
 * 3D toggle.
 *
 * Sits opposite the legend, clear of MapLibre's own controls in the top-left
 * and of the search box along the top.
 */
.map-tilt-btn {
    /* Sits in .map-topbar beside the search field. */
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 7px 13px;
    border: 0;
    border-radius: 999px;
    background: rgba(255, 255, 255, .96);
    box-shadow: 0 6px 20px rgba(0, 0, 0, .18);
    color: var(--dl-dark);
    font-size: .78rem;
    font-weight: 700;
    cursor: pointer;
    transition: background-color .2s ease, color .2s ease, box-shadow .2s ease;
}

.map-tilt-btn i { font-size: .95rem; color: var(--dl-primary); transition: color .2s ease; }

.map-tilt-btn:hover { box-shadow: 0 6px 18px rgba(24, 33, 78, .26); }

.map-tilt-btn.is-on {
    background: var(--dl-primary);
    color: #fff;
}

.map-tilt-btn.is-on i { color: #fff; }

.map-tilt-btn:focus-visible {
    outline: 2px solid var(--dl-primary);
    outline-offset: 2px;
}

/* Tilted, but not yet close enough for the basemap to carry buildings. */
.map-tilt-btn.is-waiting { background: var(--dl-accent); }

@media (prefers-reduced-motion: reduce) {
    .map-tilt-btn, .map-tilt-btn i { transition: none; }
}

/* On a narrow screen the row would push the 3D label off the edge, so the
   button drops to just its icon and the search keeps the space. */
@media (max-width: 575.98px) {
    .map-topbar { left: 52px; gap: .35rem; }
    .map-tilt-btn { padding: 7px 10px; }
    .map-tilt-btn span { display: none; }
}

/* =====================================================================
 * Listing-cover strip in the page header
 *
 * Six covers, paged by the arrows either side. Replaced a set of static
 * Wikimedia landmark photos: these are real places on the site, they link
 * somewhere useful, and they change on every page load.
 * ===================================================================== */

.header-strip {
    align-items: center;
    justify-content: center;
    gap: .55rem;
    margin: 1.6rem 0 0;
}

.header-strip-track {
    display: flex;
    gap: .6rem;
    flex-wrap: nowrap;
}

.header-strip-nav {
    flex: 0 0 auto;
    width: 30px;
    height: 30px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, .26);
    border-radius: 50%;
    background: rgba(255, 255, 255, .10);
    color: rgba(255, 255, 255, .88);
    font-size: .85rem;
    cursor: pointer;
    transition: background-color .18s ease, transform .18s ease;
}

.header-strip-nav:hover { background: rgba(255, 255, 255, .22); transform: scale(1.08); }
.header-strip-nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.header-spot {
    position: relative;
    display: block;
    /* Never shrink. These are flex items in a nowrap track, so the default
       flex-shrink:1 lets six of them squeeze unevenly on a narrow window —
       the tiles stop being square and the covers distort. */
    flex: 0 0 auto;
    width: 74px;
    height: 74px;
    border-radius: 12px;
    overflow: hidden;
    text-decoration: none;
    border: 1px solid rgba(255, 255, 255, .28);
    box-shadow: 0 6px 18px rgba(0, 0, 0, .28);
    filter: saturate(.92);
    transition: transform .22s ease, box-shadow .22s ease, filter .22s ease;
}

.header-spot img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* The name rides up from the bottom edge on hover. */
.header-spot-name {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: .5rem .3rem .28rem;
    font-size: .55rem;
    font-weight: 700;
    line-height: 1.15;
    text-align: center;
    color: #fff;
    background: linear-gradient(transparent, rgba(0, 0, 0, .86));
    opacity: 0;
    transform: translateY(100%);
    transition: opacity .22s ease, transform .22s ease;
    /* Long names must not push the tile wider. */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.header-spot:hover,
.header-spot:focus-visible {
    transform: translateY(-4px);
    filter: saturate(1.05);
    box-shadow: 0 12px 26px rgba(0, 0, 0, .38);
}

.header-spot:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.header-spot:hover .header-spot-name,
.header-spot:focus-visible .header-spot-name { opacity: 1; transform: translateY(0); }

/* Fades the new set in when the arrows swap it. */
@keyframes lg-strip-in {
    from { opacity: 0; transform: translateY(5px); }
    to { opacity: 1; transform: none; }
}
.header-strip.is-swapping .header-spot { animation: lg-strip-in .28s ease both; }

.header-strip-hint {
    margin: .8rem 0 0;
    font-size: .72rem;
    color: rgba(255, 255, 255, .55);
}

@media (prefers-reduced-motion: reduce) {
    .header-spot,
    .header-spot-name,
    .header-strip-nav { transition: none; }
    .header-spot:hover { transform: none; }
    .header-strip.is-swapping .header-spot { animation: none; }
}


/* =====================================================================
 * Businesses inside a place (mall tenant list)
 *
 * Compact rows, not full listing cards: SM Seaside alone holds 373 tenants,
 * and a wall of cards there was unreadable as well as enormous.
 * ===================================================================== */

.biz-filters {
    display: flex;
    gap: .6rem;
    flex-wrap: wrap;
    margin-bottom: 1rem;
}

.biz-search { position: relative; flex: 1 1 220px; min-width: 200px; }
.biz-search i {
    position: absolute;
    left: .75rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--dl-muted);
    pointer-events: none;
    font-size: .9rem;
}
.biz-search .form-control { padding-left: 2.15rem; }
.biz-filters .form-select { flex: 0 1 170px; }

/* Two columns on desktop, one on a phone. */
.biz-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: .5rem;
}

@media (max-width: 767.98px) {
    .biz-grid { grid-template-columns: 1fr; }
}

.biz-row {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: .55rem .7rem;
    border: 1px solid var(--dl-border);
    border-radius: 9px;
    background: #fff;
    text-decoration: none;
    color: inherit;
    min-width: 0;
    transition: border-color .16s ease, box-shadow .16s ease, transform .16s ease;
}

.biz-row:hover {
    border-color: var(--dl-primary);
    box-shadow: 0 4px 14px rgba(24, 33, 78, .10);
    transform: translateY(-1px);
}

.biz-row:focus-visible { outline: 2px solid var(--dl-primary); outline-offset: 2px; }

/* Initials stand in for a cover. Most tenants have no photo, and a grid of
   identical placeholders says less than the shop's own initials. */
.biz-row-thumb {
    flex: 0 0 auto;
    width: 40px;
    height: 40px;
    border-radius: 8px;
    background: var(--dl-primary-light, #eef1fb);
    color: var(--dl-primary);
    font-weight: 800;
    font-size: .78rem;
    display: flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.biz-row-thumb img { width: 100%; height: 100%; object-fit: cover; }

.biz-row-body { min-width: 0; flex: 1 1 auto; }

.biz-row-name {
    display: block;
    font-weight: 600;
    font-size: .88rem;
    color: var(--dl-dark);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.biz-row-meta {
    display: flex;
    gap: .7rem;
    margin-top: .12rem;
    font-size: .72rem;
    color: var(--dl-muted);
    white-space: nowrap;
    overflow: hidden;
}
.biz-row-meta i { margin-right: .25rem; }

.biz-row-go { color: var(--dl-muted); font-size: .8rem; flex: 0 0 auto; }
.biz-row:hover .biz-row-go { color: var(--dl-primary); }

.biz-empty { margin: 1rem 0 0; color: var(--dl-muted); font-size: .88rem; }

.biz-pager {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: .75rem;
    margin-top: 1rem;
    padding-top: .9rem;
    border-top: 1px solid var(--dl-border);
}
.biz-pager-label { font-size: .78rem; color: var(--dl-muted); }

@media (prefers-reduced-motion: reduce) {
    .biz-row { transition: none; }
    .biz-row:hover { transform: none; }
}

/* ---------- Explore: collapse the list, and full screen ---------- */
/* Collapsed, the grid gives the whole row to the map. The list and the drag
   handle are removed from the layout rather than merely hidden, so the map
   column is genuinely full width and the canvas resizes into it. */
/* One track, not "0 0 1fr": display:none takes the list and the handle out of
   the grid altogether, so the map would be auto-placed into the first track and
   collapse to zero width. With a single track it is the only item and takes it. */
.explore-wrap.list-collapsed { grid-template-columns: 1fr; }
.explore-wrap.list-collapsed .explore-list,
.explore-wrap.list-collapsed .explore-resizer { display: none; }

/* In full screen the map column is the root element, so it has to claim the
   viewport itself -- its grid track no longer applies. */
.explore-map-col:fullscreen,
.explore-map-col:-webkit-full-screen { width: 100vw; height: 100vh; }

/* Nothing to reclaim on the stacked layout, so the collapse control goes. */
@media (max-width: 991.98px) {
    .map-panel-btn { display: none; }
}

/* ---------- Listing menu ---------- */
.menu-group-title {
    font-size: .95rem;
    font-weight: 700;
    color: var(--dl-dark);
    letter-spacing: .01em;
    padding-bottom: .4rem;
    margin-bottom: .6rem;
    border-bottom: 1px solid var(--dl-border);
}

/* Name and price on one line with the price pinned right, the way a printed
   menu reads. The description sits under the name rather than beside it, so a
   long one does not push the price out of alignment. */
.menu-item {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    padding: .4rem 0;
}
.menu-item + .menu-item { border-top: 1px dashed var(--dl-border); }
.menu-item-main { flex: 1 1 auto; min-width: 0; }
.menu-item-name { display: block; font-weight: 600; color: var(--dl-dark); font-size: .92rem; }
.menu-item-desc { display: block; font-size: .82rem; color: var(--dl-muted); margin-top: .1rem; }
.menu-item-price {
    flex: 0 0 auto;
    font-weight: 700;
    font-size: .92rem;
    color: var(--dl-primary);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
}

.menu-item-photo {
    flex: 0 0 auto;
    width: 64px;
    height: 64px;
    object-fit: cover;
    border-radius: 8px;
    border: 1px solid var(--dl-border);
    background: var(--dl-bg-soft);
    align-self: center;
}

/* ---------- Booking calendar ---------- */
.bk-cal-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: .5rem; }
.bk-cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 3px; }
.bk-dow { text-align: center; font-size: .7rem; font-weight: 700; color: var(--dl-muted); padding: 2px 0; }
.bk-day {
    aspect-ratio: 1 / 1;
    border: 1px solid var(--dl-border);
    background: #fff;
    border-radius: 6px;
    font-size: .8rem;
    color: var(--dl-dark);
    cursor: pointer;
    padding: 0;
}
.bk-day:hover:not(.is-off) { border-color: var(--dl-primary); }
/* Taken or out of range: shown, not hidden, so the calendar reads as a calendar. */
.bk-day.is-off { background: var(--dl-bg-soft); color: #b6bcd0; cursor: not-allowed; text-decoration: line-through; }
.bk-day.is-start, .bk-day.is-end { background: var(--dl-primary); border-color: var(--dl-primary); color: #fff; font-weight: 700; }
.bk-day.is-mid { background: rgba(61, 82, 168, .14); border-color: rgba(61, 82, 168, .3); }
.menu-item-book { flex: 0 0 auto; align-self: center; }

/* ---------- Hero arrows ---------- */
.hero-controls { display: flex; align-items: center; justify-content: center; gap: .75rem; }
.hero-nav {
    width: 34px;
    height: 34px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border: 1px solid rgba(255, 255, 255, .55);
    background: rgba(255, 255, 255, .14);
    color: #fff;
    border-radius: 50%;
    cursor: pointer;
    transition: background-color .15s ease, border-color .15s ease;
}
.hero-nav:hover { background: rgba(255, 255, 255, .3); border-color: #fff; }
.hero-nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .hero-nav { transition: none; } }

/* ---------- Promos & vouchers ---------- */
.promo-filters { display: flex; flex-wrap: wrap; gap: .5rem; align-items: center; }
.promo-filters .form-select { width: auto; min-width: 190px; }
.promo-search { position: relative; flex: 1 1 260px; max-width: 420px; }
.promo-search i { position: absolute; left: .75rem; top: 50%; transform: translateY(-50%); color: var(--dl-muted); }
.promo-search .form-control { padding-left: 2.2rem; }

/* The card is a button: the whole thing opens the details dialog. */
.promo-card {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: .35rem;
    width: 100%;
    height: 100%;
    text-align: left;
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 12px;
    padding: 1.1rem 1.15rem;
    transition: box-shadow .15s ease, transform .15s ease, border-color .15s ease;
}
.promo-card:hover { box-shadow: 0 8px 22px rgba(24, 33, 78, .10); transform: translateY(-2px); border-color: var(--dl-primary); }
.promo-card:focus-visible { outline: 3px solid var(--dl-primary); outline-offset: 2px; }

.promo-kind {
    display: inline-flex;
    align-items: center;
    gap: .3rem;
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: #fff;
    background: var(--dl-primary);
    border-radius: 999px;
    padding: .2rem .6rem;
}
.promo-kind.is-voucher { background: #f0783c; }

.promo-value { font-size: 1.25rem; font-weight: 800; color: var(--dl-primary); line-height: 1.2; }
.promo-title { font-weight: 700; color: var(--dl-dark); }
.promo-summary { font-size: .86rem; color: var(--dl-muted); }
.promo-biz { font-size: .8rem; color: var(--dl-body); display: inline-flex; align-items: center; gap: .35rem; margin-top: .15rem; }

.promo-foot {
    display: flex;
    align-items: center;
    justify-content: space-between;
    width: 100%;
    margin-top: auto;
    padding-top: .6rem;
    font-size: .78rem;
}
.promo-ends { color: var(--dl-muted); display: inline-flex; align-items: center; gap: .3rem; }
/* An offer with a day or two left is the one worth hurrying for. */
.promo-ends.is-soon { color: #e05260; font-weight: 700; }
.promo-more { color: var(--dl-primary); font-weight: 600; }

.promo-code-box {
    display: flex;
    align-items: center;
    gap: .6rem;
    flex-wrap: wrap;
    background: var(--dl-bg-soft);
    border: 1px dashed var(--dl-primary);
    border-radius: 8px;
    padding: .7rem .9rem;
    margin-bottom: 1rem;
}
.promo-code-label { font-size: .7rem; text-transform: uppercase; letter-spacing: .06em; color: var(--dl-muted); }
.promo-code-box code { font-size: 1.05rem; font-weight: 700; color: var(--dl-dark); letter-spacing: .06em; }

.promo-dl { display: grid; grid-template-columns: 96px 1fr; gap: .3rem .8rem; font-size: .87rem; margin: 0; }
.promo-dl dt { color: var(--dl-muted); font-weight: 600; font-size: .78rem; }
.promo-dl dd { margin: 0; }
.promo-terms { font-size: .78rem; color: var(--dl-muted); margin: 1rem 0 0; padding-top: .7rem; border-top: 1px solid var(--dl-border); }

/* A live offer on the listing page itself. */
.promo-strip { display: flex; flex-wrap: wrap; gap: .5rem; }
.promo-pill {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    font-size: .8rem;
    font-weight: 600;
    background: var(--dl-bg-soft);
    border: 1px solid var(--dl-border);
    border-left: 3px solid var(--dl-primary);
    border-radius: 8px;
    padding: .45rem .7rem;
}
.promo-pill.is-voucher { border-left-color: #f0783c; }

@media (max-width: 575.98px) {
    .promo-filters .form-select, .promo-search { width: 100%; max-width: none; }
}

/* ===== Article SEO panel ===== */
/* Folded shut by default so the story stays the focus of the editor. */
.seo-panel {
    border: 1px solid var(--dl-border, #e6e8ec);
    border-radius: .75rem;
    background: #fff;
}

.seo-panel > summary {
    cursor: pointer;
    padding: .85rem 1rem;
    list-style: none;
    user-select: none;
}

/* The default triangle sits badly against the icon, so it is replaced. */
.seo-panel > summary::-webkit-details-marker { display: none; }

.seo-panel > summary::after {
    content: "282";
    font-family: "bootstrap-icons";
    float: right;
    font-size: .8rem;
    transition: transform .18s ease;
}

.seo-panel[open] > summary::after { transform: rotate(180deg); }
.seo-panel[open] > summary { border-bottom: 1px solid var(--dl-border, #e6e8ec); }
.seo-panel-body { padding: 1rem; }

/* A plain imitation of a Google result - enough to judge length by. */
.seo-preview {
    border: 1px solid var(--dl-border, #e6e8ec);
    border-radius: .6rem;
    padding: .85rem 1rem;
    background: var(--dl-bg-soft, #f7f8fa);
}

.seo-preview-title {
    color: #1a0dab;
    font-size: 1rem;
    font-weight: 500;
    line-height: 1.3;
    overflow-wrap: anywhere;
}

.seo-preview-url { color: #006621; font-size: .78rem; overflow-wrap: anywhere; }
.seo-preview-desc { color: #545454; font-size: .85rem; margin-top: .15rem; overflow-wrap: anywhere; }
.seo-preview-warn { color: #b23c17; font-size: .78rem; margin-top: .45rem; }

/* ===== Verified tick ===== */
/* Sits beside a listing name wherever the name appears. Sized in em so it
   scales with whatever heading or row it is dropped into. */
.verified-tick {
    color: #1d9bf0;                 /* the Verified badge colour */
    font-size: .82em;
    margin-left: .3em;
    vertical-align: baseline;
    flex: none;                     /* never squashed inside a flex row */
}

/* On the dark hero the plain blue is too dim against the photo. */
.detail-hero .verified-tick,
.hero .verified-tick {
    color: #4db5f5;
    text-shadow: 0 1px 3px rgba(0, 0, 0, .45);
}

/* ===== Suggestion pin picker ===== */
.suggest-map {
    height: 380px;
    border-radius: .6rem;
    border: 1px solid var(--dl-border);
    /* Leaflet panes otherwise paint over the rounded corners. */
    overflow: hidden;
    z-index: 0;
}

@media (max-width: 575.98px) {
    /* Taller on a phone: the map is the form. */
    .suggest-map { height: 60vh; }
}

.suggest-pin-readout {
    display: flex;
    align-items: center;
    gap: .4rem;
    margin-top: .6rem;
    font-size: .85rem;
    color: var(--dl-body);
}

.suggest-pin-readout i { color: var(--dl-primary); }

/* The pin is grabbable, so say so. */
.suggest-map .leaflet-marker-draggable { cursor: grab; }
.suggest-map .leaflet-marker-draggable:active { cursor: grabbing; }

/* ===== Hub filter band =====
   Sits between the page header and the results, lifted over the seam so it
   reads as the control panel for what follows. Rounded and shadowed rather
   than boxed, in the Material manner. */
.hub-filterbar {
    background: transparent;
    /* Pulls the card up over the header's lower edge. */
    margin-top: -2.25rem;
    position: relative;
    z-index: 3;
}

.hub-filterbar-inner {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .65rem;
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 1rem;
    padding: .9rem 1rem;
    box-shadow: 0 6px 22px rgba(39, 43, 65, .1);
}

/* Search box with a leading icon. */
.hub-search {
    position: relative;
    flex: 1 1 16rem;
    min-width: 12rem;
}

.hub-search > i {
    position: absolute;
    left: .9rem;
    top: 50%;
    transform: translateY(-50%);
    color: var(--dl-muted);
    pointer-events: none;
}

.hub-search .form-control {
    padding-left: 2.35rem;
    border-radius: 999px;
    height: 2.75rem;
}

/* Pills, not boxes. */
.hub-filterbar .form-select,
.hub-filterbar .hub-btn {
    border-radius: 999px;
    height: 2.75rem;
}

.hub-filter {
    width: auto;
    min-width: 12rem;
    flex: 0 1 auto;
}

.hub-btn {
    display: inline-flex;
    align-items: center;
    white-space: nowrap;
    padding-inline: 1.15rem;
}

.hub-filterbar .form-control:focus,
.hub-filterbar .form-select:focus {
    border-color: var(--dl-primary);
    box-shadow: 0 0 0 .2rem var(--dl-primary-light);
}

/* Select2 renders its own control, so the pill shape has to be applied to
   that too - otherwise the enhanced dropdown keeps square corners while its
   plain sibling is a pill. */
.hub-filterbar .select2-container { width: auto !important; min-width: 12rem; }

.hub-filterbar .select2-selection {
    border-radius: 999px !important;
    min-height: 2.75rem;
    display: flex;
    align-items: center;
    padding-inline: 1rem;
    border-color: var(--dl-border);
}

.hub-filterbar .select2-selection__rendered { padding: 0 !important; }
.hub-filterbar .select2-selection__arrow { top: 50% !important; transform: translateY(-50%); }

@media (max-width: 767.98px) {
    .hub-filterbar { margin-top: -1.25rem; }
    .hub-filterbar-inner { border-radius: .9rem; padding: .8rem; }
    /* Each control takes a full row rather than being squeezed to a stub. */
    .hub-search,
    .hub-filterbar .hub-filter,
    .hub-filterbar .ts-wrapper { flex: 1 1 100%; min-width: 0; }
    .hub-btn { flex: 1 1 auto; justify-content: center; }
}

/* The count line, now on its own. */
.hub-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .6rem;
    margin-bottom: 1.5rem;
}

/* ===== Select2, themed to match the rest of the site ===== */
.select2-container--bootstrap-5 .select2-dropdown {
    border-radius: .75rem;
    overflow: hidden;
    border: 1px solid var(--dl-border);
    box-shadow: 0 8px 26px rgba(39, 43, 65, .14);
}

/* The highlighted row - keyboard or hover - is filled with the brand blue, so
   its text has to invert with it. Without the colour the theme's dark default
   stays put and the row reads as near-black on dark blue. White on #3d52a8 is
   about 7.2:1, comfortably past AA. */
.select2-container--bootstrap-5 .select2-results__option--highlighted,
.select2-container--bootstrap-5 .select2-results__option--highlighted.select2-results__option--selectable,
.select2-container--bootstrap-5 .select2-results__option--highlighted[aria-selected='true'] {
    background: var(--dl-primary) !important;
    color: #fff !important;
}

/* Anything nested inside the row - a count, a muted note - has to come with
   it, or it stays grey on blue. */
.select2-container--bootstrap-5 .select2-results__option--highlighted * {
    color: #fff !important;
}

/* The already-chosen row when it is NOT hovered: tinted, not filled, so the
   dark text it keeps is still legible. */
.select2-container--bootstrap-5 .select2-results__option--selected:not(.select2-results__option--highlighted) {
    background: var(--dl-primary-light) !important;
    color: var(--dl-dark) !important;
}

.select2-container--bootstrap-5 .select2-selection:focus,
.select2-container--bootstrap-5.select2-container--focus .select2-selection {
    border-color: var(--dl-primary);
    box-shadow: 0 0 0 .2rem var(--dl-primary-light);
}

/* Above Bootstrap modals, which sit at 1055. */
.select2-container { z-index: 1100; }

/* ===== Pagination =====
   One style for every paginated list, public and admin. Round targets with
   real space between them - the numbers used to butt against each other - and
   a filled current page. 40px minimum so it is comfortable on a phone. */
.mui-pager {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: .4rem;
    margin: 0;
    padding: 0;
}

.mui-page {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    /* 2.75rem clears 40px at this root size; WCAG wants a comfortable
       target and 2.5rem was landing at 38. */
    min-width: 2.75rem;
    height: 2.75rem;
    padding: 0 .7rem;
    border-radius: 999px;
    border: 1px solid transparent;
    background: transparent;
    color: var(--dl-body, #5a6779);
    font-size: .92rem;
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease, box-shadow .15s ease;
}

a.mui-page:hover,
a.mui-page:focus-visible {
    background: var(--dl-primary-light, #e9edfb);
    color: var(--dl-primary, #3d52a8);
    text-decoration: none;
}

a.mui-page:focus-visible {
    outline: 2px solid var(--dl-primary, #3d52a8);
    outline-offset: 2px;
}

/* The page you are on: filled, so it reads without relying on weight alone. */
.mui-page.is-current {
    background: var(--dl-primary, #3d52a8);
    color: #fff;
    box-shadow: 0 2px 8px rgba(61, 82, 168, .35);
}

.mui-page.is-disabled {
    color: var(--dl-muted, #9299b8);
    opacity: .55;
    cursor: default;
}

/* The "..." between page runs is a label, not a target. */
.mui-page.is-gap {
    min-width: 1.5rem;
    padding: 0;
    color: var(--dl-muted, #9299b8);
    letter-spacing: .1em;
}

.mui-pager-count {
    width: 100%;
    text-align: center;
    margin-top: .55rem;
    font-size: .82rem;
    color: var(--dl-muted, #9299b8);
}

@media (max-width: 575.98px) {
    /* Keep the chevrons and the current page; the rest would wrap to three
       rows on a narrow screen. */
    .mui-pager { gap: .3rem; }
    .mui-page { min-width: 2.35rem; height: 2.35rem; padding: 0 .45rem; }
}

/* ===== Category banner + featured rows ===== */
/* A category with its own picture uses it as the header. The gradient is set
   inline with the image; this only has to make the text sit legibly on it. */
.page-header.has-banner {
    background-size: cover;
    background-position: center;
    background-repeat: no-repeat;
}

/* A listing an admin pinned to the top of its category. Tinted rather than
   filled, so the row still reads as a row and the name keeps its contrast. */
.biz-row.is-featured {
    border-color: var(--dl-primary);
    background: var(--dl-primary-light);
}

.biz-row-featured {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    background: var(--dl-primary);
    color: #fff;
    font-size: .68rem;
    font-weight: 600;
    letter-spacing: .02em;
    padding: .1rem .45rem;
    border-radius: 999px;
    white-space: nowrap;
}

.biz-row-featured i { font-size: .7rem; }

/* ==========================================================================
   Articles feed
   A single centred column of posts with a right rail, the shape people
   already know from a social feed. The old two-up card grid made every story
   look like a database row; this one reads like something a person wrote.
   ========================================================================== */

.feed-page {
    background: var(--dl-bg-soft);
    padding: 2rem 0 4rem;
}

.feed-layout {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: 1.75rem;
    align-items: start;
    max-width: 1060px;
    margin: 0 auto;
}

/* The reading column. Wider than this and the eye loses the line. */
.feed-main {
    max-width: 680px;
    width: 100%;
    margin: 0 auto;
    min-width: 0;
}

/* ---- shared card shell ---- */

.feed-post,
.feed-card,
.feed-composer,
.feed-filter {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 14px;
    box-shadow: 0 1px 2px rgba(39, 43, 65, .06);
}

/* ---- composer ---- */

.feed-composer {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: .85rem 1rem;
    margin-bottom: 1.25rem;
}

.feed-composer-prompt {
    flex: 1 1 auto;
    min-width: 0;
    background: var(--dl-bg-soft);
    border-radius: 999px;
    padding: .6rem 1.1rem;
    color: var(--dl-body);
    font-size: .95rem;
    text-decoration: none;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    transition: background .15s ease;
}

.feed-composer-prompt:hover,
.feed-composer-prompt:focus-visible {
    background: var(--dl-primary-light);
    color: var(--dl-primary);
}

/* ---- avatar ---- */

.feed-avatar {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    background: var(--dl-primary);
    color: #fff;
    font-weight: 700;
    font-size: .9rem;
    letter-spacing: .02em;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
    user-select: none;
}

.feed-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}

/* ---- active filter banner ---- */

.feed-filter {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .7rem 1rem;
    margin-bottom: 1.25rem;
    font-size: .92rem;
    color: var(--dl-body);
}

/* ---- a post ---- */

.feed-post {
    margin-bottom: 1.25rem;
    overflow: hidden;
}

.feed-post-head {
    display: flex;
    align-items: center;
    gap: .7rem;
    padding: 1rem 1.1rem .35rem;
}

.feed-post-meta {
    min-width: 0;
    line-height: 1.3;
}

.feed-post-author {
    display: block;
    font-weight: 600;
    color: var(--dl-dark);
    font-size: .95rem;
}

.feed-post-when {
    display: block;
    font-size: .8rem;
    color: var(--dl-muted);
}

.feed-post-when span { margin: 0 .3rem; }

.feed-post-body { padding: .5rem 1.1rem .85rem; }

.feed-post-title {
    font-size: 1.2rem;
    line-height: 1.4;
    margin: 0 0 .4rem;
    font-weight: 700;
}

.feed-post-title a {
    color: var(--dl-dark);
    text-decoration: none;
}

.feed-post-title a:hover,
.feed-post-title a:focus-visible { color: var(--dl-primary); }

.feed-post-excerpt {
    margin: 0;
    color: var(--dl-body);
    font-size: .95rem;
    line-height: 1.65;
}

.feed-post-tags {
    margin: .6rem 0 0;
    font-size: .85rem;
}

.feed-post-tags a {
    color: var(--dl-primary);
    text-decoration: none;
    margin-right: .55rem;
}

.feed-post-tags a:hover { text-decoration: underline; }

/* The photo runs the full width of the card, the way a shared photo does. */
.feed-post-photo {
    display: block;
    background: var(--dl-bg-soft);
    border-top: 1px solid var(--dl-border);
    border-bottom: 1px solid var(--dl-border);
}

/* Each cover keeps its own shape - the inline aspect-ratio comes from the
   file itself (Article::coverRatio()). These are designed graphics with
   headlines on them, and any single fixed frame crops the text off one shape
   or the other. The ratio still reserves the space before the image loads, so
   nothing below it jumps. The declaration here is only the fallback for a
   cover that could not be measured. */
.feed-post-photo img {
    display: block;
    width: 100%;
    aspect-ratio: 3 / 2;
    object-fit: cover;
    transition: transform .35s ease;
}

.feed-post-photo:hover img { transform: scale(1.02); }

/* ---- counts, then actions ---- */

.feed-post-counts {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: .7rem 1.1rem;
    font-size: .85rem;
    color: var(--dl-muted);
}

.feed-post-counts i { margin-right: .3rem; }

.feed-post-actions {
    display: flex;
    border-top: 1px solid var(--dl-border);
}

.feed-post-actions a {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    padding: .7rem .5rem;
    font-size: .9rem;
    font-weight: 600;
    color: var(--dl-body);
    text-decoration: none;
    transition: background .15s ease, color .15s ease;
}

.feed-post-actions a:hover,
.feed-post-actions a:focus-visible {
    background: var(--dl-bg-soft);
    color: var(--dl-primary);
}

.feed-post-actions a + a { border-left: 1px solid var(--dl-border); }

.feed-empty {
    text-align: center;
    padding: 3rem 1.5rem;
}

.feed-empty > i {
    font-size: 2.4rem;
    color: var(--dl-muted);
}

/* ---- right rail ---- */

.feed-rail {
    position: sticky;
    top: 90px;
    min-width: 0;
}

.feed-card {
    padding: 1.1rem;
    margin-bottom: 1.25rem;
}

.feed-card-title {
    display: flex;
    align-items: center;
    gap: .45rem;
    font-size: .95rem;
    font-weight: 700;
    color: var(--dl-dark);
    margin: 0 0 .85rem;
}

.feed-mini {
    display: flex;
    gap: .7rem;
    align-items: center;
    padding: .55rem 0;
    text-decoration: none;
    border-radius: 8px;
    transition: background .15s ease;
}

.feed-mini:hover { background: var(--dl-bg-soft); }

.feed-mini img {
    flex: 0 0 auto;
    width: 56px;
    height: 48px;
    border-radius: 8px;
    object-fit: cover;
}

.feed-mini-title {
    display: block;
    font-size: .87rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--dl-dark);
}

.feed-mini:hover .feed-mini-title { color: var(--dl-primary); }

.feed-mini-meta {
    display: block;
    font-size: .78rem;
    color: var(--dl-muted);
    margin-top: .15rem;
}

.feed-mini-meta i { margin-right: .25rem; }

.feed-tags {
    display: flex;
    flex-wrap: wrap;
    gap: .4rem;
}

.feed-tag {
    background: var(--dl-bg-soft);
    border: 1px solid var(--dl-border);
    border-radius: 999px;
    padding: .25rem .7rem;
    font-size: .8rem;
    color: var(--dl-body);
    text-decoration: none;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.feed-tag:hover,
.feed-tag:focus-visible,
.feed-tag.is-on {
    background: var(--dl-primary);
    border-color: var(--dl-primary);
    color: #fff;
}

/* ---- narrow screens: the rail follows the feed ---- */

@media (max-width: 991.98px) {
    .feed-layout {
        grid-template-columns: minmax(0, 1fr);
    }

    .feed-rail {
        position: static;
        max-width: 680px;
        width: 100%;
        margin: 0 auto;
    }
}

@media (max-width: 575.98px) {
    .feed-page { padding: 1.25rem 0 2.5rem; }

    /* Edge to edge, so the photo gets the whole screen. */
    .feed-post,
    .feed-composer,
    .feed-filter {
        border-radius: 0;
        border-left: 0;
        border-right: 0;
        margin-left: calc(var(--bs-gutter-x, 1.5rem) * -.5);
        margin-right: calc(var(--bs-gutter-x, 1.5rem) * -.5);
    }

    .feed-post-title { font-size: 1.08rem; }
    .feed-avatar { width: 40px; height: 40px; font-size: .82rem; }
}

@media (prefers-reduced-motion: reduce) {
    .feed-post-photo img { transition: none; }
    .feed-post-photo:hover img { transform: none; }
}

/* ---------- Category strip in the page header ---------- */
/* The hubs' version of the cover strip above. Chips rather than tiles,
   because a category is its name - an icon on its own does not identify one
   the way a photo of a place does. */

.header-cats {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: .45rem;
    margin: 1.5rem 0 0;
}

.header-cat {
    display: inline-flex;
    align-items: center;
    gap: .4rem;
    padding: .38rem .8rem;
    border-radius: 999px;
    border: 1px solid rgba(255, 255, 255, .28);
    background: rgba(255, 255, 255, .10);
    color: #fff;
    font-size: .82rem;
    font-weight: 600;
    line-height: 1.4;
    text-decoration: none;
    white-space: nowrap;
    transition: background-color .18s ease, border-color .18s ease, transform .18s ease;
}

/* White, not the category's own colour. These sit on a dark blue gradient,
   where a #3d52a8 or #272b41 icon is invisible - which is the whole reason
   the strip needed its own rule rather than reusing the card styling. */
.header-cat i {
    font-size: .95rem;
    color: #fff;
    line-height: 1;
}

.header-cat-n {
    font-weight: 500;
    font-size: .72rem;
    color: rgba(255, 255, 255, .62);
}

.header-cat:hover,
.header-cat:focus-visible {
    background: rgba(255, 255, 255, .22);
    border-color: rgba(255, 255, 255, .5);
    color: #fff;
    transform: translateY(-2px);
}

.header-cat:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* The one you are on inverts, so the strip doubles as a "you are here". */
.header-cat.is-on {
    background: #fff;
    border-color: #fff;
    color: var(--dl-primary);
}

.header-cat.is-on i { color: var(--dl-primary); }
.header-cat.is-on .header-cat-n { color: var(--dl-body); }

/* On a phone the row scrolls sideways rather than wrapping to four lines of
   chips above the content people actually came for. */
@media (max-width: 767.98px) {
    .header-cats {
        flex-wrap: nowrap;
        justify-content: flex-start;
        overflow-x: auto;
        padding-bottom: .35rem;
        scrollbar-width: none;
        -webkit-overflow-scrolling: touch;
    }

    .header-cats::-webkit-scrollbar { display: none; }
    .header-cat { flex: 0 0 auto; }
}

@media (prefers-reduced-motion: reduce) {
    .header-cat { transition: none; }
    .header-cat:hover { transform: none; }
}

/* ---------- Weather card on a listing ---------- */

/* The skeleton holds the space the forecast will take, so a normal load does
   not shove Business Hours down the page when the fetch returns. If there is
   nothing to show the card removes itself instead of sitting there empty. */
.wx-card.is-loading .wx-skeleton {
    display: block;
    min-height: 190px;
}

.wx-skeleton span {
    display: block;
    height: 14px;
    border-radius: 7px;
    background: linear-gradient(90deg, var(--dl-bg-soft) 25%, #eef0f7 37%, var(--dl-bg-soft) 63%);
    background-size: 400% 100%;
    animation: wx-shimmer 1.4s ease infinite;
    margin-bottom: .7rem;
}

.wx-skeleton span:first-child { height: 46px; border-radius: 10px; }
.wx-skeleton span:nth-child(2) { height: 62px; border-radius: 10px; }
.wx-skeleton span:last-child { width: 70%; margin-bottom: 0; }

@keyframes wx-shimmer {
    from { background-position: 100% 50%; }
    to { background-position: 0 50%; }
}

/* ---- right now ---- */

.wx-now {
    display: flex;
    align-items: center;
    gap: .8rem;
    padding: .2rem 0 .9rem;
    border-bottom: 1px solid var(--dl-border);
}

.wx-now > i {
    font-size: 2.3rem;
    color: var(--dl-primary);
    line-height: 1;
}

.wx-now-main { flex: 1 1 auto; min-width: 0; line-height: 1.2; }

.wx-now-deg {
    display: block;
    font-size: 1.75rem;
    font-weight: 700;
    color: var(--dl-dark);
}

.wx-now-desc {
    display: block;
    font-size: .82rem;
    color: var(--dl-body);
}

.wx-now-side {
    flex: 0 0 auto;
    text-align: right;
    font-size: .78rem;
    color: var(--dl-muted);
}

.wx-now-side span { display: block; white-space: nowrap; }
.wx-now-side i { margin-right: .3rem; }

/* ---- today, hour by hour ---- */

.wx-strip-label {
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .04em;
    text-transform: uppercase;
    color: var(--dl-muted);
    margin: .85rem 0 .5rem;
}

/* Scrolls sideways: eight hours will not fit a sidebar, and squeezing them
   makes every column too narrow to read. */
.wx-strip {
    display: flex;
    gap: .35rem;
    overflow-x: auto;
    padding-bottom: .35rem;
    scrollbar-width: thin;
}

.wx-hour {
    flex: 0 0 auto;
    width: 56px;
    text-align: center;
    padding: .5rem .2rem;
    border-radius: 10px;
    background: var(--dl-bg-soft);
    line-height: 1.35;
}

.wx-hour-t {
    display: block;
    font-size: .68rem;
    font-weight: 600;
    color: var(--dl-body);
    white-space: nowrap;
}

.wx-hour i {
    display: block;
    font-size: 1.05rem;
    color: var(--dl-primary);
    margin: .15rem 0;
}

.wx-hour-deg {
    display: block;
    font-size: .85rem;
    font-weight: 700;
    color: var(--dl-dark);
}

.wx-hour-rain {
    display: block;
    font-size: .68rem;
    color: #3d8fd8;
}

/* ---- sunrise and sunset ---- */

.wx-sun {
    display: flex;
    justify-content: space-between;
    gap: 1rem;
    margin-top: .7rem;
    padding-top: .7rem;
    border-top: 1px solid var(--dl-border);
    font-size: .78rem;
    color: var(--dl-body);
}

.wx-sun i { margin-right: .35rem; color: var(--dl-star); }

/* ---- tomorrow and the day after ---- */

.wx-days { margin-top: .5rem; }

.wx-day {
    display: grid;
    grid-template-columns: 1fr auto;
    grid-template-areas:
        "name temp"
        "desc rain";
    align-items: center;
    gap: 0 .5rem;
    padding: .6rem 0;
    border-top: 1px solid var(--dl-border);
}

.wx-day-name {
    grid-area: name;
    font-weight: 600;
    font-size: .88rem;
    color: var(--dl-dark);
}

/* The icon rides with the description rather than taking a column of its own,
   which would leave the two rows misaligned in a narrow sidebar. */
.wx-day > i {
    grid-area: desc;
    font-size: .82rem;
    color: var(--dl-primary);
    justify-self: start;
}

.wx-day-desc {
    grid-area: desc;
    font-size: .78rem;
    color: var(--dl-body);
    padding-left: 1.35rem;
}

.wx-day-temp {
    grid-area: temp;
    font-size: .88rem;
    color: var(--dl-muted);
    white-space: nowrap;
}

.wx-day-temp strong { color: var(--dl-dark); }

.wx-day-rain {
    grid-area: rain;
    font-size: .76rem;
    color: #3d8fd8;
    text-align: right;
    white-space: nowrap;
}

.wx-day-rain i { margin-right: .25rem; }

.wx-credit {
    margin: .8rem 0 0;
    font-size: .7rem;
    color: var(--dl-muted);
}

.wx-credit a { color: var(--dl-muted); text-decoration: underline; }
.wx-credit a:hover { color: var(--dl-primary); }

@media (prefers-reduced-motion: reduce) {
    .wx-skeleton span { animation: none; }
}

/* ---------- Category Directory: as many across as fit ---------- */

/*
 * Not Bootstrap columns. Twelve does not divide into ten, and the rule that
 * actually matters here is not a column count - it is "make them small and fit
 * what you can". auto-fill does exactly that: ten across a 1140px container,
 * and fewer on its own as the window narrows, with no breakpoints to keep in
 * step with the card size.
 *
 * 104px is the floor because it is the narrowest a two-word category name will
 * sit at without the count line wrapping under it as well.
 */
.cat-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(104px, 1fr));
    gap: .6rem;
}

/* Small enough that ten fit; every rule here is a size, not a restyle, so the
   card keeps the colour, hover and focus behaviour it has everywhere else. */
.cat-grid .cat-card {
    padding: .8rem .35rem;
    border-radius: 9px;
}

.cat-grid .cat-card i {
    font-size: 1.3rem;
    margin-bottom: .3rem;
}

.cat-grid .cat-card h6 {
    font-size: .76rem;
    line-height: 1.25;
    margin-bottom: .15rem;
    /* A long name wraps rather than pushing the column wider and costing the
       row a whole card. */
    overflow-wrap: anywhere;
}

.cat-grid .cat-card span { font-size: .68rem; }

/* Hover lifts the card 6px everywhere else on the site. At this size that
   reads as a jump, so it is halved. */
.cat-grid .cat-card:hover {
    transform: translateY(-3px);
    box-shadow: 0 10px 22px rgba(61, 82, 168, .3);
}

/* Below a phone's width, three is the most that stays legible. */
@media (max-width: 400px) {
    .cat-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- Listing detail: a sticky sidebar, the way Facebook does it ---------- */

/*
 * The page scrolls as one page. Only the sidebar behaves differently, and only
 * on a desktop: it follows you down instead of leaving a tall empty gutter
 * beside a long listing.
 *
 * --rail-top is set per page by sticky-rail.js, because the right offset
 * depends on the rail's own height and CSS cannot measure that. A rail that
 * fits gets 90px, under the navbar. A rail taller than the screen gets a
 * negative offset, so it finishes scrolling and comes to rest with its last
 * card against the fold rather than pinning its first card and hiding the
 * rest. The 90px here is what applies until the script has run.
 *
 * NOT independently scrolling panes with their own hidden scrollbars - that
 * was built, disliked and removed. It is Messenger's layout, not the feed's.
 */
@media (min-width: 992px) {
    /* Bootstrap stretches columns to match, and a stretched column has no room
       left to move in - sticky does nothing at all without this. */
    .listing-rail { align-self: flex-start; }

    .listing-rail {
        position: sticky;
        top: var(--rail-top, 90px);
    }
}

/* ---------- Listing editor: the side menu ---------- */

/*
 * The editor was one page with six stacked cards in a single column, about
 * 1,200 lines of it, so reaching the menu meant scrolling past announcements
 * and promos. Each card is its own page now and this is how you move between
 * them.
 */
.edit-nav {
    background: #fff;
    border: 1px solid var(--dl-border);
    border-radius: 12px;
    padding: .5rem;
    position: sticky;
    top: 90px;
}

.edit-nav-item {
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .75rem;
    border-radius: 8px;
    color: var(--dl-body);
    font-size: .92rem;
    font-weight: 500;
    text-decoration: none;
    transition: background-color .15s ease, color .15s ease;
}

.edit-nav-item i { font-size: 1rem; color: var(--dl-muted); }
.edit-nav-item span { flex: 1 1 auto; }

.edit-nav-item:hover,
.edit-nav-item:focus-visible {
    background: var(--dl-bg-soft);
    color: var(--dl-primary);
}

.edit-nav-item:hover i,
.edit-nav-item:focus-visible i { color: var(--dl-primary); }

.edit-nav-item:focus-visible { outline: 2px solid var(--dl-primary); outline-offset: -2px; }

.edit-nav-item.is-on {
    background: var(--dl-primary);
    color: #fff;
}

.edit-nav-item.is-on i { color: #fff; }

/* How many announcements, offers or menu groups are already there - the one
   thing you would otherwise have to open a pane to find out. */
.edit-nav-count {
    flex: 0 0 auto;
    background: var(--dl-bg-soft);
    color: var(--dl-body);
    border-radius: 999px;
    padding: .05rem .5rem;
    font-size: .72rem;
    font-weight: 600;
}

.edit-nav-item.is-on .edit-nav-count {
    background: rgba(255, 255, 255, .22);
    color: #fff;
}

.edit-nav-view {
    border-top: 1px solid var(--dl-border);
    margin-top: .35rem;
    padding-top: .7rem;
    font-size: .85rem;
}

/* On a phone the nav sits above the pane and reads as a row of chips rather
   than a tall list you have to scroll past to reach the form. */
@media (max-width: 991.98px) {
    .edit-nav {
        position: static;
        display: flex;
        flex-wrap: wrap;
        gap: .3rem;
    }

    .edit-nav-item { padding: .45rem .7rem; font-size: .85rem; }
    .edit-nav-view { border-top: 0; margin-top: 0; padding-top: .45rem; width: 100%; }
}

/* ---------- The story viewer on the articles feed ---------- */

/*
 * A story opens the way a photo opens on Facebook: the cover on a dark stage,
 * the summary and the conversation in a panel beside it. The card underneath
 * is still a real link to the real article page - this is what a plain
 * left-click does instead, and the page is what everything else still gets.
 */
.article-viewer {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    background: rgba(10, 12, 20, .92);
}

.article-viewer[hidden] { display: none; }

/* The page behind must not scroll under the viewer. */
body.av-open { overflow: hidden; }

.av-close {
    position: absolute;
    top: 1rem;
    left: 1rem;
    z-index: 2;
    width: 40px;
    height: 40px;
    border: 0;
    border-radius: 50%;
    background: rgba(255, 255, 255, .14);
    color: #fff;
    font-size: 1rem;
    cursor: pointer;
    transition: background-color .15s ease;
}

.av-close:hover { background: rgba(255, 255, 255, .26); }
.av-close:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* ---- the cover ---- */

.av-stage {
    flex: 1 1 auto;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 2.5rem 1rem;
    min-width: 0;
}

.av-stage img {
    max-width: 100%;
    max-height: 100%;
    /* contain, not cover: this is the whole point of opening it. Cropping the
       cover here would hide the part someone clicked to see. */
    object-fit: contain;
    border-radius: 6px;
}

.av-loading { color: rgba(255, 255, 255, .7); font-size: .9rem; }

/* ---- the panel ---- */

.av-panel {
    flex: 0 0 380px;
    background: #fff;
    display: flex;
    flex-direction: column;
    overflow-y: auto;
}

.av-head {
    display: flex;
    align-items: center;
    gap: .65rem;
    padding: 1rem 1.1rem .75rem;
    border-bottom: 1px solid var(--dl-border);
}

.av-face {
    flex: 0 0 auto;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: var(--dl-primary);
    color: #fff;
    font-weight: 700;
    font-size: .85rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}

.av-face img { width: 100%; height: 100%; object-fit: cover; }
.av-face-sm { width: 32px; height: 32px; font-size: .7rem; }

.av-author { display: block; font-weight: 600; color: var(--dl-dark); font-size: .95rem; }
.av-when { display: block; font-size: .78rem; color: var(--dl-muted); }

.av-caption { padding: .9rem 1.1rem; }

.av-caption h2 { font-size: 1.15rem; line-height: 1.4; margin: 0 0 .45rem; font-weight: 700; }
.av-caption h2 a { color: var(--dl-dark); text-decoration: none; }
.av-caption h2 a:hover { color: var(--dl-primary); }
.av-caption p { margin: 0; font-size: .93rem; line-height: 1.65; color: var(--dl-body); }

.av-tags { margin-top: .55rem !important; font-size: .84rem; }
.av-tags a { color: var(--dl-primary); text-decoration: none; margin-right: .5rem; }
.av-tags a:hover { text-decoration: underline; }

.av-read {
    display: inline-block;
    margin-top: .7rem;
    font-size: .87rem;
    font-weight: 600;
    color: var(--dl-primary);
    text-decoration: none;
}

.av-read:hover { text-decoration: underline; }
.av-read i { font-size: .8rem; }

/* ---- likes, comments, and the buttons between them ---- */

.av-counts {
    display: flex;
    justify-content: space-between;
    padding: .7rem 1.1rem;
    font-size: .84rem;
    color: var(--dl-muted);
    border-top: 1px solid var(--dl-border);
}

.av-counts i { color: #e05260; margin-right: .2rem; }

.av-actions {
    display: flex;
    border-top: 1px solid var(--dl-border);
    border-bottom: 1px solid var(--dl-border);
}

.av-actions button {
    flex: 1 1 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .45rem;
    padding: .65rem .5rem;
    border: 0;
    background: none;
    font-size: .9rem;
    font-weight: 600;
    color: var(--dl-body);
    cursor: pointer;
    transition: background-color .15s ease, color .15s ease;
}

.av-actions button:hover:not(:disabled) { background: var(--dl-bg-soft); color: var(--dl-primary); }
.av-actions button:focus-visible { outline: 2px solid var(--dl-primary); outline-offset: -2px; }
.av-actions button:disabled { opacity: .6; cursor: default; }
.av-actions button.is-on { color: #e05260; }
.av-actions button + button { border-left: 1px solid var(--dl-border); }

.av-comments {
    flex: 1 1 auto;
    padding: .9rem 1.1rem;
    min-height: 90px;
}

.av-comment { display: flex; gap: .6rem; margin-bottom: .9rem; }

.av-comment-body {
    background: var(--dl-bg-soft);
    border-radius: 14px;
    padding: .5rem .8rem;
    min-width: 0;
}

.av-comment-who { font-weight: 600; font-size: .84rem; color: var(--dl-dark); }
.av-comment-body p { margin: .1rem 0 0; font-size: .9rem; line-height: 1.5; color: var(--dl-body); }
.av-comment-when { display: block; font-size: .72rem; color: var(--dl-muted); margin-top: .2rem; }

.av-empty { font-size: .88rem; color: var(--dl-muted); margin: 0; }

/* ---- writing one ---- */

.av-compose {
    display: flex;
    gap: .5rem;
    padding: .8rem 1.1rem;
    border-top: 1px solid var(--dl-border);
    position: sticky;
    bottom: 0;
    background: #fff;
}

.av-compose input {
    flex: 1 1 auto;
    min-width: 0;
    border: 1px solid var(--dl-border);
    border-radius: 999px;
    padding: .5rem .95rem;
    font-size: .9rem;
}

.av-compose input:focus { outline: 2px solid var(--dl-primary); outline-offset: -1px; }

.av-compose button {
    flex: 0 0 auto;
    width: 38px;
    border: 0;
    border-radius: 50%;
    background: var(--dl-primary);
    color: #fff;
    cursor: pointer;
}

.av-compose button:hover { background: var(--dl-primary-dark); }
.av-compose button:focus-visible { outline: 2px solid var(--dl-dark); outline-offset: 2px; }

.av-signin {
    padding: .9rem 1.1rem;
    margin: 0;
    border-top: 1px solid var(--dl-border);
    font-size: .88rem;
    color: var(--dl-muted);
}

/* ---- a phone gets one column, cover first ---- */

@media (max-width: 991.98px) {
    .article-viewer { flex-direction: column; }

    .av-stage {
        flex: 0 0 auto;
        max-height: 42vh;
        padding: 3.2rem .75rem .75rem;
    }

    .av-panel {
        flex: 1 1 auto;
        border-radius: 14px 14px 0 0;
    }
}

/* ---------- Material Symbols ---------- */

/*
 * Google's css2 endpoint ships the @font-face and nothing else - unlike the old
 * ?family=Material+Icons endpoint, it does NOT define this class. Without it
 * every Material icon renders as the literal word "restaurant", or as a row of
 * tofu boxes once the font loads but the ligature feature is off.
 */
.material-symbols-outlined {
    font-family: 'Material Symbols Outlined';
    font-weight: normal;
    font-style: normal;
    font-size: inherit;
    line-height: 1;
    letter-spacing: normal;
    text-transform: none;
    display: inline-block;
    white-space: nowrap;
    word-wrap: normal;
    direction: ltr;
    font-feature-settings: 'liga';
    -webkit-font-feature-settings: 'liga';
    -webkit-font-smoothing: antialiased;
}
