/* Homepage V2 (modules/Homepage) — hand-maintained, same convention as
   header-v2.css: no mix/SCSS pipeline for these hp-* classes yet.
   Styled so far: .hp-hero (hero + rotating promo background), .hp-showcase
   (§10 product showcase — card/swiper design ported from the attraction SPA's
   UpsellSection/AttractionCard) and .hp-destinations (Top Destination mosaic).
   Other hp-* sections (hotels, tours, events, trust_band) are still unstyled —
   see OTA_HOMEPAGE_V2_PLAN.md Phase 2 known gaps. */

/* Full-bleed banner: the section always spans the viewport and its HEIGHT is
   derived from the art's ratio, so the whole image shows uncropped at every
   width — phone, tablet and desktop — rather than being cut off left/right by
   background-size:cover. 1546x423 (= ~3.655:1) is the house banner spec for
   desktop uploads; the slides currently on the site are 2641x723, which is
   the same ratio to within 0.05%, so they fit this box without cropping too.
   Deliberately NO max-height/min-height here: aspect-ratio means any height
   clamp gets resolved by shrinking or inflating the WIDTH instead, which is
   what used to pin the banner to the left of wide screens (a 500px cap
   derived a 1826px width) and overflow the viewport on tablets (a 300px
   floor derived a 1096px width). Height is free, width follows the screen. */
.hp-hero {
    position: relative;
    aspect-ratio: 1546 / 423;
    padding: 24px 0;
    display: flex;
    align-items: center;
    overflow: hidden;
}

/* Phones get their own 3:2 banner art, NOT the desktop strip: 1546x423 on a
   390pt phone is a 107px letterbox (~13% of the viewport) and shrinks the
   headline baked into the art to ~25% of its design size. 3:2 lands at ~260px
   (~31%), which still clears the search form below — that form is the page's
   main CTA and is what caps how tall this may go, so don't take it past ~4:3.
   Upload spec for the designers: 1320x880 (owner decision 2026-09-23). 1320
   is the widest phone's physical pixel count — 430 CSS px at DPR 3 = 1290 —
   so the art never upscales on any handset. It must MATCH 3:2 exactly,
   because the box is now precisely the art's shape and background-size:cover
   crops anything that isn't. Desktop's equivalent spec is 1546x423.

   The breakpoint must stay in lockstep with hero_search.blade.php's asset
   swap (.d-sm-none / .d-none .d-sm-block = 575.98px) or the two disagree and
   one art gets rendered in the other's box: at 768px, the width the markup
   used to swap at, a landscape phone (667x375) rendered this 3:2 box 445px
   tall on a 375px-tall screen — 119% of the viewport, search form below the
   fold. Change one edge and you must change the other.

   padding 0 because aspect-ratio sizes the BORDER box — padding would eat
   the band rather than inset it, and the overlaid title is flex-centred
   inside the box anyway. */
@media (max-width: 575.98px) {
    .hp-hero {
        aspect-ratio: 3 / 2;
        padding: 0;
    }
}

/* Compound selector (not just .hp-hero__carousel) deliberately outweighs
   owl.carousel.css's own ".owl-carousel { position: relative }" rule — that
   stylesheet loads AFTER this one (Layout::app.blade.php's @yield('head') runs
   before its own <link owl.carousel.css>), so equal specificity would let
   owl's rule win by source order and collapse this back into normal flow. */
.hp-hero .hp-hero__carousel,
.hp-hero .hp-hero__bg {
    position: absolute;
    inset: 0;
    z-index: 0;
}

.hp-hero__bg {
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}

.hp-hero__carousel .owl-stage-outer,
.hp-hero__carousel .owl-stage,
.hp-hero__carousel .owl-item,
.hp-hero__slide-wrap {
    height: 100%;
}

.hp-hero__slide {
    display: block;
    height: 100%;
    background-position: center;
    background-repeat: no-repeat;
    background-size: cover;
}

/* Fallback shape for a slide with no dedicated mobile art (see
   PromoBannerSection's bg_mobile_is_fallback): the desktop image is 3.655:1
   and the phone box is 3:2, so plain cover would crop it to the middle ~41%.
   Contain the whole image and fill what's left with a blurred, slightly
   overscaled copy of the SAME already-cached file - no extra request, and the
   identical technique .hp-attr-card__img-blur uses further down for tour cards
   whose 4:3 art doesn't fill a 1:1 card. A slide that HAS proper 3:2 mobile
   art never gets these classes and keeps the plain cover background above. */
