/* ============================================================================
   Immersive layer — the 3D and motion vocabulary that sits on top of the
   design tokens.

   Everything here is a progressive enhancement in the strict sense: with JS
   disabled, every element in this file still renders as a normal, readable,
   clickable card. The destination cards' 3D is pure CSS :hover — no script at
   all — and the pieces immersive.js does drive (parallax, the glow, the
   progress bar) all have a resting default declared here, so "no script"
   degrades to "flat and static", never to "blank" or "broken".

   Why it lives in its own sheet rather than in home-sections.css: these are
   the only rules on the site that use 3D transforms and pointer tracking, and
   they are heavy. Keeping them separate means the interior pages that do not
   use them can stop loading them (see _Layout.cshtml's per-area block).
   ========================================================================== */

/* ---------------------------------------------------- scroll progress ---- */

/* Reading position for a long landing page. Fixed to the very top, above the
   header, because it is chrome for the whole document rather than part of it. */
.rx-progress {
    position: fixed;
    inset: 0 0 auto;
    height: 3px;
    z-index: 999;
    background: transparent;
    pointer-events: none;
}

.rx-progress__bar {
    height: 100%;
    width: 0;
    background: linear-gradient(90deg, var(--pt-lime-500), var(--pt-blue-500));
    box-shadow: 0 0 12px rgba(243, 144, 43, .5);
    transition: width .1s linear;
}

/* ------------------------------------------------------- pointer glow ---- */

/* A soft light that trails the cursor across dark sections. Deliberately not a
   cursor *replacement* — hiding the real cursor breaks affordances and hurts
   anyone relying on it. This is an additive glow behind the content, and it is
   switched off entirely for touch (no pointer to follow) and reduced motion. */
.rx-glow {
    position: fixed;
    top: 0;
    left: 0;
    width: 420px;
    height: 420px;
    margin: -210px 0 0 -210px;
    border-radius: 50%;
    pointer-events: none;
    z-index: 0;
    opacity: 0;
    background: radial-gradient(circle, rgba(28, 156, 142, .22), transparent 62%);
    transition: opacity .4s var(--pt-ease);
    will-change: transform;
}

.rx-glow.is-on { opacity: 1; }

@media (hover: none), (prefers-reduced-motion: reduce) {
    .rx-glow { display: none; }
}

/* =================================================== destination cards ====
   The "card opens up" effect: on hover the cover photo tilts away from the
   viewer on its X axis while the type and a circular cut-out of the same photo
   fly toward the viewer on Z. Because the pieces move in opposite directions
   the card reads as a physical object opening, not as a picture being scaled.

   Adapted from the well-known Mythrill card experiment. The original layers
   three bespoke assets per card — a cover, a pre-rendered title image and a
   transparent cut-out of the character. This site has exactly one photograph
   per destination, authored in the CRM, so:

     · the title image becomes real text (selectable, translatable, indexable,
       and it cannot go stale when a destination is renamed), and
     · the "character" becomes a circular porthole of the same photograph. It
       needs no second asset, it can never mismatch the cover, and it works for
       any destination the CRM adds later — where a hand-cut silhouette would
       have to be produced per city and would be missing for every new one.

   Pure CSS. There is no JS behind this at all.
   ========================================================================== */

.mx-grid {
    display: grid;
    /* The generous top gap is working space: the porthole and the title travel
       up out of the card on hover, and a tight row would clip them. */
    gap: clamp(3.5rem, 5vw, 5rem) clamp(1.5rem, 2.5vw, 2.5rem);
    grid-template-columns: repeat(auto-fit, minmax(min(100%, 250px), 1fr));
    padding-block: clamp(2.5rem, 4vw, 4rem) 1rem;
}

.mx-card {
    position: relative;
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    aspect-ratio: 2 / 3;
    padding: 0 1.25rem 1.5rem;
    /* The scene depth every child's translateZ is measured against. Shallower
       than the original experiment's 2500px because our title is live text
       rather than a pre-rendered image: at 2500px a 90px push forward scales
       it by under 4%, which reads as "moved up" rather than "came toward you". */
    perspective: 1500px;
    color: inherit;
    text-decoration: none;
}

