/**
 * My Trip India — site stylesheet
 * ------------------------------------------------------------
 * Tailwind (CDN) does the layout, spacing and one-off styling in the markup.
 * This file holds only what utilities do badly: the component classes that
 * repeat across ten pages, the animation base states, and a few things
 * Tailwind has no vocabulary for (grain, masks, marquee, Swiper overrides).
 *
 * The palette lives in js/theme.js as the Tailwind config. It is mirrored
 * into CSS custom properties below so plain CSS here can reach it too —
 * keep the two in step.
 *
 * Contents
 *   1.  Tokens + base
 *   2.  Typography
 *   3.  Buttons
 *   4.  Links + micro interactions
 *   5.  Surfaces: cards, glass, media
 *   6.  Chips, tags, badges
 *   7.  Forms
 *   8.  Header + navigation
 *   9.  Scroll progress
 *   10. Animation base states  (GSAP reveals)
 *   11. Chatbot
 *   12. Enquiry drawer
 *   13. Swiper overrides
 *   14. Orbit rings  (decorative)
 *   15. Utilities
 *   16. Search bar
 *   17. Travel backdrop  (decorative)
 *   18. Destination rail + cards
 *   19. How it works (steps)
 *   20. App showcase (phone mockups)
 *   21. Why us (drifting columns)
 *   22. Map embed
 *   23. Reduced motion
 */

/* ============================================================
   1. TOKENS + BASE
   ============================================================ */
/* Deep Teal on Neutral — mirrored from ../../css/tokens.css, the palette the
   app mockups and the admin console already use. js/theme.js carries the same
   values for Tailwind; change one, change the other. */
:root {
    --ink: #12212E;          /* --it-ink       */
    --ink-80: #2B3A46;
    --ink-60: #566169;       /* --it-muted     */
    --ink-40: #8A939A;
    --paper: #F2F4F5;        /* --it-bg        */
    --paper-2: #E8ECEE;
    --paper-3: #DADFE2;      /* --it-border    */
    --line: #DADFE2;
    --line-dk: #B8BFC4;
    --brand: #2C6B7E;        /* --it-accent       — every primary action */
    --brand-deep: #1F4F5E;   /* --it-accent-deep  — the brand as small text */
    --brand-light: #367888;  /* --it-accent-light */
    --brand-soft: #DCE9EC;   /* --it-accent-soft  */
    --success: #22713F;      /* --it-success      — green means only success */
    --success-lt: #2E8C51;
    --success-soft: #E7F4EC;
    --highlight: #EA9010;    /* --it-highlight    — the warm spark */
    --highlight-deep: #8A5205;
    --danger: #A63A2B;       /* --it-danger       */

    --shell: 82rem;
    /* The header sheds height once it sticks. Everything that has to sit
       directly under it — the filter bars, the landing place of an in-page
       link — reads this one number, so they cannot drift apart again. */
    --head-stuck: 60px;
    --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* Native smooth scrolling is the fallback. When Lenis takes over (see
   initSmoothScroll in js/main.js) it drives the scroll position itself,
   and the two fight — so Lenis's own class switches this back off. */
html { scroll-behavior: smooth; }

/* the sticky header must not cover the target of an in-page link, and must
   not leave a strip of page showing between the two either */
[id] { scroll-margin-top: var(--head-stuck); }

/* A bar that parks itself directly beneath the stuck header. Tailwind's
   top-20 was 80px against a header that is now 60, which is exactly the
   strip of scrolling page that showed through between them. */
.stick-head { position: sticky; top: var(--head-stuck); z-index: 40; }

/* ── Lenis, the smooth-scroll layer ──────────────────────
   Lenis adds `lenis` to <html>, so these only bite once it is actually
   running — a page without it keeps the native behaviour above.

   The !important is load-bearing. ScrollTrigger flips scroll-behavior to
   auto while it refreshes and then writes the element's original computed
   value back as an INLINE style — which, given the rule above, is `smooth`.
   Lenis driving the scroll position while the browser also animates it
   makes the wheel feel heavy and late. An !important declaration outranks
   a non-important inline style, so this is what settles it. */
html.lenis { scroll-behavior: auto !important; }
html.lenis, html.lenis body { height: auto; }
/* modal and drawer call lenis.stop(), which lands here */
html.lenis-stopped { overflow: hidden; }
/* anything with its own scrollbar keeps the wheel: chat log, plan sheet */
html.lenis [data-lenis-prevent] { overscroll-behavior: contain; }

body {
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
    /* the one guard against a rogue wide child on small screens */
    overflow-x: hidden;
}

::selection { background: var(--brand); color: #fff; }

/* a focus ring that reads on both the paper and the ink grounds */
:focus-visible {
    outline: 2px solid var(--brand);
    outline-offset: 3px;
    border-radius: 4px;
}
.on-dark :focus-visible { outline-color: var(--highlight); }

/* slim neutral scrollbar — Firefox first, then WebKit */
* { scrollbar-width: thin; scrollbar-color: var(--line-dk) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--line-dk); border-radius: 99px; border: 3px solid var(--paper); }
::-webkit-scrollbar-thumb:hover { background: var(--brand-light); }

/* ============================================================
   2. TYPOGRAPHY
   ============================================================ */
.display {
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 400;
    font-variation-settings: 'SOFT' 0, 'WONK' 1, 'opsz' 90;
    text-wrap: balance;
}
.display em {
    font-style: italic;
    font-variation-settings: 'SOFT' 40, 'WONK' 1, 'opsz' 90;
    color: var(--brand);
}
.on-dark .display em { color: var(--highlight); }

.eyebrow {
    display: inline-flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--brand-deep);
}
.eyebrow::before {
    content: '';
    width: 1.75rem;
    height: 1px;
    background: currentColor;
    opacity: 0.6;
}
.on-dark .eyebrow { color: var(--highlight); }

.lede {
    font-size: 1.0625rem;
    line-height: 1.7;
    color: var(--ink-60);
    text-wrap: pretty;
}
.on-dark .lede { color: rgba(242, 244, 245, 0.7); }

/* drop the rule on an eyebrow that sits centred in its own column */
.eyebrow-plain::before { display: none; }

/* ============================================================
   3. BUTTONS
   ============================================================ */
.btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    padding: 0.9375rem 1.625rem;
    border: 1.5px solid transparent;
    border-radius: 99px;
    font-size: 0.875rem;
    font-weight: 600;
    letter-spacing: -0.01em;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out),
                background-color 0.25s, border-color 0.25s, color 0.25s;
}
.btn svg { width: 1.05em; height: 1.05em; flex: none; transition: transform 0.35s var(--ease-out); }
.btn:hover svg { transform: translateX(3px); }
.btn:active { transform: translateY(1px) scale(0.99); }

.btn-brand { background: var(--brand); color: #fff; box-shadow: 0 10px 28px rgba(44, 107, 126, 0.28); }
.btn-brand:hover { background: var(--brand-deep); transform: translateY(-2px); box-shadow: 0 16px 38px rgba(44, 107, 126, 0.34); }

.btn-ink { background: var(--ink); color: var(--paper); }
.btn-ink:hover { background: var(--ink-80); transform: translateY(-2px); box-shadow: 0 16px 34px rgba(18, 33, 46, 0.24); }

.btn-success { background: var(--success); color: var(--paper); box-shadow: 0 10px 28px rgba(34, 113, 63, 0.26); }
.btn-success:hover { background: var(--success-lt); transform: translateY(-2px); }

.btn-paper { background: var(--paper); color: var(--ink); }
.btn-paper:hover { background: #fff; transform: translateY(-2px); box-shadow: 0 16px 34px rgba(0, 0, 0, 0.18); }

.btn-outline { border-color: var(--ink); color: var(--ink); }
.btn-outline:hover { background: var(--ink); color: var(--paper); transform: translateY(-2px); }

/* on photography and ink sections */
.btn-glass {
    border-color: rgba(255, 255, 255, 0.38);
    color: #fff;
    background: rgba(255, 255, 255, 0.08);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
}
.btn-glass:hover { background: rgba(255, 255, 255, 0.18); border-color: rgba(255, 255, 255, 0.7); transform: translateY(-2px); }

.btn-lg { padding: 1.125rem 2rem; font-size: 0.9375rem; }
.btn-sm { padding: 0.6875rem 1.125rem; font-size: 0.8125rem; }

/* .btn sets display:inline-flex, and an author rule beats the browser's own
   [hidden] rule whatever the specificity — without this, JS setting
   `button.hidden = true` (the blog's Load more) would not hide anything. */
.btn[hidden], .btn-ico[hidden] { display: none; }

/* icon-only round button */
.btn-ico {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.875rem;
    height: 2.875rem;
    border-radius: 99px;
    border: 1.5px solid var(--paper-3);
    background: #fff;
    color: var(--ink);
    cursor: pointer;
    transition: background 0.25s, color 0.25s, border-color 0.25s, transform 0.35s var(--ease-out);
}
.btn-ico:hover { background: var(--ink); border-color: var(--ink); color: var(--paper); }
.btn-ico:disabled { opacity: 0.35; cursor: default; }
.btn-ico:disabled:hover { background: #fff; color: var(--ink); border-color: var(--paper-3); }

/* ============================================================
   4. LINKS + MICRO INTERACTIONS
   ============================================================ */
.link-u {
    position: relative;
    display: inline-flex;
    align-items: center;
    gap: 0.45rem;
    font-weight: 600;
    padding-bottom: 2px;
}
.link-u::after {
    content: '';
    position: absolute;
    left: 0; bottom: 0;
    width: 100%; height: 1.5px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.45s var(--ease-out);
}
.link-u:hover::after { transform: scaleX(1); transform-origin: left; }
.link-u svg { width: 1em; height: 1em; transition: transform 0.35s var(--ease-out); }
.link-u:hover svg { transform: translateX(3px); }

/* the magnetic CTA — JS writes --mx/--my, CSS does the moving */
.magnetic { transform: translate3d(var(--mx, 0), var(--my, 0), 0); }

/* ============================================================
   5. SURFACES
   ============================================================ */
.card {
    position: relative;
    background: #fff;
    border: 1px solid var(--paper-3);
    border-radius: 1.5rem;
    transition: transform 0.5s var(--ease-out), box-shadow 0.5s var(--ease-out), border-color 0.3s;
}
.card-lift:hover {
    transform: translateY(-6px);
    box-shadow: 0 6px 16px rgba(18, 33, 46, 0.07), 0 28px 60px rgba(18, 33, 46, 0.13);
    border-color: var(--line);
}

.glass {
    background: rgba(242, 244, 245, 0.82);
    backdrop-filter: blur(18px) saturate(1.4);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    border-bottom: 1px solid rgba(18, 33, 46, 0.07);
}
.glass-dark {
    background: rgba(18, 33, 46, 0.55);
    backdrop-filter: blur(18px) saturate(1.3);
    -webkit-backdrop-filter: blur(18px) saturate(1.3);
    border: 1px solid rgba(255, 255, 255, 0.12);
}

/* image that grows a little when its card is hovered */
.media { position: relative; overflow: hidden; }
.media img {
    width: 100%; height: 100%;
    object-fit: cover;
    transition: transform 1.1s var(--ease-out);
    will-change: transform;
}
.group:hover .media img,
.media:hover img { transform: scale(1.06); }

/* the gradient that keeps white text legible over photography */
/* Real photographs of real places are often bright — snow, white marble,
   a beach at noon — so the floor under the copy has to be deeper and reach
   higher than it did over the old stock imagery. */
.scrim::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to top,
        rgba(18, 33, 46, 0.94) 0%,
        rgba(18, 33, 46, 0.74) 26%,
        rgba(18, 33, 46, 0.34) 55%,
        rgba(18, 33, 46, 0.06) 80%,
        transparent 100%);
    pointer-events: none;
}

/* ::after is the element's LAST child, and among positioned siblings with no
   z-index the last one in the DOM wins. So the scrim was painting over the
   copy, not under it — which is why white text on these cards looked washed
   out however dark the gradient was made. The picture stays below, the
   gradient sits on it, the copy sits on top of both. */
.scrim > .media, .scrim-full > .media { z-index: 0; }
.scrim > :not(.media), .scrim-full > :not(.media) { position: relative; z-index: 2; }

/* Belt and braces for the same problem: a tight shadow sharpens the
   letterforms against the picture. The radius stays small on purpose —
   a wide blur makes the haloes of neighbouring letters merge into a
   smudged block behind the paragraph. */
.scrim, .scrim-full { text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45); }
.scrim .btn, .scrim-full .btn { text-shadow: none; }
.scrim-full::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    background: linear-gradient(to top, rgba(18, 33, 46, 0.82) 0%, rgba(18, 33, 46, 0.5) 45%, rgba(18, 33, 46, 0.55) 100%);
    pointer-events: none;
}