.hp-hero__slide--fit {
    position: relative;
    overflow: hidden;
    background-image: none;
}

.hp-hero__slide-blur,
.hp-hero__slide-art {
    display: block;
    position: absolute;
    background-position: center;
    background-repeat: no-repeat;
}

/* Overfilled by 8% + scaled so blur()'s soft transparent edge never shows. */
.hp-hero__slide-blur {
    inset: -8%;
    z-index: 0;
    background-size: cover;
    filter: blur(14px) saturate(1.15);
    transform: scale(1.06);
}

.hp-hero__slide-art {
    inset: 0;
    z-index: 1;
    background-size: contain;
}

/* Readability overlay + light text, only when there's an actual image behind
   the content (rotating slides or the static fallback) — sites with neither
   configured keep the plain default background + dark text. */
.hp-hero--has-bg::before {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 0;
    background: linear-gradient(180deg, rgba(0, 0, 0, .45), rgba(0, 0, 0, .2) 45%, rgba(0, 0, 0, .1));
}

.hp-hero--has-bg .hp-hero__title,
.hp-hero--has-bg .hp-hero__sub {
    color: #fff;
    text-shadow: 0 1px 4px rgba(0, 0, 0, .4);
}

.hp-hero .container {
    position: relative;
    z-index: 1;
}

/* Positioned absolutely (not static, owl's default) so it sits over the
   image near the bottom instead of being pushed below the 100%-height
   stage and clipped by .hp-hero's overflow:hidden. */
.hp-hero .owl-dots {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 12px;
    z-index: 1;
    text-align: center;
}

.hp-hero .owl-dot {
    display: inline-block;
    width: 8px;
    height: 8px;
    margin: 0 4px;
    border-radius: 50%;
    background: rgba(255, 255, 255, .5);
    cursor: pointer;
}

.hp-hero .owl-dot.active {
    background: #fff;
}

.hp-hero__title {
    font-size: 36px;
    font-weight: 700;
    margin-bottom: 8px;
}

.hp-hero__sub {
    font-size: 16px;
    margin-bottom: 24px;
}

.hp-hero__search {
    margin-top: 24px;
    margin-bottom: 24px;
}

/* Type scale only — the banner's own mobile box is handled above, at the same
   575.98px edge the markup swaps art on. */
@media (max-width: 575.98px) {
    .hp-hero__search {
        margin-top: 16px;
        margin-bottom: 16px;
    }

    .hp-hero__title {
        font-size: 24px;
    }

    .hp-hero__sub {
        font-size: 14px;
        margin-bottom: 16px;
    }
}

/* ── §10 Product Showcase (hp-showcase) ─────────────────────────────────────
   Card + swiper design ported from the attraction SPA's UpsellSection /
   AttractionCard (resources/frontend/js/spa/attraction/components) — the SPA's
   scoped CSS never loads on the homepage, so the classes are mirrored here
   with the hp- prefix. Same --attr-primary variable + fallback as the SPA. */

.hp-showcase { padding: 28px 0; }
.hp-showcase__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 4px; }
.hp-showcase__head .hp-section__title { margin: 0; font-size: 26px; display: flex; align-items: center; gap: 10px; }
/* Brand gradient on the title icon (shared by every showcase service AND
   the Top Destination row, which reuses this same .hp-showcase__head /
   .hp-section__title markup — see _destinations_row.blade.php). color is
   the fallback for browsers without background-clip: text. */
.hp-showcase__head .hp-section__title i {
    color: #e30613;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    font-size: 22px;
}

/* "See More" — gradient-filled pill button (was a plain outlined link) */
.hp-showcase__more {
    position: relative;
    display: inline-flex; align-items: center; gap: 8px;
    font-size: 14px; font-weight: 700;
    color: #fff;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    text-decoration: none; white-space: nowrap;
    padding: 8px 18px; border: none; outline: none; border-radius: 50px;
    transition: filter .15s;
}
.hp-showcase__more i { font-size: 12px; transition: transform .15s; }
.hp-showcase__more:hover { filter: brightness(0.92); text-decoration: none; }
.hp-showcase__more:hover i { transform: translateX(3px); }
/* Gradient focus ring — replaces the browser's default (blue) focus outline;
   it's an <a>, not a <button>, so no Bootstrap button:focus rule to beat. */