/* -- the cover, which tilts away ------------------------------------------ */

.mx-card__wrapper {
    position: absolute;
    inset: 0;
    z-index: 1;
    border-radius: 26px 8px 26px 8px;
    overflow: hidden;
    background: var(--pt-ink-700);
    transition: transform .55s var(--pt-ease-out), box-shadow .55s var(--pt-ease-out);
}

.mx-card__wrapper img { width: 100%; height: 100%; object-fit: cover; }

.mx-card:hover .mx-card__wrapper,
.mx-card:focus-visible .mx-card__wrapper {
    transform: perspective(900px) translateY(-4%) rotateX(22deg);
    box-shadow: 2px 35px 32px -8px rgba(4, 25, 26, .75);
}

/* Two scrims: the bottom one is always on so the type has something to sit
   against, the top one only arrives on hover, to bed in the porthole once it
   has risen into the upper half of the frame. */
.mx-card__wrapper::before,
.mx-card__wrapper::after {
    content: "";
    position: absolute;
    left: 0;
    width: 100%;
    transition: opacity .55s var(--pt-ease), height .55s var(--pt-ease);
    pointer-events: none;
}

.mx-card__wrapper::before {
    top: 0;
    height: 100%;
    opacity: 0;
    background-image: linear-gradient(to top, transparent 46%, rgba(4, 25, 26, .5) 68%, rgba(4, 25, 26, .95) 97%);
}

.mx-card__wrapper::after {
    bottom: 0;
    height: 62%;
    opacity: 1;
    background-image: linear-gradient(to bottom, transparent 30%, rgba(4, 25, 26, .62) 66%, rgba(4, 25, 26, .96) 97%);
}

.mx-card:hover .mx-card__wrapper::before { opacity: 1; }
.mx-card:hover .mx-card__wrapper::after { height: 76%; }

/* -- the porthole, which flies out --------------------------------------- */

.mx-card__pop {
    position: absolute;
    left: 50%;
    bottom: 34%;
    width: 56%;
    /* Half the width, so the circle stays centred on the card's axis. */
    margin-left: -28%;
    aspect-ratio: 1;
    z-index: 2;
    border-radius: 50%;
    overflow: hidden;
    border: 3px solid rgba(255, 255, 255, .9);
    box-shadow: 0 26px 48px rgba(4, 25, 26, .62);
    opacity: 0;
    transform: translate3d(0, 8%, 0) scale(.86);
    transition: opacity .55s var(--pt-ease), transform .55s var(--pt-ease-out);
    pointer-events: none;
}

.mx-card__pop img { width: 100%; height: 100%; object-fit: cover; }

.mx-card:hover .mx-card__pop,
.mx-card:focus-visible .mx-card__pop {
    opacity: 1;
    transform: translate3d(0, -30%, 100px) scale(1);
}

/* -- the second photograph, which breaks the frame ----------------------- */

/* A real photo of the same place, mounted like a print and lifted out of the
   card. It replaced a flat vector silhouette, which at this size read as a
   sticker pasted over the photography rather than as part of it — the whole
   effect depends on the thing that escapes the frame looking as real as the
   frame it escapes from.

   Starts sunk inside the card and invisible; on hover it rises far enough that
   its top clears the card's upper edge entirely. Nothing clips it because only
   .mx-card__wrapper has overflow:hidden, and this is the wrapper's sibling. */
.mx-card__figure {
    position: absolute;
    left: 50%;
    /* Sized so the cover still shows down both sides and along the bottom: at
       88% wide the portal covered the card completely and the tilt underneath
       it — the whole point of the effect — became invisible. */
    bottom: 34%;
    width: 62%;
    margin-left: -31%;
    z-index: 2;
    opacity: 0;
    transform: translate3d(0, 12%, 0) scale(.88);
    transition: opacity .5s var(--pt-ease), transform .6s var(--pt-ease-out);
    pointer-events: none;
    /* drop-shadow, not box-shadow: it follows the masked alpha silhouette
       below, so the shadow traces the subject's outline instead of drawing a
       rectangle around it. That box is what made the previous version read as
       picture-in-picture rather than as something standing free of the card. */
    filter: drop-shadow(0 26px 30px rgba(4, 25, 26, .85));
}