/* ============================================================
   6. CHIPS, TAGS, BADGES
   ============================================================ */
.tag {
    display: inline-flex;
    align-items: center;
    gap: 0.3rem;
    padding: 0.3125rem 0.625rem;
    border-radius: 99px;
    background: var(--paper-2);
    color: var(--ink-60);
    font-size: 0.6875rem;
    font-weight: 600;
    letter-spacing: 0.01em;
    white-space: nowrap;
}
.tag-brand { background: var(--brand-soft, #DCE9EC); color: var(--brand-deep); }
.tag-success { background: #E7F4EC; color: var(--success); }
.tag-highlight { background: #FBEFD8; color: #8A5205; }
.tag-glass { background: rgba(255, 255, 255, 0.16); color: #fff; backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px); }

/* filter pill */
.chip {
    padding: 0.5625rem 1.0625rem;
    border-radius: 99px;
    border: 1.5px solid var(--paper-3);
    background: transparent;
    color: var(--ink-60);
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    cursor: pointer;
    transition: background 0.25s, color 0.25s, border-color 0.25s;
}
.chip:hover { border-color: var(--line-dk); color: var(--ink); }
.chip[aria-pressed="true"],
.chip.is-on { background: var(--ink); border-color: var(--ink); color: var(--paper); }

/* ============================================================
   7. FORMS
   ============================================================ */
.field { display: block; }
.field > label,
.field-label {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-60);
}

.input,
.select,
.textarea {
    width: 100%;
    padding: 0.875rem 1rem;
    border: 1.5px solid var(--paper-3);
    border-radius: 0.875rem;
    background: #fff;
    font-family: inherit;
    font-size: 0.9375rem;
    color: var(--ink);
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}
.input::placeholder, .textarea::placeholder { color: var(--ink-40); }
.input:focus, .select:focus, .textarea:focus {
    border-color: var(--brand);
    box-shadow: 0 0 0 4px rgba(44, 107, 126, 0.12);
}
.textarea { resize: vertical; min-height: 7rem; line-height: 1.6; }

/* native select, restyled — the arrow is drawn here so it matches on every OS */
.select {
    appearance: none;
    -webkit-appearance: none;
    padding-right: 2.75rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23566169' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right 1rem center;
    cursor: pointer;
}

/* an input that sits on an ink or photographic ground */
.on-dark .input,
.on-dark .select,
.on-dark .textarea {
    background: rgba(255, 255, 255, 0.07);
    border-color: rgba(255, 255, 255, 0.16);
    color: var(--paper);
}
.on-dark .input::placeholder, .on-dark .textarea::placeholder { color: rgba(242, 244, 245, 0.4); }

/* Over a photograph the 7% wash above simply disappears into the picture.
   This variant carries its own frosted ground, so the field still reads as
   a field whatever is behind it. */
.on-dark .input.input-frost {
    background: rgba(255, 255, 255, 0.16);
    border-color: rgba(255, 255, 255, 0.36);
    backdrop-filter: blur(12px) saturate(1.2);
    -webkit-backdrop-filter: blur(12px) saturate(1.2);
}
.on-dark .input.input-frost::placeholder { color: rgba(242, 244, 245, 0.68); }
.on-dark .input.input-frost:focus { background: rgba(255, 255, 255, 0.22); }
.on-dark .field > label, .on-dark .field-label { color: rgba(242, 244, 245, 0.55); }
.on-dark .input:focus, .on-dark .select:focus, .on-dark .textarea:focus {
    border-color: var(--highlight);
    box-shadow: 0 0 0 4px rgba(234, 144, 16, 0.18);
    background: rgba(255, 255, 255, 0.11);
}
.on-dark .select {
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%23DADFE2' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
}
.on-dark .select option { background: var(--ink); color: var(--paper); }

/* validation */
.field.is-err .input,
.field.is-err .select,
.field.is-err .textarea { border-color: #A63A2B; box-shadow: 0 0 0 4px rgba(166, 58, 43, 0.12); }
.field .err-msg { display: none; margin-top: 0.375rem; font-size: 0.75rem; font-weight: 600; color: #A63A2B; }
.field.is-err .err-msg { display: block; }
.on-dark .field.is-err .err-msg { color: #E9A79B; }

/* checkbox / radio card — the whole tile is the control */
.opt {
    position: relative;
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.8125rem 1rem;
    border: 1.5px solid var(--paper-3);
    border-radius: 0.875rem;
    background: #fff;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ink-60);
    cursor: pointer;
    user-select: none;
    transition: border-color 0.2s, background 0.2s, color 0.2s;
}
.opt input { position: absolute; opacity: 0; pointer-events: none; }
.opt:hover { border-color: var(--line-dk); }
.opt:has(input:checked) { border-color: var(--brand); background: #DCE9EC; color: var(--brand-deep); }
.opt:has(input:focus-visible) { outline: 2px solid var(--brand); outline-offset: 3px; }
/* fallback for engines without :has() — JS mirrors the state onto the class */
.opt.is-on { border-color: var(--brand); background: #DCE9EC; color: var(--brand-deep); }

.on-dark .opt { background: rgba(255, 255, 255, 0.06); border-color: rgba(255, 255, 255, 0.16); color: rgba(242, 244, 245, 0.72); }
.on-dark .opt:has(input:checked), .on-dark .opt.is-on { background: rgba(234, 144, 16, 0.18); border-color: var(--highlight); color: #FBEFD8; }

/* range slider */
.range { width: 100%; height: 3px; border-radius: 99px; background: var(--paper-3); appearance: none; outline: none; }
.range::-webkit-slider-thumb {
    appearance: none;
    width: 1.375rem; height: 1.375rem;
    border-radius: 99px;
    background: var(--brand);
    border: 3px solid #fff;
    box-shadow: 0 2px 8px rgba(44, 107, 126, 0.4);
    cursor: pointer;
}
.range::-moz-range-thumb {
    width: 1.125rem; height: 1.125rem;
    border-radius: 99px;
    background: var(--brand);
    border: 3px solid #fff;
    box-shadow: 0 2px 8px rgba(44, 107, 126, 0.4);
    cursor: pointer;
}

/* ============================================================
   8. HEADER + NAVIGATION
   ============================================================ */
.site-head {
    position: fixed;
    top: 0; left: 0; right: 0;
    z-index: 60;
    transition: background-color 0.4s var(--ease-out), box-shadow 0.4s var(--ease-out),
                backdrop-filter 0.4s, border-color 0.4s;
    border-bottom: 1px solid transparent;
}
/* The bar sheds height once it sticks, so a page being read keeps more of the
   screen than a page at rest. The child selector is deliberate: Tailwind's
   h-20 is injected after this file and would win on its own. */
.site-head > div { transition: height 0.4s var(--ease-out); }
.site-head.is-stuck > div { height: var(--head-stuck); }

/* over the hero: transparent, white marks */
.site-head .nav-a { color: rgba(255, 255, 255, 0.82); }
.site-head .brand-mark { color: #fff; }

/* past the hero: warm glass, ink marks */
.site-head.is-stuck {
    background: rgba(242, 244, 245, 0.86);
    backdrop-filter: blur(18px) saturate(1.4);
    -webkit-backdrop-filter: blur(18px) saturate(1.4);
    border-bottom-color: rgba(18, 33, 46, 0.08);
    box-shadow: 0 1px 0 rgba(18, 33, 46, 0.03), 0 8px 28px rgba(18, 33, 46, 0.06);
}
.site-head.is-stuck .nav-a { color: var(--ink-60); }
.site-head.is-stuck .brand-mark { color: var(--ink); }
.site-head.is-stuck .nav-a:hover { color: var(--ink); }
.site-head.is-stuck .btn-glass { border-color: var(--ink); color: var(--ink); background: transparent; }
.site-head.is-stuck .btn-glass:hover { background: var(--ink); color: var(--paper); }

/* a page whose hero is not photographic starts in the stuck skin */
.site-head.is-solid { background: rgba(242, 244, 245, 0.86); }

.nav-a {
    position: relative;
    padding: 0.5rem 0.125rem;
    font-size: 0.875rem;
    font-weight: 600;
    transition: color 0.25s;
}
.nav-a::after {
    content: '';
    position: absolute;
    left: 0; bottom: 0;
    width: 100%; height: 1.5px;
    background: currentColor;
    transform: scaleX(0);
    transform-origin: right;
    transition: transform 0.45s var(--ease-out);
}
.nav-a:hover::after { transform: scaleX(1); transform-origin: left; }
.nav-a.is-active { color: #fff; }
.nav-a.is-active::after { transform: scaleX(1); background: var(--highlight); }
.site-head.is-stuck .nav-a.is-active { color: var(--ink); }
.site-head.is-stuck .nav-a.is-active::after { background: var(--brand); }

/* burger → cross */
.burger-line { transition: transform 0.4s var(--ease-out), opacity 0.25s; transform-origin: center; }
.is-open .burger-line-1 { transform: translateY(5.5px) rotate(45deg); }
.is-open .burger-line-2 { opacity: 0; transform: scaleX(0.2); }
.is-open .burger-line-3 { transform: translateY(-5.5px) rotate(-45deg); }

/* mobile drawer */
.nav-drawer {
    position: fixed;
    inset: 0;
    z-index: 55;
    background: var(--ink);
    display: flex;
    flex-direction: column;
    clip-path: inset(0 0 100% 0);
    transition: clip-path 0.65s var(--ease-out);
    pointer-events: none;
}
.nav-drawer.is-open { clip-path: inset(0 0 0 0); pointer-events: auto; }
.nav-drawer a.drawer-a {
    font-family: 'Fraunces', Georgia, serif;
    font-size: clamp(2rem, 9vw, 3rem);
    line-height: 1.15;
    color: var(--paper);
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.5s var(--ease-out), transform 0.5s var(--ease-out), color 0.25s;
}
.nav-drawer.is-open a.drawer-a { opacity: 1; transform: translateY(0); }
.nav-drawer a.drawer-a:hover { color: var(--highlight); }
/* the page you are already on, marked the same way the desktop nav marks it */
.nav-drawer a.drawer-a.is-active { color: var(--highlight); }
.nav-drawer a.drawer-a.is-active::before {
    content: '';
    display: inline-block;
    width: 0.5rem; height: 0.5rem;
    margin-right: 0.75rem;
    border-radius: 99px;
    background: currentColor;
    vertical-align: middle;
}
/* stagger — one line per item, in source order */
.nav-drawer.is-open a.drawer-a:nth-child(1) { transition-delay: 0.12s; }
.nav-drawer.is-open a.drawer-a:nth-child(2) { transition-delay: 0.17s; }
.nav-drawer.is-open a.drawer-a:nth-child(3) { transition-delay: 0.22s; }
.nav-drawer.is-open a.drawer-a:nth-child(4) { transition-delay: 0.27s; }
.nav-drawer.is-open a.drawer-a:nth-child(5) { transition-delay: 0.32s; }
.nav-drawer.is-open a.drawer-a:nth-child(6) { transition-delay: 0.37s; }

/* ============================================================
   9. SCROLL PROGRESS
   ============================================================ */
.scroll-bar {
    position: fixed;
    top: 0; left: 0;
    z-index: 70;
    height: 2px;
    width: 100%;
    transform: scaleX(0);
    transform-origin: left;
    background: linear-gradient(90deg, var(--brand), var(--highlight));
    pointer-events: none;
}

/* ============================================================
   10. ANIMATION BASE STATES
   ------------------------------------------------------------
   Guarded by .js-anim on <html>, which main.js sets only when GSAP has
   loaded AND the visitor has not asked for reduced motion. Without that
   class every one of these is fully visible — so no-JS, slow-network and
   reduced-motion visitors get a clean, complete page, never a blank one.
   ============================================================ */
.js-anim [data-reveal] { opacity: 0; }
.js-anim [data-reveal="up"] { transform: translateY(34px); }
.js-anim [data-reveal="fade"] { transform: none; }
.js-anim [data-reveal="left"] { transform: translateX(-34px); }
.js-anim [data-reveal="right"] { transform: translateX(34px); }
.js-anim [data-reveal="scale"] { transform: scale(0.94); }
.js-anim [data-reveal-stagger] > * { opacity: 0; transform: translateY(28px); }

/* the hero's own entrance — pre-hidden so the timeline has something to
   reveal, rather than the page showing everything and then jumping */
.js-anim [data-hero-line] { transform: translateY(118%); }
.js-anim [data-hero-item] { opacity: 0; }

/* a headline split into lines by GSAP */
.js-anim [data-split] { opacity: 0; }
/* one clipping box per headline line, so the line can slide up from behind
   its own edge. The child may be a <span> or an <em> — hence the wildcard. */
.split-line { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }
.split-line > * { display: block; will-change: transform; }

/* image that wipes open */
.js-anim [data-wipe] { clip-path: inset(0 0 100% 0); }

/* ============================================================
   11. CHATBOT
   ============================================================ */
.bot-launcher {
    position: fixed;
    right: 1.25rem; bottom: 1.25rem;
    z-index: 80;
}
.bot-panel {
    position: fixed;
    right: 1.25rem; bottom: 1.25rem;
    z-index: 81;
    width: min(23.5rem, calc(100vw - 2.5rem));
    max-height: min(37rem, calc(100vh - 2.5rem));
    display: flex;
    flex-direction: column;
    background: var(--paper);
    border: 1px solid var(--paper-3);
    border-radius: 1.75rem;
    box-shadow: 0 8px 24px rgba(18, 33, 46, 0.12), 0 32px 80px rgba(18, 33, 46, 0.24);
    overflow: hidden;
    opacity: 0;
    transform: translateY(20px) scale(0.96);
    transform-origin: bottom right;
    pointer-events: none;
    transition: opacity 0.35s var(--ease-out), transform 0.45s var(--ease-out);
}
.bot-panel.is-open { opacity: 1; transform: translateY(0) scale(1); pointer-events: auto; }

.bot-log { flex: 1; overflow-y: auto; padding: 1.25rem; display: flex; flex-direction: column; gap: 0.75rem; }
.bot-msg { max-width: 85%; padding: 0.75rem 1rem; font-size: 0.875rem; line-height: 1.55; border-radius: 1.125rem; }
.bot-msg.from-bot { align-self: flex-start; background: #fff; border: 1px solid var(--paper-3); border-bottom-left-radius: 0.375rem; color: var(--ink-80); }
.bot-msg.from-me { align-self: flex-end; background: var(--brand); color: #fff; border-bottom-right-radius: 0.375rem; }
.bot-msg.is-in { animation: botIn 0.4s var(--ease-out) both; }
@keyframes botIn { from { opacity: 0; transform: translateY(8px); } to { opacity: 1; transform: translateY(0); } }

.bot-typing { display: inline-flex; gap: 4px; align-items: center; }
.bot-typing i { width: 6px; height: 6px; border-radius: 99px; background: var(--ink-40); animation: botDot 1.3s infinite ease-in-out; }
.bot-typing i:nth-child(2) { animation-delay: 0.18s; }
.bot-typing i:nth-child(3) { animation-delay: 0.36s; }
@keyframes botDot { 0%, 60%, 100% { opacity: 0.3; transform: translateY(0); } 30% { opacity: 1; transform: translateY(-3px); } }

.bot-opts { display: flex; flex-wrap: wrap; gap: 0.4375rem; padding: 0 1.25rem 1rem; }
.bot-opt {
    padding: 0.5rem 0.875rem;
    border: 1.5px solid var(--line);
    border-radius: 99px;
    background: #fff;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--ink-80);
    cursor: pointer;
    transition: background 0.2s, border-color 0.2s, color 0.2s, transform 0.25s var(--ease-out);
}
.bot-opt:hover { background: var(--brand); border-color: var(--brand); color: #fff; transform: translateY(-1px); }

/* ============================================================
   12. ENQUIRY DRAWER
   ------------------------------------------------------------
   The enquiry form used to sit open in the page, which made the homepage
   open on admin instead of on India. It now lives behind a tab on the right
   edge and slides in when asked for.

   js/enquiry.js intercepts any click heading for #enquire, and that id is on
   the panel — so every "Enquire Now" already on the site opens this without
   a single href changing.
   ============================================================ */

/* ── the tab ─────────────────────────────────────────────── */
.enq-tab {
    position: fixed;
    top: 50%;
    right: 0;
    z-index: 70;
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding: 1.15rem 0.7rem;
    border: 0;
    border-radius: 14px 0 0 14px;
    background: var(--brand);
    color: #fff;
    font-family: inherit;
    font-size: 0.6875rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    cursor: pointer;
    /* the label runs down the edge instead of being rotated by transform,
       which keeps the box itself upright and easy to position */
    writing-mode: vertical-rl;
    box-shadow: -6px 0 22px rgba(18, 33, 46, 0.22);
    transform: translateY(-50%);
    transform-origin: right center;
    transition: background 0.25s, box-shadow 0.4s var(--ease-out),
                transform 0.45s var(--ease-out), opacity 0.3s;
}
.enq-tab svg { width: 1rem; height: 1rem; }
/* grows leftward out of the edge rather than sliding away from it */
.enq-tab:hover { background: var(--brand-deep); transform: translateY(-50%) scaleX(1.08); box-shadow: -10px 0 30px rgba(18, 33, 46, 0.32); }
/* out of the way while the panel it opens is on screen */
.enq-tab.is-away { opacity: 0; pointer-events: none; transform: translateY(-50%) translateX(100%); }

/* ── scrim ───────────────────────────────────────────────── */
.enq-scrim {
    position: fixed;
    inset: 0;
    z-index: 88;
    background: rgba(18, 33, 46, 0.55);
    backdrop-filter: blur(6px);
    -webkit-backdrop-filter: blur(6px);
    opacity: 0;
    visibility: hidden;
    /* visibility flips only after the fade, so the scrim cannot swallow
       clicks on its way out */
    transition: opacity 0.45s ease, visibility 0s linear 0.45s;
}
.enq-scrim.is-open { opacity: 1; visibility: visible; transition: opacity 0.45s ease, visibility 0s; }

/* ── panel ───────────────────────────────────────────────── */
.enq-panel {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    z-index: 89;
    width: min(34rem, 100%);
    display: flex;
    flex-direction: column;
    background: #fff;
    box-shadow: -30px 0 90px rgba(18, 33, 46, 0.35);
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 0.62s var(--ease-out), visibility 0s linear 0.62s;
}
.enq-panel.is-open { transform: none; visibility: visible; transition: transform 0.62s var(--ease-out), visibility 0s; }

.enq-body {
    flex: 1;
    min-height: 0;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 1.75rem 1.5rem 2rem;
}
@media (min-width: 640px) { .enq-body { padding: 2rem; } }

/* ── the arrival ──────────────────────────────────────────
   The panel lands first, then its contents rise in order. Keeping the
   stagger on transition-delay rather than an animation means the whole
   thing reverses cleanly when the panel closes. */
.enq-intro,
.enq-panel .field,
.enq-panel .enq-foot {
    opacity: 0;
    transform: translateY(18px);
    transition: opacity 0.55s var(--ease-out), transform 0.55s var(--ease-out);
}
.enq-panel.is-open .enq-intro,
.enq-panel.is-open .field,
.enq-panel.is-open .enq-foot { opacity: 1; transform: none; }

.enq-panel.is-open .enq-intro { transition-delay: 0.16s; }
.enq-panel.is-open .enq-grid > .field:nth-child(1) { transition-delay: 0.24s; }
.enq-panel.is-open .enq-grid > .field:nth-child(2) { transition-delay: 0.28s; }
.enq-panel.is-open .enq-grid > .field:nth-child(3) { transition-delay: 0.32s; }
.enq-panel.is-open .enq-grid > .field:nth-child(4) { transition-delay: 0.36s; }
.enq-panel.is-open .enq-grid > .field:nth-child(5) { transition-delay: 0.40s; }
.enq-panel.is-open .enq-grid > .field:nth-child(6) { transition-delay: 0.44s; }
.enq-panel.is-open .enq-grid > .field:nth-child(7) { transition-delay: 0.48s; }
.enq-panel.is-open .enq-grid > .field:nth-child(8) { transition-delay: 0.52s; }
.enq-panel.is-open .enq-grid > .field:nth-child(9) { transition-delay: 0.56s; }
.enq-panel.is-open .enq-foot { transition-delay: 0.60s; }

/* ============================================================
   13. SWIPER OVERRIDES
   ============================================================ */
.swiper { overflow: visible; }
.swiper-slide { height: auto; }
.swiper-wrapper { align-items: stretch; }
.sw-bullets { display: flex; gap: 0.4375rem; justify-content: center; }
.sw-bullets .swiper-pagination-bullet {
    width: 7px; height: 7px;
    border-radius: 99px;
    background: var(--line-dk);
    opacity: 1;
    transition: width 0.35s var(--ease-out), background 0.25s;
}
.sw-bullets .swiper-pagination-bullet-active { width: 26px; background: var(--brand); }
.on-dark .sw-bullets .swiper-pagination-bullet { background: rgba(242, 244, 245, 0.3); }
.on-dark .sw-bullets .swiper-pagination-bullet-active { background: var(--highlight); }

/* ============================================================
   14. ORBIT RINGS  (decorative)
   ------------------------------------------------------------
   Three concentric rings pushed off the right edge of a hero so only their
   left arcs show, each carrying a dot that glides along the line. Pure CSS:
   no script, no SVG, no canvas.

   Drop into any position:relative; overflow:hidden container, placed after
   the background layers and before the copy:

       <div class="orbits" aria-hidden="true">
         <span class="orbit orbit-1"><span class="orbit-ring"></span></span>
         <span class="orbit orbit-2"><span class="orbit-ring"></span></span>
         <span class="orbit orbit-3"><span class="orbit-ring"></span></span>
       </div>

   Two notes on how this differs from the obvious approach:

   • The rings are placed from a shared CENTRE (--orbit-cx, how far past the
     right edge that centre sits) rather than from three hand-picked right
     offsets. Offsets alone drift apart as the sizes change and stop being
     concentric; deriving `right` from the centre keeps them true whatever
     sizes you give them.
   • --orbit-cx is a length, not a percentage. A percentage `right` resolves
     against the hero's WIDTH, so at a normal viewport -60% is roughly
     -860px, which throws a 700px ring clean off the screen.
   ============================================================ */
.orbits {
    /* how far beyond the right edge the shared centre of the rings sits —
       raise it to show less arc, lower it to show more */
    --orbit-cx: 12rem;
    --orbit-line: rgba(255, 255, 255, 0.3);
    --orbit-dot-size: 14px;

    position: absolute;
    inset: 0;
    z-index: 1;              /* over the photograph, under the copy */
    overflow: hidden;
    pointer-events: none;
}

.orbit {
    /* per-ring defaults; the modifiers below override them */
    --orbit-size: 700px;
    --orbit-speed: 10s;
    --orbit-dir: normal;
    --orbit-dot: #fff;
    /* Dot position, as a point on the circle. To place one at angle t
       (0deg = 3 o'clock, growing clockwise because CSS y runs down):
           --orbit-dot-x: calc(50% + 50% * cos(t))
           --orbit-dot-y: calc(50% + 50% * sin(t))
       Worked out ahead of time here so the rule needs no trig support.
       Keep the angles near 180deg — that is the arc actually on screen,
       and it is where the dots come to rest under reduced motion. */
    --orbit-dot-x: 1.7%;
    --orbit-dot-y: 62.9%;

    position: absolute;
    top: 50%;
    /* right edge = centre + radius, so all three share one centre */
    right: calc(0px - var(--orbit-cx) - var(--orbit-size) / 2);
    width: var(--orbit-size);
    height: var(--orbit-size);
    /* the wrapper owns the centring transform, which leaves the rotate
       on the child free of it */
    transform: translateY(-50%);
}

.orbit-ring {
    display: block;
    position: relative;
    width: 100%;
    height: 100%;
    border-radius: 50%;
    border: 1px solid var(--orbit-line);
    background: transparent;
    /* the whole circle turns, so the dot rides the line */
    animation: orbit-spin var(--orbit-speed) linear infinite;
    animation-direction: var(--orbit-dir);
    will-change: transform;
}

.orbit-ring::after {
    content: '';
    position: absolute;
    left: var(--orbit-dot-x);
    top: var(--orbit-dot-y);
    width: var(--orbit-dot-size);
    height: var(--orbit-dot-size);
    /* pull back by half the dot so its CENTRE lands on the line */
    margin: calc(var(--orbit-dot-size) / -2) 0 0 calc(var(--orbit-dot-size) / -2);
    border-radius: 50%;
    /* colour once, and the glow follows it */
    color: var(--orbit-dot);
    background: currentColor;
    box-shadow: 0 0 calc(var(--orbit-dot-size) * 1.15) currentColor;
}

/* 165deg — low on the inner arc */
.orbit-1 {
    --orbit-size: 700px;
    --orbit-speed: 10s;
    --orbit-dot: var(--highlight);
    --orbit-dot-x: 1.7%;
    --orbit-dot-y: 62.9%;
}
/* 200deg — high on the middle arc, and turning the other way */
.orbit-2 {
    --orbit-size: 900px;
    --orbit-speed: 14s;
    --orbit-dir: reverse;
    --orbit-dot: var(--brand-soft);
    --orbit-dot-x: 3%;
    --orbit-dot-y: 32.9%;
}
/* 150deg — lowest, on the outer arc */
.orbit-3 {
    --orbit-size: 1100px;
    --orbit-speed: 18s;
    --orbit-dot: #fff;
    --orbit-dot-x: 6.7%;
    --orbit-dot-y: 75%;
}

@keyframes orbit-spin {
    from { transform: rotate(0deg); }
    to   { transform: rotate(360deg); }
}

/* Decoration only, and it needs room to read — below the desktop
   breakpoint the arcs would sit under the copy instead of beside it. */
@media (max-width: 1023.98px) {
    .orbits { display: none; }
}

/* ============================================================
   15. UTILITIES
   ============================================================ */
/* very fine grain — stops big flat colour fields from banding */
.grain::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    opacity: 0.4;
    mix-blend-mode: overlay;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='0.5'/%3E%3C/svg%3E");
}

.no-scrollbar { -ms-overflow-style: none; scrollbar-width: none; }
.no-scrollbar::-webkit-scrollbar { display: none; }

/* a row that scrolls sideways and snaps, used on small screens */
.snap-x { scroll-snap-type: x mandatory; }
.snap-x > * { scroll-snap-align: start; }

/* fade the bottom of a long block instead of cutting it */
.mask-b { -webkit-mask-image: linear-gradient(to bottom, #000 72%, transparent 100%); mask-image: linear-gradient(to bottom, #000 72%, transparent 100%); }

/* hairline divider in the site's warm neutral */
.rule { height: 1px; background: linear-gradient(90deg, transparent, var(--line), transparent); border: 0; }

/* marquee track — duplicate the content once inside for a seamless loop */
.marquee { display: flex; width: max-content; }

/* keeps a 16:9 hero video covering its box on every ratio */
.video-cover { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }

/* The hero film fades in over the still once it is actually playing, so a
   slow start, a refused autoplay or a skipped download all just leave the
   photograph showing — never a black rectangle. main.js adds .is-on. */
[data-hero-video] { opacity: 0; transition: opacity 1.4s ease; }
[data-hero-video].is-on { opacity: 1; }

/* Just enough to keep the letterforms off the picture.
   A wide blur here is a trap: the haloes around neighbouring letters merge
   and a smudged rectangle appears behind the whole paragraph. Keep the
   radius under the letter spacing and it reads as crisp edges, not shadow. */
[data-hero-inner] {
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.45);
}
/* solid fills need no help, and the shadow only muddies them */
[data-hero-inner] .btn,
[data-hero-inner] .glass-dark { text-shadow: none; }

/* the ticker along the bottom edge of the hero — masked at both ends so the
   names appear out of nothing instead of being cut off by the viewport */
.ticker-mask {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 6rem, #000 calc(100% - 6rem), transparent);
    mask-image: linear-gradient(90deg, transparent, #000 6rem, #000 calc(100% - 6rem), transparent);
}

/* skip link */
.skip {
    position: absolute;
    left: 1rem; top: -4rem;
    z-index: 100;
    padding: 0.75rem 1.25rem;
    border-radius: 99px;
    background: var(--ink);
    color: var(--paper);
    font-size: 0.875rem;
    font-weight: 600;
    transition: top 0.3s var(--ease-out);
}
.skip:focus { top: 1rem; }

/* ============================================================
   16. SEARCH BAR
   ------------------------------------------------------------
   One pill: four segments and a button. Below lg it stacks into a card,
   because five controls across a phone is unreadable at any size.

   Submitting hands the choices to travel-plans.html as query params and
   keeps the soft ones (month, party size) for the enquiry — see initSearch
   in js/main.js.
   ============================================================ */

/* the pale ring the pill floats in */
.srch-shell {
    padding: 0.5rem;
    border-radius: 2.25rem;
    background: var(--brand-soft);
}
/* on a dark band the pale ring would read as a halo, so it turns to glass */
.on-dark .srch-shell { background: rgba(255, 255, 255, 0.1); }

/* a pool of brand light under the bar, so the band is not flat behind it */
.srch-glow {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: radial-gradient(62% 130% at 50% 42%, rgba(44, 107, 126, 0.55), transparent 68%);
}

.srch {
    display: grid;
    padding: 0.5rem;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 1.75rem;
    box-shadow: 0 6px 16px rgba(18, 33, 46, 0.06), 0 24px 56px rgba(18, 33, 46, 0.1);
}

@media (min-width: 1024px) {
    .srch-shell { border-radius: 999px; }
    .srch {
        grid-template-columns: repeat(4, minmax(0, 1fr)) auto;
        align-items: center;
        border-radius: 999px;
        padding: 0.5rem 0.5rem 0.5rem 0.75rem;
    }
}

.srch-seg {
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    padding: 0.9375rem 1.25rem;
    min-width: 0;                 /* lets a long destination name ellipsis */
}

/* The focus tint. It lives on a pseudo-element inset from the segment so it
   can have soft corners without bending the divider drawn on the segment's
   own left border. */
.srch-seg::before {
    content: '';
    position: absolute;
    inset: 0.25rem;
    border-radius: 1.25rem;
    background: transparent;
    pointer-events: none;
    transition: background 0.2s;
}
.srch-seg:focus-within::before { background: var(--brand-soft); }
.srch-lab, .srch-in, .srch-step { position: relative; z-index: 1; }
.srch-seg + .srch-seg { border-top: 1px solid var(--line); }
@media (min-width: 1024px) {
    .srch-seg + .srch-seg { border-top: 0; border-left: 1px solid var(--line); }
}

.srch-lab {
    display: flex;
    align-items: center;
    gap: 0.45rem;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-40);
}
.srch-lab svg { width: 0.9rem; height: 0.9rem; flex: none; color: var(--brand); }

.srch-in {
    appearance: none;
    -webkit-appearance: none;
    width: 100%;
    padding: 0 1.4rem 0 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 700;
    color: var(--brand-deep);
    line-height: 1.3;
    cursor: pointer;
    outline: none;
    text-overflow: ellipsis;
    /* the chevron sits beside the value, as in the reference */
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='%232C6B7E' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: right center;
}
/* No ring on the control itself. It is borderless inside its segment, so a
   box around it reads as an error state — and Chrome applies :focus-visible
   to a <select> even when it was opened with the mouse, so the ring appeared
   on every click. The segment tint above replaces it: still a clearly visible
   focus indicator, which keyboard users are entitled to, without the box. */
.srch-in:focus,
.srch-in:focus-visible { outline: none; }

/* Give the native dropdown list some air. Browsers vary in how much of this
   they honour — the popup is drawn by the OS — but where it lands it stops
   the options sitting on top of each other. */
.srch-in option,
.select option {
    padding: 0.5rem 0.875rem;
    background: #fff;
    color: var(--ink);
    font-weight: 600;
    line-height: 2;
}

/* ── traveller stepper: value left, controls right ── */
.srch-step { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; }
.srch-step input {
    width: 2.75rem;
    padding: 0;
    border: 0;
    background: transparent;
    font-family: inherit;
    font-size: 1rem;
    font-weight: 700;
    color: var(--brand-deep);
    -moz-appearance: textfield;
    appearance: textfield;
}
.srch-step input::-webkit-outer-spin-button,
.srch-step input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }
/* same reasoning as the selects — the segment tint is the indicator here */
.srch-step input:focus,
.srch-step input:focus-visible { outline: none; }

.srch-pm { display: flex; gap: 0.3rem; }
.srch-pm button {
    display: grid;
    place-items: center;
    width: 1.875rem;
    height: 1.875rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: #fff;
    color: var(--ink-60);
    cursor: pointer;
    transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.srch-pm button svg { width: 0.875rem; height: 0.875rem; }
.srch-pm button:hover { background: var(--brand); border-color: var(--brand); color: #fff; }

/* ── the button ── */
.srch-go {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.6rem;
    font-family: inherit;
    font-size: 0.9375rem;
    font-weight: 600;
    width: 100%;
    height: 3.25rem;
    margin-top: 0.5rem;
    border: 0;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    cursor: pointer;
    box-shadow: 0 10px 24px rgba(44, 107, 126, 0.3);
    transition: background 0.25s, transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out);
}
.srch-go svg { width: 1.25rem; height: 1.25rem; }
.srch-go:hover { background: var(--brand-deep); transform: translateY(-2px); box-shadow: 0 16px 32px rgba(44, 107, 126, 0.36); }
.srch-go:active { transform: translateY(0); }

@media (min-width: 1024px) {
    .srch-go { width: 4rem; height: 4rem; margin-top: 0; margin-left: 0.5rem; }
}

/* ============================================================
   17. TRAVEL BACKDROP  (decorative)
   ------------------------------------------------------------
   Map paper that drifts, with a few paper planes crossing it. Goes behind
   a section's content; the section needs position:relative and
   overflow:hidden, and its content a stacking context above this.

       <section class="relative overflow-hidden …">
         <div class="tbg" aria-hidden="true">
           <span class="tbg-plane tbg-plane-1">…plane svg…</span>
           …
         </div>
         <div class="relative z-10"> …the actual content… </div>
       </section>

   Everything here is deliberately faint. It sits under headings, and the
   contrast of the copy has to survive it — ink on paper is 15.8:1 and must
   stay that way to the eye.
   ============================================================ */
.tbg {
    position: absolute;
    inset: 0;
    z-index: 0;
    overflow: hidden;
    pointer-events: none;
    /* clear at the very top, where the section's headline sits */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 100%);
    mask-image: linear-gradient(to bottom, transparent 0%, #000 22%, #000 100%);
}

/* the map grid. Oversized and moved by transform rather than
   background-position, which keeps it on the compositor. The distance is a
   whole number of tiles, so the loop has no visible seam. */
.tbg::before {
    content: '';
    position: absolute;
    inset: -20%;
    background-image: radial-gradient(circle, rgba(44, 107, 126, 0.16) 1px, transparent 1.5px);
    background-size: 28px 28px;
    animation: tbg-drift 90s linear infinite;
}
@keyframes tbg-drift {
    from { transform: translate3d(0, 0, 0); }
    to   { transform: translate3d(-280px, 140px, 0); }
}

.tbg-plane {
    position: absolute;
    color: var(--brand);
    opacity: 0;
    animation-name: tbg-fly;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    will-change: transform, opacity;
}
.tbg-plane svg { display: block; width: 100%; height: auto; }

@keyframes tbg-fly {
    0%   { opacity: 0;    transform: translate3d(0, 0, 0) rotate(-7deg); }
    14%  { opacity: 0.14; }
    86%  { opacity: 0.14; }
    100% { opacity: 0;    transform: translate3d(78vw, -16vh, 0) rotate(-7deg); }
}

/* negative delays start them mid-flight, so the section is never empty */
.tbg-plane-1 { top: 34%; left: -6%; width: 3rem;    animation-duration: 46s; animation-delay: -6s; }
.tbg-plane-2 { top: 62%; left: -4%; width: 2.1rem;  animation-duration: 62s; animation-delay: -28s; }
.tbg-plane-3 { top: 86%; left: -8%; width: 2.6rem;  animation-duration: 74s; animation-delay: -50s; }

/* ── on a dark band ──
   Same texture inverted: light marks on ink instead of teal on paper. */
.tbg-dark::before { background-image: radial-gradient(circle, rgba(255, 255, 255, 0.14) 1px, transparent 1.5px); }
.tbg-dark .tbg-plane { color: #fff; }

/* the top mask exists to keep a section's headline clear; a band with no
   headline wants the texture edge to edge */
.tbg-full { -webkit-mask-image: none; mask-image: none; }

/* ============================================================
   18. DESTINATION RAIL + CARDS
   ------------------------------------------------------------
   A photograph standing behind the section, deep along the bottom and
   washed out to the page ground as it rises, with the destination cards
   riding a rail across it.

   From 1024px up the section pins and the rail moves right to left as you
   scroll, each card rising in as it arrives (see hscroll in
   js/animations.js). Below that it is an ordinary side-scrolling row —
   pinning the viewport on a phone hijacks the one gesture people have.
   ============================================================ */

/* ── the sky ── */
.dest-sky {
    position: absolute;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
}
.dest-sky img {
    position: absolute;
    left: 0; right: 0; bottom: 0;
    width: 100%;
    height: 82%;
    object-fit: cover;
    object-position: 50% 45%;
}
/* transparent at the foot so the photograph reads at full depth, solid page
   ground by the top so the heading sits on plain paper */
.dest-sky::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(to top,
        rgba(242, 244, 245, 0.05) 0%,
        rgba(242, 244, 245, 0.45) 30%,
        rgba(242, 244, 245, 0.88) 58%,
        var(--paper) 84%);
}

/* ── the rail ── */
.dest-scroller { overflow-x: auto; overflow-y: hidden; }
.dest-rail {
    display: flex;
    gap: 1.5rem;
    width: max-content;
    padding: 1.5rem max(1.25rem, calc((100vw - var(--shell)) / 2 + 1.25rem));
}
/* The pinned, one-screen treatment asks for 640px of height to look right.
   A shorter window (a laptop with the dev tools open, a small netbook) gets
   the plain scrolling row instead — the same gate guards hscroll() in
   js/animations.js, so the CSS and the pin always agree. */
@media (min-width: 1024px) and (min-height: 640px) {
    /* One screen, and the rail takes whatever the heading leaves it — the card
       is sized by the space available rather than by its own copy, which is
       the only way a pinned section fits a laptop and a desktop alike.
       The id is in the selector on purpose: Tailwind's py-20 is injected after
       this file and would otherwise win the padding. */
    #destinations .dest-inner {
        display: flex;
        flex-direction: column;
        height: 100svh;
        padding: 6rem 0 2.5rem;   /* 5rem of the top is the fixed header */
    }
    /* the pin drives it, so the row must not clip or scroll on its own */
    .dest-scroller {
        flex: 1 1 auto;
        min-height: 0;
        display: flex;
        align-items: center;
        overflow: visible;
    }
    .dest-rail {
        height: 100%;
        /* never the whole height available — the gap left above and below is
           what makes the section feel like it has padding */
        max-height: min(32rem, 90%);
        align-items: stretch;
        padding: 0 max(2rem, calc((100vw - var(--shell)) / 2 + 2rem));
    }
}

/* ── the card ── */
.dcard {
    flex: none;
    display: flex;
    flex-direction: column;
    width: 21.5rem;
    padding: 0.75rem;
    background: #fff;
    border-radius: 2rem;
    box-shadow: 0 8px 20px rgba(18, 33, 46, 0.07), 0 30px 60px rgba(18, 33, 46, 0.12);
}

.dcard-shot {
    margin: 0;
    overflow: hidden;
    border-radius: 1.5rem;
    aspect-ratio: 16 / 10;
}
.dcard-shot img {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    transition: transform 1s var(--ease-out);
}
.dcard:hover .dcard-shot img { transform: scale(1.06); }

.dcard-body {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 1rem 0.75rem 0.5rem;
}

.dcard-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 1rem; }
.dcard-state {
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--ink-40);
}
.dcard-name {
    margin-top: 0.3rem;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 500;
    font-size: 1.625rem;
    line-height: 1.05;
    letter-spacing: -0.02em;
    color: var(--brand);
}
.dcard-days { flex: none; text-align: right; }
.dcard-days b {
    display: block;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 600;
    font-size: 1.75rem;
    line-height: 1;
    color: var(--ink);
}
.dcard-days span { display: block; margin-top: 0.3rem; font-size: 0.6875rem; color: var(--ink-40); }

.dcard-desc {
    margin-top: 0.75rem;
    font-size: 0.8125rem;
    line-height: 1.6;
    color: var(--ink-60);
    /* three lines on every card, so the buttons line up across the rail */
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

/* Tags, not a list of ticks: the same facts read faster as labels, and they
   take a third of the height, which the photograph gets instead. */
.dtags {
    margin-top: 0.875rem;
    display: flex;
    flex-wrap: wrap;
    gap: 0.375rem;
}
.dtag {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.3125rem 0.6875rem;
    border: 1px solid var(--line);
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.35;
    color: var(--ink-80);
    white-space: nowrap;
}
/* the two that answer "when" and "how many" carry the brand tint */
.dtag-key { border-color: transparent; background: var(--brand-soft); color: var(--brand-deep); }
.dtag svg { width: 0.875rem; height: 0.875rem; flex: none; }

.dcard-go {
    align-self: center;
    margin-top: auto;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    padding: 0.8125rem 1.875rem;
    border-radius: 999px;
    background: var(--brand);
    color: #fff;
    font-size: 0.875rem;
    font-weight: 600;
    box-shadow: 0 8px 20px rgba(44, 107, 126, 0.28);
    transition: background 0.25s, transform 0.35s var(--ease-out), box-shadow 0.35s var(--ease-out);
}
.dcard-go svg { width: 1em; height: 1em; transition: transform 0.35s var(--ease-out); }
.dcard-go:hover { background: var(--brand-deep); transform: translateY(-2px); box-shadow: 0 14px 28px rgba(44, 107, 126, 0.34); }
.dcard-go:hover svg { transform: translateX(3px); }
/* the tags need clearance from the button however short a card's copy is */
.dtags { margin-bottom: 1.25rem; }

@media (max-width: 420px) {
    .dcard { width: 17.5rem; }
}

/* The pinned card: three across with the fourth breaking the edge, and a
   height taken from the screen rather than from its own copy. These have to
   sit AFTER the card's own rules — same specificity, so source order decides,
   and an earlier block would quietly lose the width. */
@media (min-width: 1024px) and (min-height: 640px) {
    .dcard {
        width: clamp(18rem, calc((100vw - 9rem) / 3.3), 25rem);
        height: 100%;
        overflow: hidden;
    }
    /* the photograph absorbs the slack, so short screens crop it rather than
       pushing the button off the bottom */
    .dcard-shot { aspect-ratio: auto; flex: 1 1 auto; min-height: 6rem; }
}

/* A pinned section has exactly one screen to work with, so on a short laptop
   the copy gives ground in order — first the spacing, then the description —
   and the photograph keeps its share. */
@media (min-width: 1024px) and (min-height: 640px) and (max-height: 940px) {
    #destinations .dest-inner { padding: 5rem 0 2rem; }
    /* the heading gives up its share first — every pixel it saves goes to the
       photograph, which is what the card is really for */
    #destinations .dest-inner h2 { font-size: 2.5rem; }
    #destinations .dest-inner .lede { font-size: 0.9375rem; }
    .dcard-name { font-size: 1.5rem; }
    .dcard-days b { font-size: 1.5rem; }
    .dcard-desc { margin-top: 0.625rem; }
    .dtags { margin-top: 0.75rem; margin-bottom: 1rem; }
    .dcard-go { padding: 0.6875rem 1.5rem; }
}
@media (min-width: 1024px) and (min-height: 640px) and (max-height: 780px) {
    /* the last thing to go: a card is its photograph, its name and its tags */
    .dcard-desc { display: none; }
}
/* a 1366 x 768 laptop, which is most laptops — the heading goes down to the
   size it can afford so the rail still gets a photograph worth looking at */
@media (min-width: 1024px) and (min-height: 640px) and (max-height: 720px) {
    #destinations .dest-inner { padding: 4.5rem 0 1.5rem; }
    #destinations .dest-inner h2 { font-size: 2.125rem; }
    #destinations .dest-scroller { margin-top: 1.5rem; }
    .dcard-name { font-size: 1.375rem; }
    .dcard-days b { font-size: 1.375rem; }
}

/* ============================================================
   18b. TRAVEL PLANS — the region behind the section
   ------------------------------------------------------------
   Whichever tab is chosen, that region's photograph stands behind the
   whole band. Two stacked layers crossfade so the change reads as a
   dissolve rather than a flicker (paintBg in js/main.js).

   The wash is the load-bearing part: solid paper down the left and
   across the lower half, where the heading and the cards are, thinning
   towards the top right so the photograph is unmistakably there.
   ============================================================ */
.plans-band { background: var(--paper-2); }

.plans-bg { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.plans-bg img {
    position: absolute;
    inset: 0;
    width: 100%; height: 100%;
    object-fit: cover;
    opacity: 0;
    transform: scale(1.06);
    transition: opacity 0.9s ease, transform 6s ease-out;
}
.plans-bg img.is-on { opacity: 1; transform: scale(1); }
.plans-bg::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
        linear-gradient(to right, var(--paper-2) 0%, rgba(232, 236, 238, 0.82) 26%, rgba(232, 236, 238, 0.12) 80%),
        linear-gradient(to bottom, rgba(232, 236, 238, 0.22) 0%, rgba(232, 236, 238, 0.7) 46%, var(--paper-2) 76%);
}

/* ── the tab bar ── */
.plan-tabs {
    display: flex;
    gap: 0.25rem;
    width: max-content;
    max-width: 100%;
    padding: 0.375rem;
    border-radius: 999px;
    overflow-x: auto;
    background: rgba(255, 255, 255, 0.72);
    backdrop-filter: blur(14px) saturate(1.3);
    -webkit-backdrop-filter: blur(14px) saturate(1.3);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.8), 0 10px 30px rgba(18, 33, 46, 0.1);
}
.plan-tab {
    flex: none;
    padding: 0.625rem 1.125rem;
    border-radius: 999px;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--ink-60);
    white-space: nowrap;
    transition: color 0.25s, background-color 0.25s, box-shadow 0.25s;
}
.plan-tab:hover { color: var(--ink); background: rgba(18, 33, 46, 0.05); }
.plan-tab.is-on {
    background: var(--brand);
    color: #fff;
    box-shadow: 0 6px 16px rgba(44, 107, 126, 0.32);
}
.plan-tab.is-on:hover { background: var(--brand-deep); color: #fff; }

/* ============================================================
   19. HOW IT WORKS (STEPS)
   ------------------------------------------------------------
   A warm band after the destinations: a photograph with the reply
   promise on its corner, and three numbered cards beside it. The
   middle card steps in, which is what stops the three reading as a
   table. Animated by steps() in js/animations.js.
   ============================================================ */
.steps-band { background: linear-gradient(180deg, var(--paper) 0%, #FBF4E6 55%, var(--paper) 100%); }

/* the warm light behind the photograph */
.steps-glow {
    position: absolute;
    top: 12%; left: -10%;
    width: 46rem; height: 46rem;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(234, 144, 16, 0.16) 0%, rgba(234, 144, 16, 0) 68%);
    pointer-events: none;
}

/* ── the headline, held to one line ──
   Tied to the viewport rather than to the type scale: the line has to fit
   the eight columns it is given at every width, and a clamp on its own
   cannot know how long the sentence is. */
@media (min-width: 1024px) {
    .steps-head h2 { white-space: nowrap; font-size: min(4.1vw, 3.6rem); }
}

/* ── the photograph and its promise ── */
/* The column is wider than the photograph, so the badge and the floating
   marks are hung on a box the size of the photograph itself — otherwise
   they drift out into the gap between the columns. */
.steps-art {
    position: relative;
    width: 100%;
    max-width: 24rem;
}
.steps-shot {
    margin: 0;
    overflow: hidden;
    border-radius: 1.75rem;
    aspect-ratio: 4 / 5;
    box-shadow: 0 20px 50px rgba(18, 33, 46, 0.14);
}
.steps-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }

.steps-promise {
    position: absolute;
    left: 1.5rem; bottom: -1.75rem;
    width: 14.5rem;
    padding: 1.125rem 1.25rem 1.25rem;
    border-radius: 1.25rem;
    background: var(--highlight);
    /* white on this amber is 2.47:1 — ink, always */
    color: var(--ink);
    box-shadow: 0 16px 34px rgba(234, 144, 16, 0.35);
}
.steps-promise-top { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.steps-promise-big {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.125rem;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 700;
    font-size: 3.5rem;
    line-height: 1;
}
.steps-promise-big span {
    font-size: 0.6875rem;
    font-weight: 800;
    line-height: 1.15;
    letter-spacing: 0.1em;
    font-family: system-ui, sans-serif;
}
.steps-promise-note { margin-top: 0.375rem; font-size: 0.75rem; line-height: 1.4; opacity: 0.75; }

/* ── the two drifting marks beside the photograph ── */
.steps-float {
    position: absolute;
    display: grid;
    place-items: center;
    width: 3.25rem; height: 3.25rem;
    border-radius: 50%;
    background: #fff;
    color: var(--brand);
    box-shadow: 0 10px 26px rgba(18, 33, 46, 0.14);
}
.steps-float svg { width: 1.375rem; height: 1.375rem; }
.steps-float-1 { top: -1.25rem; right: -1.25rem; }
.steps-float-2 { top: 38%; left: -1.5rem; color: var(--highlight-deep); }

/* ── the three steps ── */
.steps-list { display: flex; flex-direction: column; gap: 1.25rem; }
.step {
    position: relative;
    display: flex;
    align-items: center;
    gap: 1.25rem;
    padding: 1.25rem 1.5rem;
    border-radius: 1.25rem;
    background: #fff;
    box-shadow: 0 6px 18px rgba(18, 33, 46, 0.06), 0 22px 44px rgba(18, 33, 46, 0.08);
}
.step-no {
    flex: none;
    display: grid;
    place-items: center;
    width: 4.25rem; height: 4.25rem;
    border-radius: 1rem;
    background: var(--brand);
    color: #fff;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 700;
    font-size: 1.875rem;
    line-height: 1;
}
.step-body { flex: 1 1 auto; min-width: 0; }
.step-title { font-size: 1.125rem; font-weight: 700; color: var(--brand-deep); }
.step-copy { margin-top: 0.25rem; font-size: 0.875rem; line-height: 1.55; color: var(--ink-60); }
.step-ico {
    flex: none;
    display: grid;
    place-items: center;
    width: 3.75rem; height: 3.75rem;
    border: 2px solid var(--highlight);
    border-radius: 50%;
    color: var(--highlight-deep);
}
.step-ico svg { width: 1.5rem; height: 1.5rem; }

@media (max-width: 1023px) {
    /* pure decoration, and on a narrow screen it collides with the enquiry tab */
    .steps-float { display: none; }
    .steps-art { margin-inline: auto; }
}
@media (max-width: 640px) {
    .step { gap: 1rem; padding: 1rem 1.125rem; }
    .step-no { width: 3.5rem; height: 3.5rem; font-size: 1.5rem; }
    /* the circle is decoration — on a phone the words need the width */
    .step-ico { display: none; }
    .steps-promise { left: 1rem; width: 12.5rem; }
    .steps-promise-big { font-size: 3rem; }
}
@media (min-width: 1024px) {
    /* the indent is what stops the three reading as a table */
    .step:nth-child(2) { margin-left: 3rem; }
    .step:nth-child(3) { margin-left: 1.5rem; }
}

/* ============================================================
   20. APP SHOWCASE (PHONE MOCKUPS)
   ------------------------------------------------------------
   This site exists to sell the app, so a real screen of it appears in
   the hero and again in its own section. The handset is CSS — one
   element, a dark shell around a screenshot — which keeps the images
   to the screens themselves and lets the frame resize with the layout.

   Every screenshot in images/app/ is a capture of the real screens in
   the App design folder, 393 x 852 at 1.5x. Re-capture them from there
   if the app changes; nothing here is a drawing of an app.
   ============================================================ */
.phone {
    --phone-w: 16.5rem;
    position: relative;
    flex: none;
    width: var(--phone-w);
    aspect-ratio: 393 / 852;
    padding: 0.4375rem;
    border-radius: 2.5rem;
    background: linear-gradient(160deg, #3A4A55 0%, #12212E 34%, #0B141C 100%);
    box-shadow:
        0 0 0 1px rgba(255, 255, 255, 0.12) inset,
        0 2px 4px rgba(255, 255, 255, 0.18) inset,
        0 30px 60px rgba(11, 20, 28, 0.45),
        0 10px 24px rgba(11, 20, 28, 0.3);
}
.phone-screen {
    position: relative;
    width: 100%; height: 100%;
    border-radius: 2.125rem;
    overflow: hidden;
    background: #fff;
}
.phone-screen > img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: top center; }

/* The feed scrolling inside the handset.
   The still underneath supplies the status bar (50/852 of the screen) and
   the tab bar (77/852), both of which stay put on a real phone. This window
   is the gap between them, and it holds a capture of the whole feed —
   1412px of it — which appShowcase() walks up and down. */
.phone-roll {
    position: absolute;
    left: 0; right: 0;
    top: 5.87%;
    bottom: 9.04%;
    overflow: hidden;
    z-index: 1;
}
.phone-roll img { display: block; width: 100%; height: auto; will-change: transform; }

/* the island, and the sheen that stops the glass reading as flat paint */
.phone::before {
    content: '';
    position: absolute;
    top: 1.0625rem; left: 50%;
    transform: translateX(-50%);
    width: 30%; height: 1.375%;
    min-height: 0.6875rem;
    border-radius: 999px;
    background: #05090D;
    z-index: 2;
}
.phone::after {
    content: '';
    position: absolute;
    inset: 0.4375rem;
    border-radius: 2.125rem;
    pointer-events: none;
    z-index: 3;
    background: linear-gradient(118deg, rgba(255, 255, 255, 0.22) 0%, rgba(255, 255, 255, 0.05) 18%, transparent 38%);
}

/* the side keys — small, but their absence is what makes a mockup look drawn */
.phone-keys { position: absolute; inset: 0; pointer-events: none; }
.phone-keys i {
    position: absolute;
    left: -0.125rem;
    width: 0.1875rem;
    border-radius: 999px;
    background: linear-gradient(180deg, #46555F, #1A2A35);
}
.phone-keys i:nth-child(1) { top: 18%; height: 4%; }
.phone-keys i:nth-child(2) { top: 25%; height: 7%; }
.phone-keys i:nth-child(3) { top: 34%; height: 7%; }
.phone-keys i:nth-child(4) { left: auto; right: -0.125rem; top: 27%; height: 11%; }

/* ── the cluster: three handsets, the middle one forward ── */
.phone-cluster {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 1.25rem;
}
/* Sized as a share of the column, not in rem: three handsets plus their gaps
   have to fit whatever width the grid hands them, at every breakpoint. */
.phone-cluster .phone-lead { --phone-w: 15rem; z-index: 2; }
.phone-cluster .phone-side { display: none; opacity: 0.94; }
@media (min-width: 768px) {
    .phone-cluster .phone { --phone-w: 27%; }
    .phone-cluster .phone-lead { --phone-w: 33%; }
    .phone-cluster .phone-side { display: block; }
    .phone-cluster .phone-side:first-child { transform: rotate(-4deg) translateY(1.25rem); }
    .phone-cluster .phone-side:last-child { transform: rotate(4deg) translateY(1.25rem); }
}

/* ── the hero pair ── */
/* Height-led, not width-led: the hero is one screen, so the handsets take
   what the screen can spare and their width follows from the aspect ratio.
   0.4613 is 393/852 — the phone's own proportion. */
.phone-duo {
    /* Three ceilings, whichever bites first: a plain maximum, the height the
       screen can spare once the header, the padding and the lifted back
       handset have taken theirs, and the width of the column the pair sits
       in — the two together run about 1.77x one handset. */
    --duo: min(20rem, calc((100svh - 15rem) * 0.4613), calc(24vw - 1rem));
    display: flex;
    align-items: center;
    justify-content: center;
}
.phone-duo .phone-front { --phone-w: var(--duo); z-index: 2; }
.phone-duo .phone-back {
    --phone-w: calc(var(--duo) * 0.88);
    /* behind and lifted, but standing far enough clear to read as two
       handsets rather than one leaning on the other */
    margin-right: -12%;
    transform: rotate(-7deg) translateY(-2.25rem);
    opacity: 0.96;
}

/* ── the two codes in the hero ── */
.qr-mini { flex: none; width: 8.25rem; }
.qr-mini img {
    display: block;
    width: 100%; height: auto;
    padding: 0.4375rem;
    border-radius: 0.875rem;
    background: var(--paper);
}
.qr-mini figcaption {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.25rem;
    margin-top: 0.5625rem;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: rgba(242, 244, 245, 0.72);
}
.qr-mini figcaption svg, .qr-mini figcaption img { width: 1rem; height: 1rem; }

/* A laptop screen is short, and the hero now carries two codes as well as
   the headline. Everything gives a little rather than the first line
   sliding up under the header. */
@media (min-width: 1024px) and (max-height: 760px) {
    [data-hero-inner] { padding-top: 5.5rem; padding-bottom: 3rem; }
    /* still the display face at full voice, only pulled in far enough that
       the two lines and the codes both fit a short laptop */
    [data-hero-inner] h1 { font-size: clamp(3rem, 5.2vw, 5rem); }
    [data-hero-inner] .lede { font-size: 0.9375rem; }
    .qr-mini { width: 6.5rem; }
}

/* ── feature list beside the cluster ── */
.appfeat { display: flex; gap: 1rem; }
.appfeat + .appfeat { margin-top: 1.5rem; }
.appfeat-ico {
    flex: none;
    display: grid;
    place-items: center;
    width: 2.75rem; height: 2.75rem;
    border-radius: 0.875rem;
    background: rgba(255, 255, 255, 0.08);
    border: 1px solid rgba(255, 255, 255, 0.12);
    color: var(--highlight-lt);
}
.appfeat-ico svg { width: 1.25rem; height: 1.25rem; }
.appfeat h3 { font-size: 1rem; font-weight: 700; color: var(--paper); }
.appfeat p { margin-top: 0.25rem; font-size: 0.875rem; line-height: 1.55; color: rgba(242, 244, 245, 0.62); }

/* ── the two app bands ──
   The scroll bar at the top of every page runs brand → highlight. These two
   sections are the same idea at full size: teal at one corner, amber at the
   other, dark enough throughout that white type keeps its contrast. The
   hairline along the top is literally the progress bar's gradient. */
.app-band {
    position: relative;
    background:
        radial-gradient(58rem 34rem at 82% 4%, rgba(234, 144, 16, 0.42) 0%, rgba(234, 144, 16, 0) 60%),
        radial-gradient(46rem 28rem at 8% 96%, rgba(234, 144, 16, 0.2) 0%, rgba(234, 144, 16, 0) 58%),
        radial-gradient(52rem 30rem at -8% 10%, rgba(44, 107, 126, 0.5) 0%, rgba(44, 107, 126, 0) 58%),
        linear-gradient(118deg, #0D1A24 0%, #12212E 34%, #241F1C 64%, #3A2608 100%);
}
.app-band::before {
    content: '';
    position: absolute;
    inset: 0 0 auto 0;
    height: 3px;
    background: linear-gradient(90deg, var(--brand), var(--highlight));
    z-index: 4;
}
/* the card version, for the download block */
.app-band-card {
    box-shadow: 0 30px 70px rgba(11, 20, 28, 0.45), 0 0 0 1px rgba(234, 144, 16, 0.14);
}
.app-band-card::before { border-radius: 2rem 2rem 0 0; }

/* an amber cast under whatever sits on these bands */
.glow-amber { box-shadow: 0 30px 60px rgba(11, 20, 28, 0.5), 0 14px 40px rgba(234, 144, 16, 0.26); }

/* ── store buttons and QR tiles ── */
.store-btn {
    display: inline-flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.6875rem 1.125rem;
    border-radius: 0.875rem;
    background: var(--paper);
    color: #000;
    text-align: left;
    transition: transform 0.3s var(--ease-out), box-shadow 0.3s var(--ease-out);
}
.store-btn:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(0, 0, 0, 0.28); }
.store-btn svg, .store-btn img { width: 1.5rem; height: 1.5rem; flex: none; }
.store-btn b { display: block; font-size: 0.875rem; font-weight: 700; line-height: 1.15; }
/* both lines at full strength — black on the light button, white on the
   dark one — with only size and weight carrying the hierarchy */
.store-btn span { display: block; font-size: 0.625rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.store-btn-dark { background: rgba(255, 255, 255, 0.08); border: 1px solid rgba(255, 255, 255, 0.16); color: #fff; }

.qr-tile { background: var(--paper); border-radius: 1.25rem; padding: 0.875rem; text-align: center; }
.qr-tile img { display: block; width: 100%; height: auto; border-radius: 0.5rem; }
.qr-tile figcaption {
    margin-top: 0.625rem;
    font-size: 0.625rem;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--ink-60);
}

/* ============================================================
   21. WHY US (DRIFTING COLUMNS)
   ------------------------------------------------------------
   A photograph on one side and the reasons on the other, in two
   columns that pass each other — the first rising, the second
   falling, both without end.

   The loop: each column holds its cards twice and travels exactly
   -50% of the run, so the duplicate lands where the original
   started. That only stays seamless if every card carries its own
   bottom margin — a flex `gap` leaves one fewer gap than cards and
   the run would drift by half a gap on every pass.
   ============================================================ */
.why-band {
    background:
        radial-gradient(40rem 26rem at 88% 8%, rgba(44, 107, 126, 0.08) 0%, rgba(44, 107, 126, 0) 60%),
        var(--paper-2);
}

/* ── the photograph ── */
.why-shot {
    position: relative;
    margin: 0;
    max-width: 26rem;
    border-radius: 1.75rem;
    overflow: hidden;
    aspect-ratio: 5 / 4;
    box-shadow: 0 24px 60px rgba(18, 33, 46, 0.18);
}
.why-shot img { display: block; width: 100%; height: 100%; object-fit: cover; }
.why-shot figcaption {
    position: absolute;
    left: 1rem; right: 1rem; bottom: 1rem;
    padding: 0.875rem 1.125rem;
    border-radius: 1rem;
    background: rgba(18, 33, 46, 0.62);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    color: var(--paper);
}
.why-shot figcaption b {
    display: block;
    font-family: 'Fraunces', Georgia, serif;
    font-weight: 600;
    font-size: 1.125rem;
    line-height: 1.1;
}
.why-shot figcaption span {
    display: block;
    margin-top: 0.1875rem;
    font-size: 0.75rem;
    line-height: 1.4;
    color: rgba(242, 244, 245, 0.7);
}

/* ── the two columns ── */
.whyrail {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
    height: 30rem;
    overflow: hidden;
    /* the cards arrive and leave rather than being cut off */
    -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 9%, #000 91%, transparent 100%);
            mask-image: linear-gradient(to bottom, transparent 0, #000 9%, #000 91%, transparent 100%);
}
@media (min-width: 640px) { .whyrail { grid-template-columns: 1fr 1fr; height: 34rem; } }

/* On a phone the two columns would share 30rem and neither would be legible.
   The drift is a desktop flourish; here the reasons simply stack and stay. */
@media (max-width: 639px) {
    .whyrail { height: auto; -webkit-mask-image: none; mask-image: none; }
    .whycol-run { animation: none; transform: none; }
    .whycol-run > [aria-hidden="true"] { display: none; }
}

.whycol { overflow: hidden; }
.whycol-run {
    display: flex;
    flex-direction: column;
    animation: why-drift-up 38s linear infinite;
    will-change: transform;
}
.whycol-down .whycol-run { animation-name: why-drift-down; animation-duration: 44s; }

@keyframes why-drift-up   { from { transform: translateY(0);     } to { transform: translateY(-50%); } }
@keyframes why-drift-down { from { transform: translateY(-50%); } to { transform: translateY(0);     } }

/* reading one of them should not mean chasing it */
.whyrail:hover .whycol-run,
.whyrail:focus-within .whycol-run { animation-play-state: paused; }

/* ── a card ── */
.whycard {
    margin-bottom: 1rem;                 /* the gap, owned by the card — see above */
    padding: 1.5rem;
    border-radius: 1.25rem;
    background: #fff;
    border: 1px solid var(--paper-3);
    box-shadow: 0 1px 2px rgba(18, 33, 46, 0.04), 0 12px 28px rgba(18, 33, 46, 0.06);
    transition: border-color 0.3s, box-shadow 0.3s, transform 0.3s var(--ease-out);
}
.whycard:hover {
    border-color: var(--brand-soft);
    box-shadow: 0 2px 4px rgba(18, 33, 46, 0.05), 0 18px 40px rgba(44, 107, 126, 0.14);
    transform: translateY(-2px);
}
.whycard-ico {
    display: inline-grid;
    place-items: center;
    width: 2.75rem; height: 2.75rem;
    border-radius: 0.875rem;
    background: var(--brand-soft);
    color: var(--brand-deep);
}
.whycard-ico svg { width: 1.125rem; height: 1.125rem; }
.whycard h3 { margin-top: 1rem; font-size: 0.9375rem; font-weight: 700; color: var(--ink); }
.whycard p { margin-top: 0.4375rem; font-size: 0.8125rem; line-height: 1.6; color: var(--ink-60); }

/* ============================================================
   22. MAP EMBED
   ------------------------------------------------------------
   A keyless Google Maps iframe, framed like every other figure on
   the site, with the address sitting on top of it. The card is over
   the map only where there is room for it; on a phone it drops below,
   because a card over a small map leaves neither of them usable.
   ============================================================ */
.map-frame {
    position: relative;
    border-radius: 2rem;
    overflow: hidden;
    border: 1px solid var(--paper-3);
    background: var(--paper-2);
    box-shadow: 0 18px 44px rgba(18, 33, 46, 0.1);
}
.map-frame iframe {
    display: block;
    width: 100%;
    height: 26rem;
    border: 0;
}
.map-card {
    padding: 1.5rem;
    background: #fff;
    border-top: 1px solid var(--paper-3);
}
@media (min-width: 640px) {
    .map-frame iframe { height: 30rem; }
    .map-card {
        position: absolute;
        left: 1.5rem; bottom: 1.5rem;
        width: 20rem;
        border: 1px solid rgba(255, 255, 255, 0.6);
        border-radius: 1.5rem;
        background: rgba(255, 255, 255, 0.92);
        backdrop-filter: blur(12px) saturate(1.3);
        -webkit-backdrop-filter: blur(12px) saturate(1.3);
        box-shadow: 0 16px 40px rgba(18, 33, 46, 0.18);
    }
}

/* ============================================================
   23. REDUCED MOTION
   ------------------------------------------------------------
   main.js additionally skips GSAP entirely, so this covers the CSS
   transitions and keyframes that run without it.
   ============================================================ */
@media (prefers-reduced-motion: reduce) {
    html { scroll-behavior: auto; }
    *, *::before, *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
    /* the rings stay, they just stop turning — the dots were authored at
       angles that sit on the visible arc, so the frozen frame still reads */
    .orbit-ring { animation-play-state: paused; }

    /* the drawer still opens, it just arrives rather than flies in — and its
       contents must not be left waiting on a stagger that no longer runs */
    .enq-intro, .enq-panel .field, .enq-panel .enq-foot { opacity: 1; transform: none; }
    .enq-tab:hover { transform: translateY(-50%); }

    /* the map grid stays; the planes would otherwise freeze mid-fade at
       whatever opacity the paused frame happened to hold */
    .tbg::before { animation: none; }
    .tbg-plane { animation: none; opacity: 0.12; }

    /* With the keyframes forced to finish, the rising column would rest half
       a run up — showing the duplicates, which are hidden from assistive tech.
       Stop it dead instead, drop the copies and let the list stand full height. */
    .whycol-run { animation: none !important; transform: none !important; }
    .whyrail { height: auto; -webkit-mask-image: none; mask-image: none; }
    .whycol-run > [aria-hidden="true"] { display: none; }

    .media img { transition: none; }
    .group:hover .media img, .media:hover img { transform: none; }
    .btn:hover, .card-lift:hover { transform: none; }
    .nav-drawer { transition: none; }
}