.hp-showcase__more::after {
    content: '';
    position: absolute; inset: -4px;
    border-radius: 54px;
    padding: 2px;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0;
    transition: opacity .15s ease;
    pointer-events: none;
}
.hp-showcase__more:focus-visible::after { opacity: 1; }

/* Tabs — Gother-style underline. Bootstrap ships a global `button:focus {
   outline: 5px auto -webkit-focus-ring-color; }` (bootstrap.css:233) — that's
   the blue ring on click. Its specificity (element+pseudo-class) beats a
   plain `.hp-showcase__tab { outline: none }` (class-only) regardless of
   load order, so the override below matches it pseudo-class-for-pseudo-class
   (`.hp-showcase__tab:focus` etc.) — equal specificity, later in the
   cascade, wins. The red bottom border (active AND focus-visible, for
   keyboard users) is the replacement indicator instead of the ring. */
.hp-showcase__tabs { display: flex; gap: 4px; overflow-x: auto; border-bottom: 1px solid #eef0f3; margin-bottom: 18px; scrollbar-width: none; }
.hp-showcase__tabs::-webkit-scrollbar { display: none; }
.hp-showcase__tab { flex-shrink: 0; background: none; border: none; outline: none; border-bottom: 3px solid transparent; padding: 10px 14px; font-size: 15px; font-weight: 600; color: #5e6d77; cursor: pointer; transition: color .15s, border-color .15s; }
.hp-showcase__tab:focus,
.hp-showcase__tab:active,
.hp-showcase__tab:active:focus { outline: none; }
.hp-showcase__tab:hover { color: #1a2b48; }
/* Gradient keyboard-focus indicator — matches .is-active below rather than
   a solid --attr-primary color, since that's the brand treatment used
   everywhere else a "current/selected" state needs to stand out here. */
.hp-showcase__tab:focus-visible {
    color: #e30613;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    border-image: linear-gradient(90deg, #ff2f00, #fff000) 1;
}
/* Active tab: brand gradient on the label (background-clip: text — color
   above/here is the fallback for browsers without that support) and on the
   underline (border-image — the bottom border is the only side with a
   non-zero width here, so it's the only edge that actually paints). */
.hp-showcase__tab.is-active,
.hp-showcase__tab.is-active:focus {
    color: #e30613;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    border-image: linear-gradient(90deg, #ff2f00, #fff000) 1;
    font-weight: 700;
}
.hp-showcase.is-loading .hp-showcase__body { opacity: .5; pointer-events: none; }

/* Horizontal swiper row (mirrors .upsell-swiper) */
.hp-upsell-swiper { display: flex; gap: 16px; overflow-x: auto; padding-bottom: 8px; align-items: stretch; scrollbar-width: thin; scrollbar-color: #ddd transparent; min-width: 0; }
.hp-upsell-swiper::-webkit-scrollbar { height: 4px; }
.hp-upsell-swiper::-webkit-scrollbar-thumb { background: #ddd; border-radius: 4px; }
.hp-upsell-swiper__item { flex: 0 0 260px; min-width: 260px; display: flex; flex-direction: column; }

/* Tour/Hotel/Attraction showcases — wider cards than the default */
.hp-showcase--hotel .hp-upsell-swiper__item,
.hp-showcase--hotel .hp-upsell-explore-card,
.hp-showcase--attraction .hp-upsell-swiper__item,
.hp-showcase--attraction .hp-upsell-explore-card { flex: 0 0 260px; min-width: 260px; }

/* Tour showcase — tour art is designed poster artwork with the headline text
   baked into the image at 4:3 (e.g. media 2134x1600), not a photo. The shared
   1:1 `cover` crop below therefore cut ~25% off the sides and sliced through
   the wording. Tours instead get the art's own 4:3 box + `object-fit:contain`,
   so no part of the image is ever lost, and wider cards (300px) so the
   baked-in text stays legible at card size. `contain` leaves slack only when
   an upload ISN'T 4:3 — .hp-attr-card__img-blur fills that with a blurred copy
   of the same (already-cached) image instead of empty bars. */
.hp-showcase--tour .hp-upsell-swiper__item,
.hp-showcase--tour .hp-upsell-explore-card { flex: 0 0 300px; min-width: 300px; }
.hp-showcase--tour .hp-attr-card__img-wrap { aspect-ratio: 4 / 3; background: #dfe7f0; }
.hp-showcase--tour .hp-attr-card__img-wrap img { object-fit: contain; }

/* Rendered for every service (one shared card partial) but only painted for
   tours — display:none also stops the browser fetching the background, so the
   other showcases pay nothing for it. Inset/scale overfill hides the soft
   transparent edge blur() leaves behind. */
.hp-attr-card__img-blur { display: none; }
.hp-showcase--tour .hp-attr-card__img-blur {
    display: block;
    position: absolute;
    inset: -8%;
    z-index: 0;
    background-size: cover;
    background-position: center;
    filter: blur(14px) saturate(1.15);
    transform: scale(1.06);
}

/* Card — Gother-style: near-square image, title + location, discount/badge
   pills, "Start at [strike] [price]" row (2026-07-17 redesign). */
.hp-attr-card { display: flex; flex-direction: column; height: 100%; min-width: 0; border-radius: 14px; overflow: hidden; background: #fff; box-shadow: 0 2px 12px rgba(0,0,0,.08); text-decoration: none; color: inherit; transition: box-shadow .2s, transform .2s; }
.hp-attr-card:hover { box-shadow: 0 6px 24px rgba(0,0,0,.14); transform: translateY(-2px); text-decoration: none; color: inherit; }
.hp-attr-card__img-wrap { position: relative; overflow: hidden; background: #eef0f3; flex-shrink: 0; aspect-ratio: 1 / 1; }
.hp-attr-card__img-wrap img { position: relative; z-index: 1; width: 100%; height: 100%; object-fit: cover; display: block; }
/* Decorative only — no wishlist backend wired into the homepage showcase (v1) */
.hp-attr-card__wishlist { position: absolute; z-index: 2; top: 10px; right: 10px; width: 32px; height: 32px; border-radius: 50%; background: rgba(0,0,0,.35); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 15px; }
.hp-attr-card__badge { position: absolute; z-index: 2; top: 10px; left: 10px; background: var(--attr-primary, #e30613); color: #fff; font-size: 11px; font-weight: 700; padding: 3px 10px; border-radius: 20px; }

/* Default image theme — sits UNDER every homepage item image (showcase cards
   + destination tiles): visible while the img loads, when no image is
   configured, and when the URL 404s (each img carries an inline onerror that
   hides itself so this shows through). Soft branded gradient + big washed-out
   icon instead of the browser's broken-image glyph. */
.hp-img-fallback { position: absolute; inset: 0; z-index: 0; display: flex; align-items: center; justify-content: center; background: linear-gradient(135deg, #eef2f7 0%, #dfe7f0 55%, #d3dde9 100%); color: #b3c0d0; font-size: 36px; }
.hp-img-fallback::after { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 30% 25%, rgba(255,255,255,.7), rgba(255,255,255,0) 55%); }
.hp-img-fallback i { position: relative; z-index: 1; opacity: .85; }
.hp-attr-card__badge--gold { background: #e07700; }
.hp-attr-card__body { padding: 14px 16px 16px; display: flex; flex-direction: column; gap: 8px; flex: 1; min-height: 0; }
.hp-attr-card__name { font-size: 16px; font-weight: 700; color: #1a2b48; line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden; }
.hp-attr-card__location { display: flex; align-items: center; gap: 5px; font-size: 13px; color: #6c757d; }
.hp-attr-card__location i { color: #6c757d; font-size: 12px; }

/* Per-service extras — mirror each SPA's own search card styles:
   stars/review row from HotelResultCard.vue (.hs-hcard__stars/__review),
   duration meta from TourCard.vue (.gyg-meta), perk pills from
   AttractionCard.vue (.attr-card__pill) / HotelResultCard badges. */
.hp-attr-card__stars { display: flex; align-items: center; gap: 2px; }
.hp-attr-card__stars .fa-star { color: #f5c000; font-size: 11px; }
.hp-attr-card__stars-label { font-size: 11px; color: #6b7280; margin-left: 4px; }
.hp-attr-card__review { display: flex; align-items: center; gap: 5px; flex-wrap: wrap; }
.hp-attr-card__review-badge { background: #2563eb; color: #fff; font-size: 11px; font-weight: 700; padding: 2px 7px; border-radius: 5px; line-height: 1.4; }
.hp-attr-card__review-label { font-size: 12px; font-weight: 600; color: #1a2b48; }
.hp-attr-card__review-count { font-size: 11px; color: #9ca3af; }
.hp-attr-card__meta { display: flex; align-items: center; gap: 5px; font-size: 12px; color: #6c757d; }
.hp-attr-card__footer { margin-top: auto; display: flex; flex-direction: column; gap: 8px; }
.hp-attr-card__pills { display: flex; flex-wrap: wrap; gap: 6px; }
.hp-attr-card__pill { display: inline-flex; align-items: center; gap: 4px; font-size: 12px; font-weight: 600; padding: 4px 12px; border-radius: 20px; color: #fff; background: #16a34a; }
/* Amenity/feature perks (green, AttractionCard's __pill--green convention) —
   soft-fill variant of the same green as the base pill. Must stay AFTER
   the base __pill rule: same specificity, so source order decides the
   override. */
.hp-attr-card__pill--perk { background: rgba(22, 163, 74, .12); color: #16a34a; }
.hp-attr-card__price-row { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; flex-wrap: wrap; }
.hp-attr-card__price-label { font-size: 13px; color: #6c757d; }
.hp-attr-card__price-nums { display: flex; align-items: baseline; gap: 6px; flex-wrap: wrap; }
.hp-attr-card__price-orig { font-size: 12px; color: #999; text-decoration: line-through; }
.hp-attr-card__price-from { font-size: 19px; font-weight: 800; color: var(--systemColor, #e30613); }
.hp-attr-card__price-unit { font-size: 12px; color: #6c757d; }

/* Trailing "Explore" card (mirrors .upsell-explore-card) */
.hp-upsell-explore-card { flex: 0 0 260px; border-radius: 14px; overflow: hidden; position: relative; cursor: pointer; background-size: cover; background-position: center; background-color: var(--attr-primary, #e30613); transition: transform .2s; display: flex; align-items: center; justify-content: center; text-decoration: none; min-height: 300px; }
.hp-upsell-explore-card:hover { transform: translateY(-2px); text-decoration: none; }
.hp-upsell-explore-card__overlay { position: absolute; inset: 0; background: rgba(0,0,0,.38); }
.hp-upsell-explore-card__inner { position: relative; z-index: 2; display: flex; flex-direction: column; align-items: center; gap: 14px; padding: 20px 16px; }
.hp-upsell-explore-card__circle { width: 72px; height: 72px; border-radius: 50%; background: rgba(255,255,255,.22); border: 2px solid rgba(255,255,255,.6); display: flex; align-items: center; justify-content: center; color: #fff; font-size: 26px; }
.hp-upsell-explore-card__label { font-size: 16px; font-weight: 700; color: #fff; text-align: center; text-shadow: 0 1px 6px rgba(0,0,0,.4); }

/* ── Top Destination mosaic (hp-destinations) ───────────────────────────────
   Hand-curated tiles, each deep-linking into one service's search page
   (PopularDestinationsSection / DestinationLink). 4-col × 2-row mosaic per 6
   tiles mirroring the reference mock: within each group of 6, tile 2 is tall
   (both rows), tile 3 wide (two columns); dense flow packs the remainder. */

.hp-destinations { padding: 28px 0; }
.hp-destinations .hp-section__desc { color: #6c757d; margin-bottom: 6px; }
/* COLUMN flow with 2 fixed rows (not row flow): the first 6 tiles fill the
   visible 4-column mosaic exactly like the reference mock, and every further
   group of 6 repeats the same pattern to the RIGHT behind a horizontal
   scroll (owner spec 2026-07-18) — more tiles never wrap downward.
   grid-auto-columns is a quarter of the visible width, so 6 tiles span the
   container edge-to-edge and column 5+ overflows into the scroll. */
.hp-dest-grid { display: grid; grid-template-rows: repeat(2, 200px); grid-auto-flow: column dense; grid-auto-columns: calc((100% - 48px) / 4); gap: 16px; margin-top: 14px; overflow-x: auto; padding-bottom: 8px; scrollbar-width: thin; scrollbar-color: #ddd transparent; }
.hp-dest-grid::-webkit-scrollbar { height: 4px; }
.hp-dest-grid::-webkit-scrollbar-thumb { background: #ddd; border-radius: 4px; }
/* Mosaic pattern per group of 6: tile 2 tall (spans both rows), tile 3 wide
   (spans two columns); dense flow packs tiles 4-6 around them. */
.hp-dest-grid > :nth-child(6n+2) { grid-row: span 2; }
.hp-dest-grid > :nth-child(6n+3) { grid-column: span 2; }
.hp-dest-tile { position: relative; display: block; border-radius: 14px; overflow: hidden; background: #eef0f3; box-shadow: 0 2px 12px rgba(0,0,0,.08); transition: box-shadow .2s, transform .2s; }
.hp-dest-tile:hover { box-shadow: 0 6px 24px rgba(0,0,0,.14); transform: translateY(-2px); }
.hp-dest-tile__img { position: absolute; inset: 0; z-index: 1; width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .3s; }
.hp-dest-tile:hover .hp-dest-tile__img { transform: scale(1.04); }
/* Shade + name always stack above both the img (z1) and the .hp-img-fallback
   layer (z0), so a fallback tile still reads as a full tile (name over gradient). */
.hp-dest-tile__shade { position: absolute; inset: 0; z-index: 2; background: linear-gradient(180deg, rgba(0,0,0,0) 55%, rgba(0,0,0,.55)); }
.hp-dest-tile__name { position: absolute; left: 16px; bottom: 12px; right: 16px; z-index: 3; color: #fff; font-size: 22px; font-weight: 800; text-shadow: 0 1px 6px rgba(0,0,0,.5); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

@media (max-width: 767px) {
    /* Same column-flow mosaic + horizontal swipe, just smaller: two visible
       columns instead of four, shorter rows. */
    .hp-destinations { padding: 20px 0; }
    .hp-dest-grid { grid-template-rows: repeat(2, 130px); grid-auto-columns: calc((100% - 12px) / 2); gap: 12px; }
    .hp-dest-tile__name { font-size: 17px; left: 12px; bottom: 10px; right: 12px; }
}

@media (max-width: 767px) {
    .hp-showcase { padding: 20px 0; }
    .hp-showcase__head .hp-section__title { font-size: 20px; }
    .hp-showcase__head .hp-section__title i { font-size: 18px; }
    .hp-showcase__more { padding: 6px 14px; font-size: 13px; }
    .hp-upsell-swiper__item { flex: 0 0 200px; min-width: 200px; }
    .hp-attr-card__name { font-size: 14px; }
    .hp-upsell-explore-card { flex: 0 0 160px; min-height: 160px; }
    .hp-showcase__tab { font-size: 14px; padding: 8px 10px; }
    .hp-showcase--hotel .hp-upsell-swiper__item,
    .hp-showcase--attraction .hp-upsell-swiper__item { flex: 0 0 235px; min-width: 235px; }
    /* Tour cards stay wider than the other showcases on phones too: the art
       carries baked-in headline text, which 235px left unreadable. 280px still
       leaves a ~50px peek of the next card on a 360px screen, so the row is
       visibly swipeable. The explore card is pinned here as well — the
       .hp-showcase--tour desktop rule outweighs the plain
       `.hp-upsell-explore-card` override above (two classes vs one; a media
       query adds no specificity), so without this it would keep its 300px. */
    .hp-showcase--tour .hp-upsell-swiper__item,
    .hp-showcase--tour .hp-upsell-explore-card { flex: 0 0 280px; min-width: 280px; }
}

/* ── Newsletter (hp-newsletter) ──────────────────────────────────────────────
   hp-* restyle of the shared footer's mailchimp block (Layout::parts.footer,
   `.mailchimp`) for homepage_v2 — see Sections/NewsletterSection. Accent color
   is --systemColor (admin's `style_main_color` setting, set globally in
   Layout::parts.custom-css) rather than a hardcoded hex, so it follows the
   site's theme color like the rest of the app; the button keeps the same
   fixed brand gradient already used for .hp-showcase__more / active tabs
   below. Functional classes kept from the footer version
   (`.bravo-subscribe-form`, `.form-mess`) so public/js/home.js's existing
   submit handler works unchanged. */
.hp-newsletter { padding: 28px 0 48px; }
.hp-newsletter__inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
    padding: 28px 32px;
    border-radius: 16px;
    background: linear-gradient(90deg, #fff5f2, #fffdf2);
}
.hp-newsletter__media { display: flex; align-items: center; gap: 16px; flex: 1 1 320px; }
.hp-newsletter__icon {
    flex: none;
    width: 52px;
    height: 52px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 22px;
    color: #fff;
    background: var(--systemColor, #e30613);
}
.hp-newsletter__title { margin: 0; font-size: 20px; font-weight: 800; color: #1a2b48; }
.hp-newsletter__sub { margin: 2px 0 0; font-size: 14px; color: #6c757d; }
.hp-newsletter__form { flex: 1 1 360px; max-width: 420px; }
.hp-newsletter__field { display: flex; gap: 10px; }
.hp-newsletter__input {
    flex: 1 1 auto;
    height: 48px;
    padding: 0 16px;
    border-radius: 24px;
    border: 1px solid #e5e7eb;
    background: #fff;
    font-size: 14px;
}
/* Gradient focus border — outline can't hold a gradient value directly, so
   the border itself is swapped via the double-background/clip trick (same
   technique used for the search fields on this page). */
.hp-newsletter__input:focus {
    outline: none;
    border-color: transparent;
    background-image: linear-gradient(#fff, #fff), linear-gradient(135deg, var(--systemColor, #e30613), var(--hv2-brand-light, #ff5f4d));
    background-origin: border-box;
    background-clip: padding-box, border-box;
    box-shadow: 0 0 0 3px rgba(var(--hv2-brand-rgb, 227,6,19), .10);
}
.hp-newsletter__btn {
    position: relative;
    flex: none;
    height: 48px;
    padding: 0 24px;
    border: none;
    outline: none;
    border-radius: 24px;
    color: #fff;
    font-weight: 700;
    font-size: 14px;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    cursor: pointer;
}
/* Gradient focus ring — replaces the browser's default (blue) focus outline. */
.hp-newsletter__btn::after {
    content: '';
    position: absolute; inset: -4px;
    border-radius: 28px;
    padding: 2px;
    background-image: linear-gradient(90deg, #ff2f00, #fff000);
    -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);
    -webkit-mask-composite: xor;
    mask-composite: exclude;
    opacity: 0;
    transition: opacity .15s ease;
    pointer-events: none;
}
.hp-newsletter__btn:focus-visible::after { opacity: 1; }
.hp-newsletter__btn .fa-spinner { display: none; margin-left: 6px; }
.hp-newsletter__form.loading .hp-newsletter__btn .fa-spinner { display: inline-block; }
.hp-newsletter .form-mess { margin-top: 8px; font-size: 13px; }

@media (max-width: 767px) {
    .hp-newsletter { padding: 20px 0 32px; }
    .hp-newsletter__inner { padding: 20px; flex-direction: column; align-items: flex-start; }
    .hp-newsletter__media { flex: 0 1 auto; width: 100%; }
    .hp-newsletter__form { flex: 0 1 auto; max-width: 100%; width: 100%; }
}

/* ── Scroll-to-search floating button ────────────────────────────────────────
   Stacked above the .mojito-open-livechat bubble (fixed, right:12px,
   bottom:15px, 44x44, z-index:2000 — injected by GTM at runtime, not in this
   repo) so the two floating buttons don't overlap. */
.hp-scroll-to-search {
    position: fixed;
    right: 20px;
    bottom: 75px;
    z-index: 1000;
    width: 44px;
    height: 44px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    border: none;
    outline: none;
    color: #fff;
    font-size: 16px;
    background-image: linear-gradient(90deg, var(--systemColor, #ff2f00), #fff000);
    box-shadow: 0 4px 14px rgba(0, 0, 0, .25);
    cursor: pointer;
    transition: filter .15s, transform .1s, opacity .2s ease;
}
.hp-scroll-to-search:hover { filter: brightness(1.05); }
.hp-scroll-to-search:active { transform: scale(.94); }
.hp-scroll-to-search--hidden {
    opacity: 0;
    pointer-events: none;
    transform: scale(.8);
}

@media (max-width: 767px) {
    .hp-scroll-to-search { right: 16px; bottom: 66px; width: 40px; height: 40px; font-size: 14px; }
}