/* An arched portal rather than a rectangle, with its base dissolved into the
   card by a gradient mask — so the photograph appears to rise out of the cover
   rather than sit on top of it in a box.

   Two approaches were tried and rejected before this one: a flat vector
   silhouette (read as a sticker over the photography) and the photo clipped to
   a landmark outline (the shape filled with sky and water instead of the
   subject, because a stock photo's composition never lines up with a traced
   outline). Both failures came from the same place — without a genuine
   transparent cut-out there is nothing to trace, so the honest move is a shape
   that is deliberately abstract and reads as a frame the image escapes from.

   --pos aims the subject inside the portal and is set per card in the markup. */
.mx-card__figure-in {
    display: block;
    width: 100%;
    aspect-ratio: 4 / 5;
    border-radius: 46% 46% 16px 16px / 32% 32% 16px 16px;
    overflow: hidden;
    -webkit-mask-image: linear-gradient(to bottom, #000 56%, rgba(0, 0, 0, .5) 84%, transparent 100%);
            mask-image: linear-gradient(to bottom, #000 56%, rgba(0, 0, 0, .5) 84%, transparent 100%);
}

.mx-card__figure-in img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: var(--pos, center);
}

.mx-card:hover .mx-card__figure,
.mx-card:focus-visible .mx-card__figure {
    opacity: 1;
    transform: translate3d(0, -46%, 120px) scale(1);
}

/* -- the type, which rises ------------------------------------------------ */

.mx-card__body {
    position: relative;
    z-index: 3;
    text-align: center;
    color: #fff;
    transition: transform .55s var(--pt-ease-out);
}

.mx-card:hover .mx-card__body,
.mx-card:focus-visible .mx-card__body { transform: translate3d(0, -26px, 90px); }

.mx-card__country {
    display: inline-block;
    margin-bottom: .3rem;
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-xs);
    font-weight: 700;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--pt-lime-500);
}

.mx-card__city {
    display: block;
    font-family: var(--pt-font-accent);
    font-size: clamp(1.6rem, 2.2vw, 2.15rem);
    line-height: 1;
    color: #fff;
}

/* Trails the title by a shorter Z distance, so the two separate as they rise
   instead of moving as one block. */
.mx-card__meta {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: .35rem;
    margin-top: .45rem;
    font-size: var(--pt-text-sm);
    color: rgba(255, 255, 255, .78);
    transition: transform .55s var(--pt-ease-out);
}

.mx-card__meta svg { width: 14px; height: 14px; }
.mx-card:hover .mx-card__meta { transform: translate3d(0, 0, 30px); }

/* One line of copy that only exists on the showcase cards. Hidden until hover
   so the resting card stays a photograph with a name on it, the way the
   reference does. */
.mx-card__blurb {
    display: block;
    max-width: 26ch;
    margin: .5rem auto 0;
    font-size: var(--pt-text-sm);
    line-height: 1.5;
    color: rgba(255, 255, 255, .78);
    opacity: 0;
    max-height: 0;
    overflow: hidden;
    transition: opacity .45s var(--pt-ease) .1s, max-height .45s var(--pt-ease);
}

.mx-card:hover .mx-card__blurb,
.mx-card:focus-visible .mx-card__blurb { opacity: 1; max-height: 5rem; }

/* The showcase band sits on ink, so its cards need a touch more separation
   from the background than the ones on paper do. */
.mx-showcase { position: relative; isolation: isolate; }

/* Softer than the shadow used on ink: on a pale band the heavy one read as a
   dark halo around every card. */
.mx-showcase .mx-card__wrapper { box-shadow: 0 16px 34px rgba(4, 25, 26, .18); }

/* Enough room for the arch to rise without clipping, and no more — the
   previous 6rem left an empty band under the heading. */
.mx-showcase .mx-grid { padding-block: clamp(2.25rem, 3.5vw, 3.5rem) 1rem; }

/* A pale line-art wallpaper rather than a photograph. A darkened photo behind
   the band read as noise — fragments of type and objects showing through at
   half opacity — and it left the hero's white wave divider stranded between two
   dark sections, where it looked like a stray stripe rather than a transition.
   A light section with a drawn pattern fixes both: the wave now lands on the
   light band it was always shaped for. */
.mx-showcase { background: var(--pt-blue-050); }

.mx-showcase::before {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    /* Tile kept small so the motifs read as a wallpaper texture; scaled up they
       start looking like illustrations someone forgot to remove. */
    background: url("../img/travel-pattern.svg") 0 0 / 320px 320px repeat;
    opacity: .8;
    /* Fades the wallpaper out top and bottom so the band blends into the
       sections either side instead of starting and stopping abruptly. */
    -webkit-mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
            mask-image: linear-gradient(180deg, transparent, #000 18%, #000 82%, transparent);
}

.mx-card:focus-visible { outline: none; }
.mx-card:focus-visible .mx-card__wrapper { box-shadow: 0 0 0 3px var(--pt-lime-500), 2px 35px 32px -8px rgba(4, 25, 26, .75); }

/* Without a hover pointer the effect can never be triggered, and a tap would
   fire it on the way to following the link. Show the flat, finished card. */
@media (hover: none) {
    .mx-card__pop { display: none; }
    .mx-grid,
    .mx-showcase .mx-grid { gap: var(--pt-gap-lg); padding-block: 1rem; }

    /* No hover to trigger it, and a tap would fire it on the way to following
       the link — so the card stays a single clean photograph. */
    .mx-card__figure { display: none; }

    .mx-card__blurb { opacity: 1; max-height: 5rem; }
}

@media (prefers-reduced-motion: reduce) {
    .mx-card__wrapper,
    .mx-card__body,
    .mx-card__meta,
    .mx-card__figure,
    .mx-card__pop { transition: none; }

    .mx-card:hover .mx-card__wrapper,
    .mx-card:hover .mx-card__body,
    .mx-card:hover .mx-card__meta { transform: none; }

    .mx-card:hover .mx-card__figure { transform: translate3d(0, -40%, 0) scale(1); }
    .mx-card__pop { display: none; }
}

/* ============================================================ 3D globe ====
   Drawn entirely in CSS — no texture image, no WebGL, no library. A dotted
   land pattern scrolls horizontally behind a spherical shading layer, which is
   what produces the read of a rotating ball: the dots move, the highlight and
   the limb shadow do not.

   The alternative (a canvas/WebGL globe) would cost a dependency and a few
   hundred KB for a decorative element, and would leave a blank hole for anyone
   it fails on. This degrades to a handsome static sphere.
   ========================================================================== */

.rx-globe {
    position: relative;
    width: min(100%, 420px);
    aspect-ratio: 1;
    margin-inline: auto;
    display: grid;
    place-items: center;
}

.rx-globe__sphere {
    position: relative;
    z-index: 1;
    width: 78%;
    height: 78%;
    border-radius: 50%;
    overflow: hidden;
    background: radial-gradient(circle at 32% 26%, var(--pt-blue-600) 0%, var(--pt-blue-800) 42%, var(--pt-ink-900) 78%);
    box-shadow:
        inset -18px -22px 60px rgba(0, 0, 0, .75),
        inset 12px 14px 40px rgba(28, 156, 142, .35),
        0 30px 70px rgba(4, 25, 26, .55);
}

/* Graticule: a faint dot matrix scrolled sideways forever, sitting under the
   landmasses so the ocean still reads as a surface rather than flat colour.
   Masked to fade toward the limb, which is what stops it reading as a flat
   patterned disc. */
.rx-globe__texture {
    position: absolute;
    inset: 0;
    background-image: radial-gradient(circle, rgba(190, 231, 223, .28) 1.5px, transparent 1.6px);
    background-size: 20px 20px;
    animation: rx-globe-spin 26s linear infinite;
    -webkit-mask-image: radial-gradient(circle at 50% 50%, #000 42%, rgba(0, 0, 0, .35) 68%, transparent 82%);
            mask-image: radial-gradient(circle at 50% 50%, #000 42%, rgba(0, 0, 0, .35) 68%, transparent 82%);
}

@keyframes rx-globe-spin {
    from { background-position: 0 0; }
    to   { background-position: 400px 0; }
}

/* The continents. The map is an alpha mask rather than an <img>, so the land
   takes its colour from this element's own background and cannot drift from
   the palette.

   Tile width is 1.5 sphere-widths, so about two thirds of the world shows at
   once. A geographically honest globe would show exactly half (a 200% tile),
   but half the world can be almost entirely Pacific — the sphere went blank
   for a stretch of every rotation, which read as the map having run out.
   Two thirds always has land in frame.

   The keyframe travels exactly one tile so the loop closes seamlessly. The
   percentage is not the tile width: mask-position resolves against
   (element − image), so the end value is size/(100% − size) — with a 150%
   tile that is -300%, and it has to be recomputed if the size ever changes. */
.rx-globe__map { position: absolute; inset: 0; }

@supports ((-webkit-mask-image: url("../img/world-map.svg")) or (mask-image: url("../img/world-map.svg"))) {
    .rx-globe__map {
        background-color: rgba(214, 243, 236, .92);
        -webkit-mask-image: url("../img/world-map.svg");
                mask-image: url("../img/world-map.svg");
        -webkit-mask-repeat: repeat-x;
                mask-repeat: repeat-x;
        -webkit-mask-size: 150% 100%;
                mask-size: 150% 100%;
        -webkit-mask-position: 0 0;
                mask-position: 0 0;
        animation: rx-globe-map 48s linear infinite;
    }
}

@keyframes rx-globe-map {
    from { -webkit-mask-position: 0 0;      mask-position: 0 0; }
    to   { -webkit-mask-position: -300% 0;  mask-position: -300% 0; }
}

/* Sphere shading, painted over the land so the globe reads as lit from the
   upper left and falling away at the limb. Sits above the map and below the
   pins — a pin behind the limb shadow would look like a smudge. */
.rx-globe__shade {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    pointer-events: none;
    background:
        radial-gradient(circle at 30% 24%, rgba(255, 255, 255, .20), transparent 48%),
        radial-gradient(circle at 50% 50%, transparent 50%, rgba(4, 25, 26, .45) 76%, rgba(4, 25, 26, .9) 100%);
}

/* Atmospheric rim — a bright halo just outside the sphere's edge. */
.rx-globe__halo {
    position: absolute;
    inset: 8%;
    border-radius: 50%;
    pointer-events: none;
    box-shadow: 0 0 60px 6px rgba(28, 156, 142, .45);
}

/* Orbit rings, tilted in 3D so they pass in front of and behind the sphere. */
.rx-globe__orbit {
    position: absolute;
    inset: 0;
    border-radius: 50%;
    border: 1px dashed rgba(190, 231, 223, .42);
    transform-style: preserve-3d;
}

/* Ring A carries the plane and is lifted above the sphere. The sphere is a
   later sibling, so at 90° and 270° — where the orbit crosses the globe's face
   — it was painting straight over the marker and the plane simply disappeared
   for half of every lap. Raising the ring keeps the marker on its own line the
   whole way round. Ring B stays behind the globe, which is what still gives the
   pair a sense of depth. */
.rx-globe__orbit--a { z-index: 5; transform: rotateX(76deg) rotateZ(8deg); animation: rx-orbit 18s linear infinite; }
.rx-globe__orbit--b { z-index: 0; inset: 6%; transform: rotateX(70deg) rotateZ(-32deg); border-color: rgba(243, 144, 43, .45); animation: rx-orbit 26s linear infinite reverse; }

/* Held at the same 76deg tilt the ring's static rule uses, because the plane
   riding this ring cancels exactly that angle to stay upright. */
@keyframes rx-orbit {
    from { transform: rotateX(76deg) rotateZ(0deg); }
    to   { transform: rotateX(76deg) rotateZ(360deg); }
}

/* The plane rides the dashed ring itself rather than a separate circle of its
   own: it is a *child* of .rx-globe__orbit--a, parked on that ring's edge, so
   the parent's rotateX tilt and rotateZ spin carry it around the exact ellipse
   the ring draws. Orbiting it independently is what previously left it
   crossing empty space with no line under it.

   Its own animation is the inverse of the parent's — same duration, same
   linear timing, so the two stay locked — which cancels the tilt and the spin
   and leaves the icon upright and facing the viewer the whole way round. */
.rx-globe__sat {
    position: absolute;
    top: 50%;
    left: 0;
    width: 34px;
    height: 34px;
    margin: -17px 0 0 -17px;
    display: grid;
    place-items: center;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--pt-lime-500), var(--pt-lime-600));
    color: var(--pt-ink-900);
    box-shadow: 0 8px 22px rgba(225, 122, 30, .5);
    transform: rotateZ(0deg) rotateX(-76deg);
    animation: rx-sat-face 18s linear infinite;
}

.rx-globe__sat svg { width: 17px; height: 17px; }

@keyframes rx-sat-face {
    from { transform: rotateZ(0deg) rotateX(-76deg); }
    to   { transform: rotateZ(-360deg) rotateX(-76deg); }
}

/* Pins dropped on the sphere. Positioned by --x/--y set inline per pin. */
.rx-globe__pin {
    position: absolute;
    left: var(--x);
    top: var(--y);
    width: 12px;
    height: 12px;
    margin: -6px 0 0 -6px;
    border-radius: 50%;
    background: var(--pt-lime-500);
    box-shadow: 0 0 0 3px rgba(243, 144, 43, .25);
}

.rx-globe__pin::after {
    content: "";
    position: absolute;
    inset: -6px;
    border-radius: 50%;
    border: 2px solid var(--pt-lime-500);
    opacity: 0;
    animation: rx-ping 2.8s var(--pt-ease-out) infinite;
    animation-delay: var(--d, 0s);
}

@keyframes rx-ping {
    0%   { transform: scale(.6); opacity: .9; }
    70%  { transform: scale(2.1); opacity: 0; }
    100% { transform: scale(2.1); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
    .rx-globe__texture,
    .rx-globe__map,
    .rx-globe__orbit--a,
    .rx-globe__orbit--b,
    .rx-globe__sat,
    .rx-globe__pin::after { animation: none; }
}

/* ---------------------------------------------------- globe centre plate -- */

/* The headline figure sitting inside the sphere. Above the texture and the
   pins, below the country cards that overlap the globe's edge. */
.rx-globe__core {
    position: absolute;
    inset: 0;
    z-index: 3;
    display: grid;
    place-content: center;
    text-align: center;
    pointer-events: none;
}

/* Soft scrim behind the figure. Without it the type sits directly on the
   continents and the coastlines read as noise through the letterforms. */
.rx-globe__core::before {
    content: "";
    position: absolute;
    top: 50%;
    left: 50%;
    width: 74%;
    height: 46%;
    transform: translate(-50%, -50%);
    border-radius: 50%;
    background: radial-gradient(ellipse, rgba(4, 25, 26, .78), rgba(4, 25, 26, .45) 55%, transparent 76%);
}

.rx-globe__core strong,
.rx-globe__core span { position: relative; }

.rx-globe__core strong {
    display: block;
    font-family: var(--pt-font-accent);
    font-size: clamp(1.9rem, 3.2vw, 2.8rem);
    line-height: 1;
    color: #fff;
    text-shadow: 0 2px 18px rgba(4, 25, 26, .8);
}

.rx-globe__core span {
    display: block;
    margin-top: .3rem;
    font-family: var(--pt-font-display);
    font-size: .68rem;
    font-weight: 700;
    letter-spacing: .2em;
    text-transform: uppercase;
    color: var(--pt-lime-300);
}

/* ======================================================== country orbit ===
   The hero's right-hand stage: the globe with country cards floating over and
   around it. Cards are placed with --x/--y percentages of this box rather
   than a flex/grid flow, because the whole point is an irregular scatter that
   reads as depth — a tidy grid of the same cards reads as a table.
   ========================================================================== */

.rx-orbit {
    position: relative;
    display: grid;
    place-items: center;
    min-height: clamp(380px, 46vw, 560px);
}

.rx-orbit .rx-globe { width: min(100%, 380px); }

.rx-country {
    position: absolute;
    left: var(--x);
    top: var(--y);
    z-index: 4;
    display: flex;
    align-items: center;
    gap: .6rem;
    padding: .6rem .85rem;
    border-radius: 14px;
    border: 1px solid rgba(255, 255, 255, .12);
    background: rgba(10, 38, 36, .82);
    backdrop-filter: blur(10px);
    box-shadow: 0 14px 34px rgba(4, 25, 26, .55);
    white-space: nowrap;
    color: inherit;
    text-decoration: none;
    animation: rx-float 7s var(--pt-ease) infinite;
    animation-delay: var(--d, 0s);
    transition: border-color .25s var(--pt-ease), box-shadow .25s var(--pt-ease);
}

.rx-country:hover {
    border-color: rgba(243, 144, 43, .8);
    box-shadow: 0 18px 40px rgba(4, 25, 26, .7);
}

/* Flag plate. The hairline ring keeps a flag with a white edge (Japan,
   Georgia, Indonesia) from bleeding into the card behind it. */
.rx-flag {
    width: 26px;
    height: 17.3px;
    flex: none;
    border-radius: 3px;
    box-shadow: 0 0 0 1px rgba(255, 255, 255, .35), 0 2px 5px rgba(4, 25, 26, .5);
}

.rx-country__name {
    display: block;
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-sm);
    font-weight: 700;
    color: #fff;
    line-height: 1.2;
}

.rx-country__region {
    display: block;
    font-size: var(--pt-text-xs);
    color: rgba(255, 255, 255, .6);
    line-height: 1.2;
}

@keyframes rx-float {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-11px); }
}

/* Below this the cards have nowhere to go without covering the globe or
   spilling out of the column, so the stage keeps the globe alone. */
@media (max-width: 1100px) {
    .rx-country { display: none; }
    .rx-orbit { min-height: 340px; }
}

@media (prefers-reduced-motion: reduce) {
    .rx-country { animation: none; }
}

/* ================================================= signature experiences ==
   A wide feature strip whose panels expand on hover/focus into a full picture
   with copy — the "accordion gallery" pattern. It gives a lot of photographic
   surface (which is what makes a travel homepage feel rich) in a fixed height,
   and it is genuinely interactive rather than decorative.
   ========================================================================== */

.rx-strip {
    display: flex;
    gap: .75rem;
    height: clamp(360px, 52vh, 520px);
}

.rx-panel {
    position: relative;
    flex: 1;
    min-width: 0;
    border-radius: 26px 10px 26px 10px;
    overflow: hidden;
    color: #fff;
    text-decoration: none;
    background: var(--pt-ink-700);
    transition: flex .6s var(--pt-ease-out);
}

/* The open panel takes roughly half the strip; the rest share what is left. */
.rx-panel.is-open { flex: 3.2; }

.rx-panel img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform .8s var(--pt-ease-out), filter .6s var(--pt-ease);
    filter: saturate(.75) brightness(.62);
}

.rx-panel.is-open img { filter: saturate(1.05) brightness(.82); transform: scale(1.04); }

.rx-panel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 40%, rgba(4, 25, 26, .9));
}

.rx-panel__body {
    position: absolute;
    inset: auto 0 0;
    z-index: 2;
    padding: clamp(1rem, 2vw, 1.6rem);
}

/* Each part is a block: the markup uses <span> throughout (the panel is an
   <a>, so it may not contain <p>/<h3>), and inline children would otherwise
   run the number, the title and the copy together on one line. */
.rx-panel__index,
.rx-panel__title,
.rx-panel__text,
.rx-panel__go { display: block; }

.rx-panel__index {
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-xs);
    font-weight: 700;
    letter-spacing: .12em;
    color: var(--pt-lime-500);
}

.rx-panel__title {
    font-family: var(--pt-font-accent);
    font-size: clamp(1.35rem, 1.8vw, 1.9rem);
    line-height: 1.05;
    color: #fff;
    margin: .25rem 0 0;
    /* Vertical until the panel opens: a closed panel is too narrow for
       horizontal text, and rotating it is what makes the strip readable at
       every width instead of clipping to initials. Capped so a long title
       cannot grow the bottom-anchored body taller than the panel itself. */
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    max-height: 15rem;
    overflow: hidden;
}

.rx-panel.is-open .rx-panel__title {
    writing-mode: horizontal-tb;
    transform: none;
    max-height: none;
}

/* A closed panel shows its vertical title and nothing else. The number, the
   paragraph and the link are all horizontal text far wider than the ~150px a
   closed panel gets, so leaving them in the flow pushed the body past the
   panel's top edge and spilled the labels across its neighbours. */
.rx-panel:not(.is-open) .rx-panel__index,
.rx-panel:not(.is-open) .rx-panel__text,
.rx-panel:not(.is-open) .rx-panel__go { display: none; }

.rx-panel__text {
    max-width: 34ch;
    margin: .5rem 0 0;
    font-size: var(--pt-text-sm);
    color: rgba(255, 255, 255, .82);
    opacity: 0;
    transition: opacity .4s var(--pt-ease) .15s;
}

.rx-panel.is-open .rx-panel__text { opacity: 1; }

.rx-panel__go {
    margin-top: .7rem;
    font-family: var(--pt-font-display);
    font-size: var(--pt-text-sm);
    font-weight: 700;
    color: var(--pt-lime-500);
    opacity: 0;
    transition: opacity .4s var(--pt-ease) .2s;
}

.rx-panel__go svg { width: 15px; height: 15px; vertical-align: -2px; margin-left: .2rem; }
.rx-panel.is-open .rx-panel__go { opacity: 1; }
.rx-panel:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--pt-lime-500); }

/* Below the strip's usable width the accordion becomes a plain scroll rail —
   an accordion needs horizontal room to mean anything, and on a phone the
   closed panels would be a few pixels wide. */
@media (max-width: 820px) {
    .rx-strip {
        height: auto;
        overflow-x: auto;
        scroll-snap-type: x mandatory;
        scrollbar-width: none;
        padding-bottom: .5rem;
    }

    .rx-strip::-webkit-scrollbar { display: none; }

    .rx-panel,
    .rx-panel.is-open { flex: 0 0 78%; height: 380px; scroll-snap-align: start; }
    .rx-panel img { filter: saturate(1) brightness(.72); }

    /* Every panel is effectively "open" on a rail — each one has full width,
       so the closed-state hiding above must be undone or the cards would be
       photographs with a vertical title and nothing else. */
    .rx-panel__title { writing-mode: horizontal-tb; transform: none; max-height: none; }

    .rx-panel .rx-panel__index,
    .rx-panel .rx-panel__text,
    .rx-panel .rx-panel__go { display: block; opacity: 1; }
}

/* ---------------------------------------------------------- magnetic ----- */

/* Buttons that lean toward the cursor. A 6px pull — enough to feel responsive,
   not enough to make the target hard to actually hit. */
.rx-magnetic { transition: transform .35s var(--pt-ease-out); will-change: transform; }

@media (hover: none), (prefers-reduced-motion: reduce) {
    .rx-magnetic { transform: none !important; }
}

/* ----------------------------------------------------------- parallax ---- */

/* Drift driven by scroll position, written by immersive.js as --py. */
.rx-parallax { transform: translate3d(0, var(--py, 0px), 0); will-change: transform; }

@media (prefers-reduced-motion: reduce) {
    .rx-parallax { transform: none !important; }
}

/* -------------------------------------------------------- counter band --- */

/* Stat row for the globe section — same figures as the getaway band, but on
   ink and with the numbers as the loudest thing on the row. */
/* Sized so four figures hold one row inside the hero's copy column (~570px at
   the container's max width): 4 × 110px + three gaps still clears it, where
   the previous 130px minimum tipped the fourth onto a second row. */
.rx-figures {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(110px, 1fr));
    gap: var(--pt-gap);
    margin-top: var(--pt-gap-xl);
    padding-top: var(--pt-gap-lg);
    border-top: 1px solid rgba(255, 255, 255, .14);
}

.rx-figure__value {
    display: block;
    font-family: var(--pt-font-accent);
    font-size: clamp(2rem, 3.4vw, 3rem);
    line-height: 1;
    color: #fff;
}

.rx-figure__label {
    display: block;
    margin-top: .3rem;
    font-size: var(--pt-text-sm);
    color: rgba(255, 255, 255, .62);
}
