/* ============================================================
   ALLIANCE TRAVEL — Cinematic Design System
   Dark editorial · Warm bronze · Destination accents
   ============================================================ */

/* v26 mobile-ux: render-blocking @import removed (an @import blocks the whole
   stylesheet). DM Sans still loads via the <link> in each page <head>. */

/* ── Reset ─────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h, 72px) + 12px);
  font-size: var(--fs-body);
  overflow-x: clip;
}

body {
  background: var(--bg);
  color: var(--txt-1);
  font-family: var(--font-body);
  font-size: var(--fs-body, 1rem);
  line-height: var(--lh-relaxed, 1.6);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
  /* v22 Agent 3 — svh = smallest viewport height (URL bar showing). Body
     uses svh so the page always fits regardless of iOS Safari URL-bar
     state; pre-15.4 falls back to vh. Sticky/full-bleed regions use
     dvh instead — see scroll-hero__pinned for the rationale. */
  min-height: 100vh;
  min-height: 100svh;
}

/* Headings default to the display face (Sora, via --font-display).
   Low-specificity tag rule so component classes that set size/weight keep
   working and any that needs to opt out still can. The RTL block remaps
   --font-display to Cairo, so Arabic headings render in Cairo — never
   Fraunces (which has no Arabic glyphs). */
h1, h2, h3, h4, h5, h6 {
  font-family: var(--font-display);
  font-optical-sizing: auto;
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

button {
  cursor: pointer;
  font-family: inherit;
  border: none;
  background: none;
}

/* ════════════════════════════════════════════════════════════════
   ⛰  RESPONSIVE FOUNDATION  (v22 · 2026-05-22)
   ════════════════════════════════════════════════════════════════
   Single source of truth for breakpoints, spacing scale, fluid type,
   section rhythm, container gutters, touch safety, mobile-perf gates.
   ADDITIVE: legacy --s1..--s12 + scattered clamp() are left alone.
   ════════════════════════════════════════════════════════════════ */
:root {
  /* ── SPACING SCALE — 8-aligned (user-requested 8/16/24/32/48/64/80) ── */
  --space-1:  4px;
  --space-2:  8px;
  --space-3:  16px;
  --space-4:  24px;
  --space-5:  32px;
  --space-6:  48px;
  --space-7:  64px;
  --space-8:  80px;
  --space-9:  96px;
  --space-10: 128px;

  /* ── FLUID SECTION RHYTHM — recovers ~96px per section on mobile ── */
  --section-y:    clamp(48px, 8vw, 96px);
  --section-y-sm: clamp(32px, 5vw, 64px);
  --section-y-lg: clamp(64px, 10vw, 128px);

  /* ── CONTAINER GUTTER ── */
  --container-x: clamp(16px, 5vw, 80px);

  /* ── FLUID TYPOGRAPHY SCALE ── */
  /* The ladder below 16px, settled 2026-09-20: 11 / 13 / 15 / 16. It used
     to be a single fluid rung, which is why ~200 declarations opted out
     and six near-identical sizes carried most of the page's text. */
  --fs-2xs:        .6875rem;   /* 11px */
  --fs-caption:    .8125rem;   /* 13px */
  --fs-body-sm:    .9375rem;   /* 15px */
  /* v26 mobile-ux: floor raised 0.9375rem→1rem so body copy never drops below 16px on phones */
  --fs-body:       1rem;       /* 16px */
  --fs-body-lg:    clamp(1rem,       0.95rem  + 0.30vw, 1.125rem);
  --fs-h6:         clamp(1rem,       0.95rem  + 0.30vw, 1.125rem);
  --fs-h5:         clamp(1.125rem,   1.05rem  + 0.40vw, 1.25rem);
  --fs-h4:         clamp(1.25rem,    1.10rem  + 0.80vw, 1.5rem);
  --fs-h3:         clamp(1.5rem,     1.20rem  + 1.40vw, 2rem);
  --fs-h2:         clamp(1.875rem,   1.40rem  + 2.20vw, 2.75rem);
  --fs-h1:         clamp(2.25rem,    1.60rem  + 3.00vw, 3.5rem);
  --fs-display-2:  clamp(2.75rem,    1.80rem  + 4.50vw, 4.5rem);
  --fs-display-1:  clamp(3rem,       2.00rem  + 6.00vw, 6rem);

  /* ── LINE-HEIGHT TOKENS ── */
  --lh-tight:    1.1;
  --lh-snug:     1.25;
  --lh-normal:   1.5;
  --lh-relaxed:  1.7;

  /* ── TOUCH & FORM TARGETS ── */
  --touch-min:   44px;
  --field-h:     52px;
  --field-fs:    16px;

  /* ── STICKY CHROME HEIGHTS ── */
  --nav-h:        72px;
  --sticky-bar-h: 68px;
  --fab-size:     56px;
}

/* Touch-device safety — 44×44 targets + iOS-zoom-safe inputs */
@media (pointer: coarse) {
  a[href]:not(.skip-link):not(.nav-logo):not(.lang-btn),
  button:not(.theme-toggle):not(.lang-btn):not(.nav-hamburger),
  [role="button"],
  summary,
  .phone-card__btn {
    min-height: var(--touch-min);
  }
  input:not([type="checkbox"]):not([type="radio"]),
  select,
  textarea {
    min-height: var(--field-h);
    font-size: max(var(--field-fs), 1rem);
  }
  a, button, [role="button"], summary, input, select, textarea {
    touch-action: manipulation;
  }
}

/* Performance gates for small viewports.
   Heavy backdrop-filter blurs cost GPU cycles on mobile; cap or strip
   them per selector. Only touches blurs > 12px on selectors that appear
   on mobile trip + landing pages. Locked-out: .nav-backdrop (Phase 3),
   .site-nav.scrolled (already gated above), .trust-strip (already nulled). */
@media (max-width: 640px) {
  .site-nav.scrolled {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  .trust-strip {
    background: rgba(12, 14, 18, 0.92);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
  /* Floating pill site-nav: 24px sat(180%) → 8px no-sat */
  .site-nav {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  /* Sticky bars: cap 16-20px → 8px, drop saturate */
  .sticky-total,
  .trip-sticky-bar {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  /* Dropdown menu (trip switcher), toast: cap 12-18px → 8px */
  .trip-switcher__menu,
  .toast {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  /* Hero ghost button: 12px → 8px */
  .home-hero .btn--ghost,
  .hero .btn--ghost {
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
  }
  /* Trip-card overlays (mobile shows ~3 cards stacked, each with 2 blurred chips) */
  .trip-card__from,
  .trip-card__monument {
    backdrop-filter: blur(8px) !important;
    -webkit-backdrop-filter: blur(8px) !important;
  }
  /* Glass elevation wrapper utility */
  section + section::before { display: none !important; }
  .home-hero__photos picture:nth-child(n+3) { display: none; }
}

/* Reduced motion — hard kill switch */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* Fluid typography utilities */
.fs-display-1 { font-size: var(--fs-display-1); line-height: var(--lh-tight);   }
.fs-h3        { font-size: var(--fs-h3);        line-height: var(--lh-snug);    }
.fs-h5        { font-size: var(--fs-h5);        line-height: var(--lh-normal);  }
.fs-body-lg   { font-size: var(--fs-body-lg);   line-height: var(--lh-relaxed); }
.fs-body      { font-size: var(--fs-body);      line-height: var(--lh-relaxed); }
.fs-body-sm   { font-size: var(--fs-body-sm);   line-height: var(--lh-normal);  }
.fs-caption   { font-size: var(--fs-caption);   line-height: var(--lh-normal);  }

/* Adaptive grid utilities */
.grid-cards     { display: grid; gap: var(--space-5); grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-cards--lg { grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr)); gap: var(--space-5); }

/* Atomic utilities — minimal set for inline-style migration (v22 Phase A) */
.u-hidden        { display: none; }
.u-text-center   { text-align: center; }
.u-mx-auto       { margin-inline: auto; }
.u-m-0           { margin: 0; }
.u-mt-sp3        { margin-top: var(--space-3); }
.u-mb-sp3        { margin-bottom: var(--space-3); }
.u-mb-sp4        { margin-bottom: var(--space-4); }
.u-size-full     { width: 100%; height: 100%; }
.u-measure-md    { max-width: 600px; }
.u-measure-lg    { max-width: 680px; }
.u-measure-xl    { max-width: 720px; }
.u-text-1        { color: var(--txt-1); }
.u-text-2        { color: var(--txt-2); }
.u-text-3        { color: var(--txt-3); }
.u-text-mint     { color: var(--mint); }
.u-text-accent   { color: var(--accent); }
.u-fw-400        { font-weight: 400; }
.u-fw-600        { font-weight: 600; }
.u-font-display  { font-family: var(--font-display); }
.u-radius-clip   { border-radius: var(--r2); overflow: hidden; }
.u-divider       { height: 1px; background: var(--border); }
.u-bg-2          { background: var(--bg-2); }
.u-no-decoration { text-decoration: none; }

/* Noscript fallback styling (used in 5 region pages' booking-section <noscript>) */
.u-noscript-card { margin: 48px auto; padding: 24px; background: var(--bg-card);
                   border: 1px solid rgba(255,255,255,.1); border-radius: var(--r3); color: var(--txt-1); }
.u-noscript-msg  { margin: 0 0 16px; color: var(--txt-2); line-height: 1.6; }
.u-noscript-title { margin: 0 0 12px; }
.u-cluster       { display: flex; flex-wrap: wrap; gap: var(--space-4); }

/* ════════════════════════════════════════════════════════════════
   ⛰  /RESPONSIVE FOUNDATION
   ════════════════════════════════════════════════════════════════ */

/* Mobile will-change gates (v22) — release compositor layers for
   continuous-animation + scroll-linked selectors on ≤640px. The
   keyframes / scroll handlers still run, but the browser is allowed
   to manage layer creation per-frame instead of permanently. Outside
   the foundation block so component-level concerns stay editable. */
@media (max-width: 640px) {
  [data-region] .hero,
  .home-hero__photos img,
  .fab-whatsapp::before {
    will-change: auto;
  }
}

/* ════════════════════════════════════════════════════════════════
   🔺 Z-INDEX LAYER SYSTEM  (v22 · 2026-05-22)
   ════════════════════════════════════════════════════════════════
   Single semantic layer system. Use tokens rather than raw numbers
   so layer relationships stay explicit and reorderable in one place.
   Order: base → raised → dropdown → sticky → nav → backdrop →
   drawer → modal → toast → fab.

   MIGRATION SCOPE: site-chrome layers (nav, sticky, dropdown, modal,
   toast, fab, lightbox, scroll-progress, sticky-total, skip-link,
   trip-switcher menu, trip-sticky-bar) → tokens. Intra-component
   stacking ladders (small integers 0–25 used to order children inside
   one isolated stacking context, e.g. hero layers, scroll-hero
   parts, map pins, trip-card overlays) intentionally STAY raw —
   those numbers form a local ladder a single token can't capture.
   Negative values (-1, -2) for decorative ::before underlays also
   stay raw. The 3 z-indexes inside MOBILE NAV DRAWER are locked
   from d91e50b — do not migrate.
   ════════════════════════════════════════════════════════════════ */
:root {
  --z-base:     0;
  --z-raised:   1;     /* card hover lifts, image overlays            */
  --z-dropdown: 100;   /* select dropdowns, tooltips                  */
  --z-sticky:   200;   /* sticky-total bar                            */
  --z-nav:      300;   /* fixed site-nav                              */
  --z-backdrop: 350;   /* nav drawer backdrop (below drawer)          */
  --z-drawer:   400;   /* nav drawer panel                            */
  --z-modal:    500;   /* lightbox, full overlays                     */
  --z-toast:    600;   /* toast notifications                         */
  --z-fab:      650;   /* WhatsApp FAB                                */
}

ul {
  list-style: none;
}

input,
select {
  font-family: inherit;
}

/* ══════════════════════════════════════════════════════════════
   CANONICAL TOKEN ROOT — single source of truth
   ──────────────────────────────────────────────────────────────
   This block consolidates 4 years of v1 → v19 token redefinitions
   that previously lived in 5 separate :root blocks scattered through
   the file. All cascade-winning values are preserved exactly — Phase
   A.1 produces ZERO visual diff. Scale migration (spacing, radii,
   elevation refinements) is deferred to Phase A.2 with its own visual
   review.

   ARCHITECTURE
     • Dark mode is the default (no theme attribute needed).
     • Light mode override lives in the single :root[data-theme="light"]
       block immediately below.
     • Per-page accent overrides (egypt amber, azerbaijan crimson,
       istanbul teal, malaysia mint, sharm coral) live in the inline
       <style> at the head of each HTML page — page-scoped, not site
       tokens.
     • Legacy color shims (--navy-hov, --mint-hov, --sage-light,
       --danger-light) are kept as literal values matching the pre-
       cleanup baseline. The --bronze family was deleted in Phase J
       once all consumers migrated to var(--mint*). Remaining shims
       will get deleted as components migrate.

   ADD-A-TOKEN RULES
     1. Add it here, not in another :root block.
     2. If it's a brand color, add the dark variant here AND the light
        equivalent in the light-mode block below.
     3. If it's motion, it must use one of: --t-fast, --t-base, --t-slow,
        --t-cinema (durations) × --ease-out, --ease-spring, --ease-snap,
        --ease-bounce (easings). No ad-hoc bezier curves.
   ══════════════════════════════════════════════════════════════ */
:root {
  /* ── Surfaces — 6-layer dark ladder (v19) ──────────────────────── */
  --bg-deep:   #06090d;          /* page edge, behind sticky chrome  */
  --bg:        #0a0f15;          /* page background                  */
  --bg-low:    #0d131b;          /* one tick darker for low-priority */
  --bg-2:      #11181f;          /* alternating section bg           */
  --bg-card:   #161e28;          /* card surfaces — clearly elevated */
  --bg-elev:   #1c2532;          /* hover state, dropdowns, modals   */
  --bg-glass:  rgba(20, 26, 36, .72);  /* frosted backdrop pill/nav  */

  /* ── Borders ───────────────────────────────────────────────────── */
  --border:      rgba(255, 255, 255, .06);
  --border-hi:   rgba(255, 255, 255, .12);
  --border-mint: rgba(156, 232, 178, .32);

  /* ── Text — warm-temperature ladder (v19) ──────────────────────── */
  --txt-1:  #f3ede2;             /* primary — warm cream             */
  --txt-2:  #b6ada0;             /* secondary — warm beige           */
  --txt-3:  #8e857a;             /* tertiary — muted warm gray (v22.2 WCAG-AA bump from #7a7268 4.06:1 → 4.6:1) */

  /* ── Brand — Prussian Blue + Mint ──────────────────────────────── */
  --navy:        #002c51;
  --navy-soft:   #003d72;
  --navy-dim:    rgba(0, 44, 81, .30);
  --mint:        #9ce8b2;
  --mint-soft:   #7dd4a0;
  --mint-deep:   #5cb37c;
  --mint-dim:    rgba(156, 232, 178, .10);
  --mint-glow:   rgba(156, 232, 178, .28);
  --ring:        rgba(156, 232, 178, .55);   /* focus ring */

  /* ── Default accent (per-page <style> overrides this on trip pages) */
  --accent:       #9ce8b2;
  --accent-dim:   rgba(156, 232, 178, .12);
  /* Gold retired (owner call 2026-08-13): the amber secondary accent read as
     clutter. Alias to the primary accent so every --accent-2 consumer (hero em,
     step badges, amber chips) collapses onto the single brand green. */
  --accent-2:      var(--accent);
  --accent-2-dim:  var(--accent-dim);
  --accent-glow:  rgba(156, 232, 178, .26);

  /* ── Status ────────────────────────────────────────────────────── */
  --sage:         #3B7A65;
  --sage-soft:    rgba(59, 122, 101, .18);
  /* #cf5252 measured 3.98:1 on --bg-card (#161e28) — under AA for the
     booking-form field errors and required-field asterisks that sit on
     cards. Lightened the minimum that clears 4.5:1 on BOTH card and page
     backgrounds (4.61 and 5.28) while keeping the hue. */
  --danger:       #d46363;
  --danger-soft:  rgba(207, 82, 82, .12);
  /* --danger is tuned as TEXT on the card/page grounds above. As a FILL it
     runs the other way: white on #d46363 is 3.64:1 (and 4.21:1 on the
     pre-2026-09 #cf5252, so the fill never passed). --danger-bg is the
     variant for anything that paints light ink ON the red. */
  --danger-bg:    #c94a4a;
  --warn:         #e0a04a;
  --warn-soft:    rgba(224, 160, 74, .14);
  /* 2026-09-05: stars follow the brand green. Owner rule: amber is a WARNING
     colour only (--warn), never decoration; the old #F5C842 also measured
     1.59:1 on white. --mint, NOT --accent: every trip page overrides --accent
     with its region colour in an inline <style>, and a var() indirection
     resolves at the consumer — so review stars came out sky-blue on Istanbul
     and orange on Bali. --mint is the one token no page overrides. */
  --star-gold:    var(--mint);

  /* ── WhatsApp — brand color, immutable in both themes ───────────── */
  --wa-green:     #25D366;
  --wa-green-hov: #1ebe5d;
  --wa-ink:       #052e16;   /* on-green text/icon ink for WA buttons */

  /* ── Per-region hero atmospheres (always dark, no light override) ─ */
  --region-bg-egypt:      #0a0703;
  --region-bg-azerbaijan: #050a14;
  --region-bg-istanbul:   #080612;
  --region-bg-malaysia:   #030a05;
  --region-bg-sharm:      #020a10;

  /* ── Typography ────────────────────────────────────────────────── */
  --font-display: 'Sora', 'DM Sans', system-ui, sans-serif;  /* 2026-08-13: one display voice — Sora everywhere (owner retired Fraunces after rejecting its italic hero; a serif-heading/sans-hero split read as a patchwork). Body stays DM Sans; the RTL block remaps display to Cairo (Sora is Latin-only). */
  --font-body:    'DM Sans', system-ui, sans-serif;
  --font-hero-display: 'Sora', 'DM Sans', system-ui, sans-serif; /* heroes only: modern geometric sans (owner call 2026-08-13 — Fraunces italic heroes read as unreadable); RTL remaps to Cairo */

  /* ── Spacing scale (legacy v1 — kept for backward compat; use --space-* in new code)
       Aliases by design: --s4/--s5 both 24px (legacy v1 → v6 widening absorbed a removed step);
                          --s7/--s8 both 40px (same lineage). 3000+ references across
                          components — DO NOT delete, only fix anomalies.
       v22 anomaly fix: --s2 was 9px (off-8-grid). Now 8px so the legacy
       and --space-2 (8px) scales agree at that step. Single 1px nudge,
       no expected visual regression — visually verified at 1440px. */
  --s1:   4px;  --s2:   8px;  --s3:  16px;  --s4:  24px;
  --s5:  24px;  --s6:  32px;  --s7:  40px;  --s8:  40px;
  --s9:  56px;  --s10: 72px;  --s11: 96px;  --s12: 128px;

  /* ── Radii (--r1 = 2px today; will move to 4px in A.2) ─────────── */
  --r1: 2px;
  --r2: 8px;
  --r3: 12px;
  --r4: 999px;
  /* Two rungs the original four never had, added 2026-09-20. The shipped
     design leans on both — 4px across small tags, pills, the hotel ribbon and
     the extras checkbox (24 elements on the homepage alone), and 16px on the
     card family. Declaring them is what lets every border-radius in this file
     resolve to a token; the alternative was snapping cards from 18px to 12px,
     which is a redesign wearing a refactor's clothes. */
  --r-tag:  4px;
  --r-card: 16px;

  /* ── Elevation (navy-tinted v1; refined ladder in A.2) ────────── */
  --elev-1: 0 1px 0 rgba(0, 44, 81, .2),  0 4px 16px rgba(0, 0, 0, .4);
  --elev-2: 0 12px 48px rgba(0, 0, 0, .6), 0 0 0 1px rgba(0, 44, 81, .15);
  /* The two map panels (#algeria-map, #trip-map) shared one shadow and one
     light-theme variant, written out four times. Same concept, four places
     to drift apart. Not folded into --elev-1/2: neither matches it, and of
     the 61 distinct bespoke shadows in this file 51 are used exactly once,
     so the depth here is per-component by design, not by accident. */
  --elev-map:     0 30px 60px -30px rgba(0, 44, 81, .35);

  /* ── Motion — durations (survey Q14: +--t-cinema) ──────────────── */
  --t-fast:   180ms;    /* tap, focus, micro state                    */
  --t-base:   320ms;    /* component hover, dropdown, modal           */
  --t-slow:   560ms;    /* section entrance, sticky reveal            */
  --t-cinema: 900ms;    /* hero entrance, map fly-to, page transition */
  --t:        200ms ease-out;  /* legacy v1 alias — TODO migrate to --t-fast */

  /* ── Motion — easings (survey Q13: 3 base + 1 bounce) ──────────── */
  --ease-out:    cubic-bezier(.22, 1, .36, 1);
  --ease-spring: cubic-bezier(.22, 1, .36, 1);   /* same curve, semantic alias */
  --ease-snap:   cubic-bezier(.4,  0, .2, 1);    /* taps & chrome (Material)   */
  --ease-bounce: cubic-bezier(.34, 1.5, .64, 1); /* DELIGHT ONLY — toast, counter punch */
  /* Legacy alias kept while a few v6 transitions still reference it.
     --ease-out-quart deleted in phase H — had zero consumers. */
  --ease-spring-soft: var(--ease-spring);

  /* ── Legacy color shims (literal values matching baseline) ─────── */
  --navy-hov:     #003d72;                    /* = navy-soft */
  --mint-hov:     #7dd4a0;                    /* = mint-soft */
  --sage-light:   rgba(59, 122, 101, .18);    /* = sage-soft */
  --danger-light: rgba(185, 64, 64, .15);     /* v1 red (lower saturation than --danger) */
  /* v21 phase J: --bronze, --bronze-hov, --bronze-dim deleted — every
     consumer migrated to var(--mint), var(--mint-hov), var(--mint-dim). */
}

/* ── Light mode — single canonical override ──────────────────────── */
:root[data-theme="light"] {
  /* Surfaces */
  --bg-deep:   #ede5d4;
  --bg:        #fbf8f1;          /* warm cream page */
  --bg-low:    #f5efe1;
  --bg-2:      #f7f1e3;
  --bg-card:   #ffffff;
  --bg-elev:   #ffffff;
  --bg-glass:  rgba(251, 248, 241, .82);

  /* Borders */
  --border:      rgba(0, 44, 81, .08);
  --border-hi:   rgba(0, 44, 81, .16);
  --border-mint: rgba(35, 122, 74, .35);

  /* Text — txt-3 uses v3.1 WCAG fix (#5a6a7c, 5.8:1 contrast on cream)
     instead of v19's regressed #8a8e98 (3.04:1, failed AA). */
  --txt-1:  #002c51;             /* primary — brand Prussian */
  --txt-2:  #4a5567;             /* secondary — slate        */
  --txt-3:  #5a6a7c;             /* tertiary — AA-compliant  */

  /* Brand — mint darkened for AA contrast on cream */
  --navy:        #002c51;
  --navy-soft:   #003d72;
  --navy-dim:    rgba(0, 44, 81, .12);
  --mint:        #237a4a;
  --mint-soft:   #2c8a55;
  --mint-deep:   #1f6b40;
  --mint-dim:    rgba(35, 122, 74, .10);
  --mint-glow:   rgba(35, 122, 74, .25);
  --ring:        rgba(35, 122, 74, .50);

  /* Accent (default; per-page <style> overrides win) */
  --accent:       #237a4a;
  --accent-dim:   rgba(35, 122, 74, .12);
  /* Gold retired (owner call 2026-08-13) — same alias as the dark theme. */
  --accent-2:      var(--accent);
  --accent-2-dim:  var(--accent-dim);
  --accent-glow:  rgba(35, 122, 74, .24);
  /* Error red for light: #cf5252 measured 4.22 on white, 3.89 on the tinted
     banner and 3.17 on the CTA note. #a33333 clears 4.5 on all three. */
  --danger:       #a33333;
  --danger-soft:  rgba(163, 51, 51, .12);
  /* Light's --danger is already dark enough to carry white ink (6.82:1),
     so --danger-bg tracks it; it exists here only so the token resolves
     in both themes. */
  --danger-bg:    #a33333;
  --elev-map:     0 30px 60px -30px rgba(0, 44, 81, .15);
  /* --danger-light is the tint the error chips and invalid fields actually
     consume (:2060, :2662); without a light override they kept the dark
     theme's value under a light-theme red. */
  --danger-light: rgba(163, 51, 51, .12);

  /* Elevation — navy-tinted, softer */
  --elev-1: 0 1px 0 rgba(0, 44, 81, .06), 0 4px 16px rgba(0, 44, 81, .05);
  --elev-2: 0 12px 48px rgba(0, 44, 81, .12);

  /* Legacy color shims (literal values matching baseline) */
  --mint-hov:     #1a6638;                  /* slightly darker than --mint-soft */
  /* v21 phase J: --bronze, --bronze-hov, --bronze-dim deleted — every
     consumer migrated to var(--mint), var(--mint-hov), var(--mint-dim). */
}

/* ── Layout ─────────────────────────────────────────────── */
.container {
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: var(--container-x, clamp(16px, 5vw, 80px));
  width: 100%;
}
/* .u-measure-* are declared at the top of the file, BEFORE .container. Same
   specificity, later rule wins — so `.container.u-measure-xl` computed to 1280px
   and the legal pages ran at ~142 characters per line. Compound selectors here,
   after .container, restore the measure. */
.container.u-measure-md { max-width: 600px; }
.container.u-measure-lg { max-width: 680px; }
.container.u-measure-xl { max-width: 720px; }
.section    { padding-block: var(--section-y,    clamp(48px, 8vw, 96px));  }
.section-sm { padding-block: var(--section-y-sm, clamp(32px, 5vw, 64px));  }

/* ── Navigation ─────────────────────────────────────────── */
.site-nav {
  position: fixed;
  top: 0;
  inset-inline: 0;
  z-index: var(--z-nav);
  padding: var(--s4) var(--s7);
  display: flex;
  align-items: center;
  justify-content: space-between;
  transition: background var(--t-fast), backdrop-filter var(--t-fast);
}

.site-nav.scrolled {
  background: rgba(12, 14, 18, .88);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
}

.nav-logo {
  font-family: var(--font-display);
  font-size: 1.25rem;
  font-weight: 500;
  letter-spacing: .02em;
  color: var(--txt-1);
}

.nav-logo span {
  color: var(--mint);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: var(--s6);
}

.nav-links a {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  transition: color var(--t-fast);
}

.nav-links a:hover {
  color: var(--txt-1);
}

.nav-cta {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  padding: var(--s2) var(--s5);
  background: var(--mint);
  /* --mint is light in the default (dark) theme, so white text was ~1.4:1 and
     invisible; navy is the fixed dark ink. Light theme overrides back to #fff
     (darker --mint) via the !important rule further down. */
  color: var(--navy);
  border-radius: var(--r4);
  transition: background var(--t-fast), transform var(--t-fast);
}

.nav-cta:hover {
  background: var(--mint-hov);
  transform: translateY(-1px);
}

/* ════════════════════════════════════════════════════════════════
   MOBILE NAV DRAWER  (v22 · Phase 3 component #1)
   - ≤900px: hamburger replaces inline nav controls; drawer slides
     in from right (LTR) / left (RTL); backdrop + body scroll lock.
   - ≥901px: drawer wrapper is `display: contents` → desktop layout
     is byte-identical to pre-drawer.
   ════════════════════════════════════════════════════════════════ */

.nav-hamburger { display: none; }
.nav-drawer    { display: contents; }
.nav-backdrop  { display: none; }

@media (max-width: 900px) {
  .site-nav {
    padding: 12px 16px;
    /* Strip backdrop-filter on mobile — it creates a containing block that
       traps the position:fixed .nav-drawer inside the nav's ~72px height box.
       Replace with a solid bg so visual identity stays consistent. Bonus:
       backdrop-filter is GPU-expensive on phones; removing it is a perf win. */
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    /* !important on BOTH backgrounds: the v3 pill block declares the same
       specificity later in the file, so without the flag its 50%-alpha navy
       won the cascade and page text ghosted through the blur-less pill. */
    background: var(--bg-deep, #06090d) !important;
  }
  :root[data-theme="light"] .site-nav { background: rgba(251, 248, 241, 0.98) !important; }

  .nav-hamburger {
    display: grid;
    place-items: center;
    width: var(--touch-min);
    height: var(--touch-min);
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--r4);
    color: var(--txt-1);
    cursor: pointer;
    transition: border-color var(--t-fast), color var(--t-fast), transform var(--t-fast);
    margin-inline-start: auto;
    flex-shrink: 0;
    /* above the drawer it toggles, which itself sits above the nav pill */
    z-index: calc(var(--z-drawer) + 10);
  }
  .nav-hamburger:hover, .nav-hamburger:focus-visible {
    border-color: var(--mint);
    color: var(--mint);
  }
  .nav-hamburger .icon-close { display: none; }
  .site-nav.nav-open .nav-hamburger .icon-menu  { display: none; }
  .site-nav.nav-open .nav-hamburger .icon-close { display: block; }

  /* The drawer is a CHILD of .site-nav (enhance.js `nav.appendChild(drawer)`)
     while the backdrop is appended to <body>. .site-nav is position:fixed with
     z-index:var(--z-nav), so it opens a stacking context: the drawer's own
     z-index orders it only against its nav siblings, and against the page the
     drawer counts for whatever .site-nav counts for. The backdrop, being at
     body level, is compared to .site-nav directly -- so --z-backdrop (350)
     would paint over a nav sitting at --z-nav (300), hiding the drawer behind
     its own scrim.

     Lifting the nav while open carries the whole subtree over the backdrop,
     the sticky bars (--z-sticky) and the page in one move. Needs !important
     to beat the unconditional `.site-nav{z-index:var(--z-nav)!important}`
     further down; the compound selector is more specific, so it wins. */
  .site-nav.nav-open { z-index: calc(var(--z-drawer) + 10) !important; }

  .nav-drawer {
    display: flex;
    position: fixed;
    top: 0; right: 0; bottom: 0;
    width: min(85vw, 360px);
    background: var(--bg-elev);
    border-inline-start: 1px solid var(--border);
    z-index: var(--z-drawer);
    flex-direction: column;
    align-items: stretch;
    gap: var(--space-3);
    padding: calc(var(--nav-h) + 16px) var(--space-5) var(--space-5);
    transform: translateX(100%);
    transition: transform var(--t-base) var(--ease-out), visibility 0s linear var(--t-base);
    visibility: hidden;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding-bottom: max(var(--space-5), env(safe-area-inset-bottom));
    box-shadow: -16px 0 48px rgba(0,0,0,.4);
  }
  [dir="rtl"] .nav-drawer {
    right: auto; left: 0;
    border-inline-start: none;
    border-inline-end: 1px solid var(--border);
    transform: translateX(-100%);
    box-shadow: 16px 0 48px rgba(0,0,0,.4);
  }
  /* Drawer lives on <body> (not inside .site-nav, because nav's
     backdrop-filter creates a containing block that would clip a
     fixed-positioned child). The .is-open class is added to the
     drawer itself by initNavDrawer's setOpen(). */
  .nav-drawer.is-open {
    transform: translateX(0) !important;
    visibility: visible !important;
    transition: transform var(--t-base) var(--ease-out);
  }
  [dir="rtl"] .nav-drawer.is-open {
    transform: translateX(0) !important;
  }

  /* !important needed to beat the later .site-nav .nav-links rules at
     L3596, L3835, L3952 which set display:none, flex-direction:row,
     order:1, grid-column — all designed for the inline desktop nav. */
  .nav-drawer .nav-links {
    list-style: none; margin: 0; padding: 0;
    display: flex !important;
    flex-direction: column !important;
    order: 0 !important;
    gap: 0 !important;
    border-bottom: 1px solid var(--border);
    margin-bottom: var(--space-3);
  }
  .nav-drawer .nav-links li {
    list-style: none;
    width: 100%;
  }
  .nav-drawer .nav-links a {
    display: flex !important;
    align-items: center;
    width: 100%;
    white-space: normal !important;
  }
  .nav-drawer .nav-links li { border-top: 1px solid var(--border); }
  .nav-drawer .nav-links a {
    display: flex; align-items: center;
    padding: var(--space-3) 0;
    font-size: var(--fs-h6);
    color: var(--txt-1);
    min-height: var(--touch-min);
    transition: color var(--t-fast);
  }
  .nav-drawer .nav-links a:hover, .nav-drawer .nav-links a:focus-visible { color: var(--mint); }

  .nav-drawer .lang-switcher, .nav-drawer .theme-toggle { align-self: flex-start; }

  .nav-drawer .nav-cta {
    display: flex; justify-content: center; align-items: center;
    gap: var(--space-2);
    margin-top: auto;
    padding: var(--space-3) var(--space-4);
    min-height: var(--touch-min);
    font-size: var(--fs-body);
    border-radius: var(--r4);
    width: 100%;
    box-sizing: border-box;
  }

  /* Controls move into .nav-drawer at <=900px via initNavDrawer() in
     enhance.js. Hide their inline-nav slots so they don't render twice
     during the brief moment between page parse and JS execution. */
  .site-nav > .nav-links,
  .site-nav > .lang-switcher,
  .site-nav > .theme-toggle,
  .site-nav > .nav-cta { display: none; }

  .nav-backdrop {
    display: block;
    position: fixed; inset: 0;
    background: rgba(0,0,0,.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    z-index: var(--z-backdrop);
    opacity: 0;
    pointer-events: none;
    transition: opacity var(--t-base) var(--ease-out);
  }
  .nav-backdrop.is-visible { opacity: 1; pointer-events: auto; }

  body.nav-scroll-lock { overflow: hidden; }
}

/* ── Hero ───────────────────────────────────────────────── */
.hero {
  position: relative;
  min-height: 100svh;
  display: grid;
  grid-template-rows: 1fr auto;
  overflow: hidden;
}

.hero__bg {
  position: absolute;
  inset: 0;
  background: var(--hero-gradient, linear-gradient(135deg, #1a1208 0%, #0a0c12 60%, #0c1420 100%));
}

.hero__bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 80% 60% at 70% 50%, var(--accent-glow), transparent 70%);
}

.hero__noise {
  position: absolute;
  inset: 0;
  opacity: .03;
  background-image: url("data:image/svg+xml,%3Csvg viewBox='0 0 256 256' xmlns='http://www.w3.org/2000/svg'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='4' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* v21 phase J.2.4: .hero__faded-title (v13 trip-hero giant watermark) deleted —
   v14 scroll-pinned hero has no host for this. Same pattern as the
   home-hero's TRAVEL watermark removed in E.1. */

.hero__inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s7);
  align-items: center;
  padding: 140px clamp(20px, 5vw, 80px) var(--s10);
  max-width: 1280px;
  margin-inline: auto;
  width: 100%;
}

.hero__content {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  padding: var(--s1) var(--s3);
  border: 1px solid var(--accent-dim);
  border-radius: var(--r4);
  width: fit-content;
}

.hero__title {
  font-family: var(--font-display);
  font-size: clamp(44px, 6vw, 88px);
  font-weight: 400;
  line-height: 1.05;
  color: var(--txt-1);
}

.hero__title em {
  font-style: normal;
  color: var(--accent-2);   /* accent em — Sora has no italic; color carries the emphasis */
}

.hero__lede {
  font-size: 1.0625rem;
  color: var(--txt-2);
  max-width: 44ch;
  line-height: 1.65;
}


.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s2);
}

/* v21 phase J.2.4: .hero__dep-card + .dep-pill + .dep-badge family
   deleted — the floating "departure card" overlay on v13 trip heroes
   that showed upcoming flight dates inline. v14 hero replaced this
   with the calculator section; the floating overlay is gone. */

/* v21 phase J.2.4: .hero__strip + .hero__strip-inner + .trust-pill
   family deleted — v13 hero trust strip (review-stars / experience-
   years / certifications under the hero). v14 + v7 industry layer
   replaced this with the standalone .trust-strip component injected
   by enhance.js. */

/* ── Floating highlight cards ────────────────────────────── */
.highlights {
  background: var(--bg-2);
}

.highlights__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: var(--s4);
}

.hl-card {
  /* bg + border-color from canonical v21-D.2 surface block */
  border: 1px solid;
  border-radius: var(--r3);
  padding: var(--s6);
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}

.hl-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--elev-2);
  border-color: var(--border-hi);
}

.hl-card__icon {
  width: 44px;
  height: 44px;
  border-radius: var(--r2);
  background: var(--accent-dim);
  display: grid;
  place-items: center;
  color: var(--accent);
  /* Transition on the base rule so the icon eases both in AND out of hover
     (was declared only on :hover, causing an instant snap-back on leave). */
  transition: transform var(--t-base) var(--ease-spring);
}

.hl-card__label {
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--txt-3);
}

.hl-card__title {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--txt-1);
}

.hl-card__body {
  font-size: var(--fs-caption);
  color: var(--txt-2);
  line-height: 1.55;
}

/* Section heads — canonical definition lives in section "15. Section heads"
   below (~L7311). The older duplicate block was removed here to keep a single
   source of truth; the .section-head__title em rule was migrated there. */

/* ── Hotel Picker ───────────────────────────────────────── */
.hotels {
  background: var(--bg);
}

.tier-tabs {
  display: flex;
  gap: var(--s2);
  flex-wrap: wrap;
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--s7);
}

.tier-tab {
  padding: var(--s3) var(--s5);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--txt-3);
  border-bottom: 2px solid transparent;
  margin-bottom: -1px;
  transition: color var(--t-fast), border-color var(--t-fast);
  cursor: pointer;
}

.tier-tab[aria-pressed="true"],
.tier-tab:hover {
  color: var(--txt-1);
}

.tier-tab[aria-pressed="true"] {
  border-color: var(--accent);
  color: var(--accent);
}

.hotel-grid {
  display: grid;
  /* v26 mobile-ux: mid-band orphan audit. The 600-768px band is already
     forced to a single column by the ≤768px override (:2249), so the floor
     cannot strand a lopsided 2-up there. Above 768px the 1fr tracks stay
     equal-width; no earlier 1-col forcing needed. */
  /* v27 density: floor 300px→260px yields a 4-up on the 1280px container
     (was 3-up), tightening the 25-hotel egypte wall by a full row-band. It
     still steps to 3-up ~1024px, 2-up ~800px; the ≤768px rule below forces
     1-col. Gap --s5(24px)→--s3(16px) trims inter-row space. */
  /* orphan fix: auto-fill keeps the empty tracks, so a short catalogue never
     filled its row — tunisie (1 card), azerbaidjan (2) and kuala-lumpur (3)
     each left a narrow card pinned to the row's inline-start edge with the
     rest of the section blank (mirrored to the right edge under /ar/).
     auto-fit collapses those empty tracks and behaves exactly like auto-fill
     whenever every track is occupied, so the ≥4-card pages are pixel-
     identical. The repeat count stays keyed to the 260px min on purpose: with
     a definite max the count is computed from the max instead, which drops
     egypte's 4-up to a 2-up. Growth is capped at the item level — see
     .hotel-card's max-width below — and justify-items centres each card in
     its track, so a lone card lands mid-row in LTR and RTL alike. */
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--s3);
  justify-items: center;
}

.hotel-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  /* width:100% preserves the stretch sizing inside a normal track; the cap is
     what stops a lone card ballooning to the whole container once auto-fit
     collapses the empty tracks around it. */
  width: 100%;
  max-width: 420px;
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
  cursor: pointer;
}

.hotel-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--elev-2);
  border-color: var(--border-hi);
}

.hotel-card.selected {
  border-color: var(--mint);
  box-shadow: 0 0 0 1px var(--mint), var(--elev-2);
}

.hotel-card__img {
  aspect-ratio: 4/3;
  background: var(--accent-dim);
  position: relative;
  overflow: hidden;
}

/* v21 phase J.2.5: .hotel-card__img-art + its hover-scale deleted —
   a gradient fill layer for hotel card photos that was replaced by
   real <img> elements via the hotel-card__photo class. */

/* The ribbon's own geometry lives with the sticker rule further down (it sets
   every property this block used to, and wins on source order); its background
   and colour come from the unified `!important` rule below. Per-tier colours
   were dropped with it -- they never rendered. */

.hotel-card__body {
  padding: var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
  flex: 1;
}

.hotel-card__stars {
  display: flex;
  gap: 2px;
  color: var(--star-gold);
}

.hotel-card__name {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--txt-1);
}

.hotel-card__amenities {
  display: flex;
  gap: var(--s2);
  flex-wrap: wrap;
}

.amenity-pill {
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .06em;
  padding: 3px var(--s2);
  background: var(--accent-dim);
  color: var(--accent);
  border-radius: var(--r-tag);
}

.hotel-card__price {
  font-size: var(--fs-caption);
  color: var(--txt-2);
  margin-top: auto;
}

.hotel-card__price strong {
  font-size: 1.375rem;
  font-weight: 600;
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
  display: block;
}

.hotel-card__cta {
  width: 100%;
  padding: var(--s3) var(--s5);
  border-radius: var(--r2);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  border: 1px solid var(--border-hi);
  color: var(--txt-1);
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
  text-align: center;
}

.hotel-card__cta:hover {
  background: var(--mint-dim);
  border-color: var(--mint);
  color: var(--mint);
}

.hotel-card.selected .hotel-card__cta {
  background: var(--mint-dim);
  border-color: var(--mint);
  color: var(--mint);
}

/* Empty state */
.hotel-empty {
  grid-column: 1/-1;
  text-align: center;
  padding: var(--s11) var(--s6);
  color: var(--txt-2);
}

.hotel-empty button {
  margin-top: var(--s4);
  color: var(--accent);
  font-size: var(--fs-body-sm);
  text-decoration: underline;
  cursor: pointer;
}

/* ── Pricing Calculator ──────────────────────────────────── */
.calc-section {
  background: var(--bg-2);
}

.calc-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s9);
  align-items: start;
}

.calc-form {
  display: flex;
  flex-direction: column;
  gap: var(--s6);
}

.calc-form-group {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  min-width: 0;
}

/* Responsive: the hotel/formule <select>'s longest <option> was forcing the
   calc grid's column to its ~700px min-content, clipping the calculator on
   phones. Let the grid items + form controls shrink below intrinsic width. */
.calc-grid > * { min-width: 0; }
.calc-form select,
.calc-form input,
.calc-form textarea { min-width: 0; max-width: 100%; }

.calc-form-label {
  /* v22 Agent 3 — same uplift as .bform-field label: --txt-3 → --txt-2,
     fluid --fs-body-sm, tighter letter-spacing. Keeps the calculator
     and booking form visually consistent. */
  font-size: var(--fs-body-sm);
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--txt-2);
}

/* Date chips */
/* dup sweep 2026-08: the earlier `.date-chips` copy is deleted — an identical
   declaration block is re-declared under "── 11. Date chips ──" further down,
   which wins the cascade outright. */

.date-chip {
  padding: var(--s2) var(--s4);
  border-radius: var(--r4);
  border: 1px solid var(--border);
  font-size: var(--fs-caption);
  color: var(--txt-2);
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
  cursor: pointer;
}

/* Hover gated to non-touch + non-active chips — fixes "hover stuck on first
   default chip after selecting another" (touch devices retain :hover until
   you tap somewhere else; active chip overrides hover so the freeze never
   manifests as a stale visual). */
@media (hover: hover) {
  .date-chip:not(.active):hover {
    border-color: var(--border-hi);
    color: var(--txt-1);
  }
}

.date-chip.active {
  border-color: var(--mint);
  background: var(--mint-dim);
  color: var(--mint);
}

.date-chip:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}

/* Segmented (room type) */
.segmented {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  overflow: hidden;
  background: var(--bg);
}

.seg-opt {
  padding: var(--s3);
  text-align: center;
  font-size: var(--fs-caption);
  color: var(--txt-2);
  border-right: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast);
}

.seg-opt:last-child {
  border-right: none;
}

.seg-opt:hover {
  background: var(--bg-card);
  color: var(--txt-1);
}

.seg-opt.active {
  background: var(--mint-dim);
  color: var(--mint);
  font-weight: 500;
}

/* Stepper */
.stepper-row {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.stepper-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--s3) 0;
  border-bottom: 1px solid var(--border);
}

.stepper-item:last-child {
  border-bottom: none;
}

.stepper-item__info h4 {
  font-size: var(--fs-body-sm);
  color: var(--txt-1);
}

.stepper-item__info p {
  font-size: var(--fs-caption);
  color: var(--txt-3);
}

.stepper {
  display: flex;
  align-items: center;
  gap: var(--s3);
}

.stepper__btn {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  font-size: 1.125rem;
  color: var(--txt-2);
  transition: border-color var(--t-fast), color var(--t-fast), opacity var(--t-fast);
}

.stepper__btn:hover:not(:disabled) {
  border-color: var(--mint);
  color: var(--mint);
}

.stepper__btn:disabled {
  opacity: .35;
  cursor: not-allowed;
}

.stepper__val {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--txt-1);
  min-width: 20px;
  text-align: center;
  font-variant-numeric: tabular-nums;
}

/* Extras toggles */
.extras-list {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.extra-toggle {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: var(--s4);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
}

.extra-toggle:hover {
  border-color: var(--border-hi);
  background: var(--bg-card);
}

/* dup sweep 2026-08: `.extra-toggle.checked` deleted here — re-declared
   identically in the light/dark token block below. */

.extra-toggle__check {
  width: 20px;
  height: 20px;
  border-radius: var(--r-tag);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  flex-shrink: 0;
  transition: background var(--t-fast), border-color var(--t-fast);
}

/* dup sweep 2026-08: `.extra-toggle.checked .extra-toggle__check` deleted here
   — re-declared identically in the same block as the rule above. */

.extra-toggle__info {
  flex: 1;
}

.extra-toggle__label {
  font-size: var(--fs-body-sm);
  color: var(--txt-1);
}

.extra-toggle__detail {
  font-size: var(--fs-caption);
  color: var(--txt-3);
}

.extra-toggle__price {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--txt-2);
  font-variant-numeric: tabular-nums;
  margin-left: auto;
  white-space: nowrap;
}

/* Breakdown panel */
.breakdown {
  position: sticky;
  top: 100px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
}

.breakdown__header {
  padding: var(--s5) var(--s6);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--txt-3);
}

.breakdown__lines {
  padding: var(--s5) var(--s6);
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  min-height: 120px;
}

.breakdown__line {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  gap: var(--s3);
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  animation: lineIn var(--t) both;
  min-width: 0;
}

.breakdown__line span {
  text-align: end;
  font-variant-numeric: tabular-nums;
}
/* The label (1st span) must wrap; only the amount (last span) stays on one
   line — otherwise a long package label nowraps past the panel on phones. */
.breakdown__line span:first-child {
  text-align: start;
  min-width: 0;
  overflow-wrap: anywhere;
}
.breakdown__line span:last-child {
  white-space: nowrap;
  flex-shrink: 0;
}

.breakdown__divider {
  height: 1px;
  background: var(--border);
}

.breakdown__total {
  padding: var(--s5) var(--s6);
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.breakdown__total-label {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
}

.breakdown__total-amount {
  font-family: var(--font-body);
  font-size: 1.75rem;
  font-weight: 600;
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
}

.breakdown__usd {
  padding: 0 var(--s6) var(--s4);
  font-size: var(--fs-caption);
  color: var(--txt-3);
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.breakdown__ctas {
  padding: var(--s5) var(--s6);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.breakdown__empty {
  padding: var(--s8) var(--s6);
  text-align: center;
  color: var(--txt-3);
  font-size: var(--fs-body-sm);
}

.breakdown__why {
  padding: 0 var(--s6) var(--s5);
}

.breakdown__why details {
  font-size: var(--fs-caption);
  color: var(--txt-3);
}

.breakdown__why summary {
  cursor: pointer;
  color: var(--accent);
  display: flex;
  align-items: center;
  gap: var(--s1);
}

.breakdown__why summary:hover {
  color: var(--mint-hov);
}

/* ── Buttons — canonical primitive (v21 phase D.1) ─────────────────
   Previously: `.btn--primary` redefined 3× across lines 1190, 2509,
   3183, with a stale orange box-shadow (bronze legacy) hidden behind
   a mint override 2000 lines later. Consolidated into one block here.
   Variants tweak only what differs from the base. */
.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s3) var(--s6);
  border-radius: var(--r4);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  /* Explicit: without it <a> inherits the body 1.7 and <button> gets the UA
     `normal`, so identical .btn classes rendered 52px vs 59.5px in one row. */
  line-height: 1.7;
  transition:
    background   var(--t-fast) var(--ease-out),
    color        var(--t-fast) var(--ease-out),
    border-color var(--t-fast) var(--ease-out),
    transform    var(--t-fast) var(--ease-snap),
    box-shadow   var(--t-fast) var(--ease-out);
  cursor: pointer;
  border: none;
  text-align: center;
  white-space: nowrap;
  max-width: 100%;
}
.btn:active { transform: scale(.97); }
.btn:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
/* On phones, let a long-label button wrap instead of overflowing the viewport
   (e.g. "Une question ? Contactez-nous sur WhatsApp"). Desktop stays nowrap. */
@media (max-width: 600px) {
  .btn { white-space: normal; }
}

/* Primary — mint fill, navy text, mint glow on hover, radial halo on hover */
.btn--primary {
  position: relative;
  overflow: hidden;
  background: var(--mint);
  color: var(--navy);
  font-weight: 600;
}
.btn--primary:hover {
  background: var(--mint-soft);
  transform: translateY(-1px);
  box-shadow: 0 6px 20px var(--mint-glow);
}
.btn--primary::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at center, rgba(255, 255, 255, .35) 0%, transparent 60%);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
  pointer-events: none;
}
.btn--primary:hover::after { opacity: .6; }

/* Ghost — outlined, transparent fill, tints to accent on hover */
.btn--ghost {
  border: 1px solid rgba(255, 255, 255, .25);
  color: var(--txt-1);
  background: transparent;
}
.btn--ghost:hover {
  border-color: var(--mint);
  color: var(--mint);
  background: var(--mint-dim);
}

/* WhatsApp — brand green */
.btn--wa {
  background: var(--wa-green);
  color: var(--wa-ink);
}
.btn--wa:hover {
  background: var(--wa-green-hov);
  color: var(--wa-ink);
  border-color: transparent;
  transform: translateY(-1px);
}

/* Size + layout variants */
.btn--full { width: 100%; justify-content: center; }
.btn--sm   { padding: var(--s2) var(--s5); font-size: var(--fs-body-sm); }

/* Mobile sticky total bar */
.sticky-total {
  display: none;
  position: fixed;
  bottom: 0;
  inset-inline: 0;
  z-index: var(--z-sticky);
  background: rgba(12, 14, 18, .96);
  backdrop-filter: blur(16px);
  border-top: 1px solid var(--border);
  padding: var(--s3) var(--s5);
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
}

.sticky-total__label {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
}

.sticky-total__amount {
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
}

/* ── Itinerary ───────────────────────────────────────────── */
.itinerary-bg {
  background: var(--bg);
}

.timeline {
  display: flex;
  flex-direction: column;
  gap: 0;
  position: relative;
}

.timeline::before {
  content: '';
  position: absolute;
  left: 15px;
  top: 0;
  bottom: 0;
  width: 1px;
  background: linear-gradient(to bottom, transparent, var(--border) 10%, var(--border) 90%, transparent);
}

.tl-day {
  display: grid;
  grid-template-columns: 32px 1fr;
  gap: var(--s5);
  padding-bottom: var(--s8);
  cursor: pointer;
}

.tl-day:last-child {
  padding-bottom: 0;
}

.tl-node {
  width: 32px;
  height: 32px;
  flex-shrink: 0;
  background: var(--bg-2);
  border: 1px solid var(--border);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--txt-3);
  transition: background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
  position: relative;
  z-index: 1;
}

.tl-day.active .tl-node,
.tl-day:hover .tl-node {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}

.tl-content {
  padding-top: 4px;
}

.tl-day-label {
  font-size: var(--fs-caption);
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: .1em;
  color: var(--accent);
  margin-bottom: var(--s1);
}

.tl-title {
  font-size: var(--fs-body);
  font-weight: 500;
  color: var(--txt-1);
  margin-bottom: var(--s2);
}

.tl-activities {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.6;
}

.tl-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s3);
}

.tl-tag {
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .07em;
  padding: 2px var(--s2);
  border-radius: var(--r-tag);
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--txt-3);
}

/* ══════════════════════════════════════════════════════════
   TIMELINE — ALTERNATING SPINE (additive .timeline--spine modifier)
   Base .timeline above is untouched so un-migrated pages keep working.
   ══════════════════════════════════════════════════════════ */
.timeline--spine {
  position: relative;
}

/* Mobile-first: single left rail (rail moved to centre on desktop below) */
.timeline--spine::before {
  content: '';
  position: absolute;
  left: 21px;
  top: 0;
  bottom: 0;
  width: 2px;
  background: linear-gradient(to bottom, transparent, var(--border) 8%, var(--border) 92%, transparent);
}
[dir="rtl"] .timeline--spine::before {
  left: auto;
  right: 21px;
}

.timeline--spine .tl-day {
  display: grid;
  grid-template-columns: 44px 1fr;
  align-items: start;
  gap: var(--space-5);
  padding-bottom: var(--space-8);
  cursor: pointer;
}
.timeline--spine .tl-day:last-child {
  padding-bottom: 0;
}

/* Medallion node — 44px (meets --touch-min), rings the --bg so the spine
   reads behind it */
.timeline--spine .tl-node {
  grid-column: 1;
  width: 44px;
  height: 44px;
  background: var(--accent-dim);
  border: 1px solid var(--border);
  border-radius: 50%;
  box-shadow: 0 0 0 6px var(--bg);
  display: grid;
  place-items: center;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--accent);
  z-index: 1;
}
.timeline--spine .tl-day.active .tl-node,
.timeline--spine .tl-day:hover .tl-node {
  background: var(--accent-dim);
  border-color: var(--accent);
  color: var(--accent);
}

/* Card — mobile single-rail default */
.timeline--spine .tl-content {
  grid-column: 2;
  text-align: start;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--space-5);
  padding-top: var(--space-5);
  transition:
    transform var(--t-base) var(--ease-out),
    border-color var(--t-base) var(--ease-out),
    box-shadow var(--t-base) var(--ease-out);
}
.timeline--spine .tl-day:hover .tl-content {
  transform: translateY(-4px);
  border-color: var(--accent);
  box-shadow: 0 10px 30px -12px var(--accent-glow);
}

/* Mobile: override fade-left/right to fade-up to avoid x-overflow */
@media (max-width: 767.98px) {
  .timeline--spine .tl-content[data-aos="fade-left"],
  .timeline--spine .tl-content[data-aos="fade-right"] {
    transform: translateY(20px);
  }
}

/* Desktop: central spine + alternating cards */
@media (min-width: 768px) {
  .timeline--spine::before {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
    width: 2px;
    background: linear-gradient(to bottom, transparent, var(--border) 8%, var(--border) 92%, transparent);
  }
  [dir="rtl"] .timeline--spine::before {
    left: 50%;
    right: auto;
  }

  .timeline--spine .tl-day {
    grid-template-columns: 1fr auto 1fr;
    align-items: center;
    gap: var(--space-5);
    padding-bottom: var(--space-8);
  }

  .timeline--spine .tl-node {
    grid-column: 2;
    margin-inline: auto;
  }

  .timeline--spine .tl-day--right .tl-content {
    grid-column: 3;
    text-align: start;
  }
  .timeline--spine .tl-day--left .tl-content {
    grid-column: 1;
    text-align: end;
  }

  /* RTL mirrors the alternation: swap the side columns */
  [dir="rtl"] .timeline--spine .tl-day--right .tl-content {
    grid-column: 1;
    text-align: end;
  }
  [dir="rtl"] .timeline--spine .tl-day--left .tl-content {
    grid-column: 3;
    text-align: start;
  }
}

/* v21 phase J.2: ~95 lines of .packages-bg / .packages-grid /
   .pkg-card / .pkg-card.recommended / .pkg-badge / .pkg-tier /
   .pkg-name / .pkg-price / .pkg-features / .pkg-feature CSS deleted.
   The packages tier-comparison feature was never built — zero HTML
   consumers across all 6 pages, zero JS references. */

/* ── Trust / Social proof ────────────────────────────────── */
.trust-bg {
  background: var(--bg);
}

.stats-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: var(--s5);
  margin-bottom: var(--s11);
}

.stat-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--s6);
  text-align: center;
}

.stat-card__num {
  font-family: var(--font-display);
  font-size: clamp(36px, 5vw, 56px);
  /* weight comes from the later .stat-card__num rule (700) — the 300 that
     used to sit here was dead (shadowed) and 300 is no longer loaded */
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
}

.stat-card__label {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  margin-top: var(--s1);
}

.testimonials-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--s5);
}

/* dup sweep 2026-08: `.testi-card` deleted here — re-declared identically
   under "── 17. Testimonial cards ──" below. */

.testi-stars {
  color: var(--star-gold);
  display: flex;
  gap: 2px;
}

.testi-text {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.65;
  font-style: italic;
}

.testi-author {
  display: flex;
  align-items: center;
  gap: var(--s3);
  margin-top: auto;
}

.testi-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent-dim);
  display: grid;
  place-items: center;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--accent);
}

.testi-name {
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--txt-1);
}

/* dup sweep 2026-08: `.testi-trip` deleted here — the "── 17. Testimonial
   cards ──" copy below re-declares both properties (and adds margin-top). */

/* ── FAQ ─────────────────────────────────────────────────── */
.faq-bg {
  background: var(--bg-2);
}

.faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  /* 780px: the width the two hand-authored pages had set inline; one value now. */
  max-width: 780px;
  margin-inline: auto;
}

.faq-item {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  overflow: hidden;
}

.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding: var(--s5) var(--s6);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  color: var(--txt-1);
  text-align: start;
  cursor: pointer;
  transition: color var(--t-fast);
}

.faq-q:hover {
  color: var(--accent);
}

.faq-q svg {
  flex-shrink: 0;
  transition: transform var(--t-base) var(--ease-spring);
  color: var(--txt-3);
}

.faq-item.open .faq-q svg {
  transform: rotate(180deg);
}

.faq-a {
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--t-base) ease, padding var(--t-base) ease;
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.65;
}

.faq-item.open .faq-a {
  max-height: 400px;
  padding: 0 var(--s6) var(--s5);
}

/* Two accordion mechanisms share this component: the trip pages' <button> +
   .open class (set by calculator.js initFAQ) and the hand-authored pages'
   <details>/<summary>, which set the [open] ATTRIBUTE and load no JS. Both are
   spelled out here so /omra/ and /rendez-vous-visa/ need no page-local copy
   (visual audit D8: three FAQ designs on one site).
   `overflow:hidden` on .faq-item makes Chrome lay a closed <details> body out
   anyway, so the collapse is asserted rather than left to the UA. */
.faq-item[open] .faq-a {
  max-height: none;
  overflow: visible;
  padding: var(--s4) var(--s6) var(--s5);
  border-top: 1px solid var(--border);
}
.faq-item:not([open]) > .faq-a {
  display: none;
}
summary.faq-q {
  list-style: none;
}
summary.faq-q::-webkit-details-marker {
  display: none;
}
.faq-q > span {
  flex: 1;
}
.faq-item[open] .faq-q,
.faq-item[open] .faq-q svg {
  color: var(--accent);
}
.faq-item[open] .faq-q svg {
  transform: rotate(180deg);
}

/* ── Final CTA ───────────────────────────────────────────── */
.final-cta {
  background: var(--bg);
  border-top: 1px solid var(--border);
  padding-block: var(--s12);
  text-align: center;
}

.final-cta__scarcity {
  display: inline-flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--danger);
  background: var(--danger-light);
  border: 1px solid rgba(185, 64, 64, .25);
  padding: var(--s2) var(--s4);
  border-radius: var(--r4);
  margin-bottom: var(--s6);
}

.final-cta__title {
  font-family: var(--font-display);
  font-size: clamp(32px, 5vw, 64px);
  font-weight: 400;
  color: var(--txt-1);
  line-height: 1.1;
  margin-bottom: var(--s5);
}

.final-cta__title em {
  font-style: normal;
  color: var(--accent-2);   /* accent em — color carries the emphasis */
}

.final-cta__sub {
  font-size: 1.0625rem;
  color: var(--txt-2);
  margin-bottom: var(--s8);
  max-width: 52ch;
  margin-inline: auto;
}

.final-cta__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s4);
  justify-content: center;
}

.contact-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s6);
  justify-content: center;
  margin-top: var(--s8);
  padding-top: var(--s8);
  border-top: 1px solid var(--border);
}

.contact-item {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
}

.contact-item svg {
  color: var(--accent);
}

/* v27: plain-text phone numbers in the contact row are now 1-click WhatsApp
   deep-links. Keep them visually inline with the surrounding text, reveal
   affordance on hover/focus. */
.contact-phone-link {
  color: inherit;
  text-decoration: none;
  border-bottom: 1px dotted var(--accent);
  transition: color var(--t-fast, .2s) var(--ease-out, ease);
}
.contact-phone-link:hover,
.contact-phone-link:focus-visible {
  color: var(--accent);
}

/* ── Footer ─────────────────────────────────────────────── */
.site-footer {
  background: var(--bg-2);
  border-top: 1px solid var(--border);
  padding-block: var(--s9);
}


/* dup sweep 2026-08: `.footer-brand` deleted here — the v28 footer block near
   the end of the file re-declares all three properties identically. */


.footer-tagline {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  max-width: 32ch;
}

.footer-col h4 {
  font-size: var(--fs-2xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--txt-3);
  margin-bottom: var(--s4);
}

.footer-col a,
.footer-col p {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  display: block;
  margin-bottom: var(--s2);
  transition: color var(--t-fast);
}

/* dup sweep 2026-08: `.footer-col a:hover` deleted here — the v28 footer block
   re-declares `color: var(--txt-1)` (plus the underline sweep). */

.footer-bottom {
  margin-top: var(--s7);
  padding-top: var(--s7);
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--s4);
  font-size: var(--fs-caption);
  color: var(--txt-3);
}

/* ── Animations ──────────────────────────────────────────── */
@keyframes lineIn {
  from {
    opacity: 0;
    transform: translateY(4px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

@keyframes fadeUp {
  from {
    opacity: 0;
    transform: translateY(24px);
  }

  to {
    opacity: 1;
    transform: translateY(0);
  }
}

.fade-up {
  animation: fadeUp var(--t-slow) ease-out both;
}

.fade-up--d1 {
  animation-delay: 80ms;
}

.fade-up--d2 {
  animation-delay: 160ms;
}

.fade-up--d3 {
  animation-delay: var(--t-fast);
}

/* ── v21 phase C.3 — pause-off-screen plumbing ──────────────
   enhance.js's IntersectionObserver toggles `.is-paused` on any
   ambient host (.home-hero, .hero, #alliance-globe, [data-pause-off-
   screen]) when it scrolls out of view. This rule freezes every CSS
   animation inside the subtree, recovering the frame budget the
   browser would otherwise spend ticking off-screen keyframes.
   Pairs with the Performance Contract in MOTION-CLEANUP-MASTER.md §0a. */
.is-paused,
.is-paused *,
.is-paused *::before,
.is-paused *::after {
  animation-play-state: paused !important;
}

/* Reduced motion */
@media (prefers-reduced-motion: reduce) {

  *,
  *::before,
  *::after {
    animation-duration: 1ms !important;
    transition-duration: 1ms !important;
  }
}

/* ── Responsive ──────────────────────────────────────────── */
@media (max-width: 1024px) {
  .calc-grid {
    grid-template-columns: 1fr;
  }

  .breakdown {
    position: static;
  }

  .sticky-total {
    display: flex;
  }

  /* Exactly one pinned price per screen. This is the only breakpoint where
     .sticky-total is shown, and .trip-sticky-bar (built by enhance.js on every
     trip page) has no width guard of its own — so below 1024px a visitor who
     had configured two adults saw "À partir de 169.000 DA" pinned to the top
     and "Total estimé 338 000 DA" pinned to the bottom at the same time. The
     live, configured total is the truer number, so it keeps the screen here;
     above 1024px .sticky-total is display:none and the inquiry bar stands
     alone, unchanged. Scoped with :has so /rendez-vous-visa/, which has an
     inquiry bar and no calculator, is untouched. */
  body:has(.sticky-total) .trip-sticky-bar,
  body.has-sticky-total .trip-sticky-bar {
    display: none;
  }

  /* v22 Phase 3 — only consume bottom padding on pages that ACTUALLY
     have a sticky-total bar (i.e. trip pages). Homepage previously paid
     for 68px of non-existent chrome. */
  body:has(.sticky-total),
  body.has-sticky-total {
    padding-bottom: var(--sticky-bar-h, 68px);
    /* Respect iOS safe-area so the bar sits above the home indicator */
    padding-bottom: calc(var(--sticky-bar-h, 68px) + env(safe-area-inset-bottom));
  }

  /* v22 Phase 3 — lift the WhatsApp FAB above the sticky-total bar.
     The 16px extra buffer covers cases where the sticky bar's actual
     content height exceeds the --sticky-bar-h token (which is a
     ladder reference, not a hard pin). */
  body:has(.sticky-total) .fab-whatsapp,
  body.has-sticky-total .fab-whatsapp {
    bottom: calc(var(--sticky-bar-h, 68px) + var(--space-4) + env(safe-area-inset-bottom, 0px));
  }

  /* The FAB (z-index 650) sits above the nav drawer's stacking context, so a
     FAB already visible when the drawer opens painted on top of the open
     drawer. Hide it while the drawer holds the scroll lock. */
  body.nav-scroll-lock .fab-whatsapp {
    opacity: 0;
    pointer-events: none;
  }

  /* Same problem, same treatment: the sticky bars ride --z-sticky (200) while
     the drawer backdrop sits at 105, so they stayed full-brightness and
     tap-blocking beside the open drawer — killing tap-outside-to-close along
     the whole bottom band. opacity (not display:none) so body:has(.sticky-total)
     keeps its padding reservation and the page does not reflow. */
  body.nav-scroll-lock .sticky-total,
  body.nav-scroll-lock .trip-sticky-bar,
  body.nav-scroll-lock .trip-sticky-bar--visa {
    opacity: 0;
    pointer-events: none;
  }

  /* v22 Agent 3 — at ≤1024px, swap to auto-fit so each column has a
     min-width floor (220px) and the grid naturally reflows to 1 col
     at ≤480px without needing a 3rd explicit breakpoint. Replaces the
     previous fixed 1fr 1fr which broke awkwardly on phones. */
}

@media (max-width: 768px) {
  /* v22 Phase 3 — trip-page hero mobile reclamation */
  .hero { min-height: auto; }
  .hero__inner {
    grid-template-columns: 1fr;
    padding: calc(var(--nav-h) + var(--space-5)) var(--container-x) var(--space-7);
    gap: var(--space-4);
  }

  /* v26 mobile-ux: homepage hero keeps a fixed ~140px/128px inline padding at
     all widths (set inline in index.html). Override here so the headline sits
     higher on phones, mirroring .hero__inner above. !important beats the inline. */
  .home-hero__inner {
    padding: calc(var(--nav-h) + var(--space-5)) var(--container-x) var(--section-y) !important;
  }

  /* dead-css sweep 2026-08: .hero__strip-inner stacking rule deleted (host
     removed in v21 phase J.2.4). */

  .hotel-grid {
    grid-template-columns: 1fr;
  }

  /* Single column from here down: drop the 420px item cap so the card keeps
     spanning the full track, byte-identical to the pre-cap rendering. */
  .hotel-card {
    max-width: none;
  }

  /* dead-css sweep 2026-08: .packages-grid single-column rule deleted (the
     packages component was culled in v21 phase J.2). */

  .stats-grid {
    grid-template-columns: repeat(2, 1fr);
  }

  .testimonials-grid {
    grid-template-columns: 1fr;
  }

  /* v22 Agent 3 — at ≤768px, drop the brand col bias so its 2fr can
     match the others; auto-fit still controls the column count.
     Final hard collapse to 1 col happens at ≤480px below. */

  .nav-links {
    display: none;
  }

  .footer-bottom {
    flex-direction: column;
    text-align: center;
  }
}

/* v22 Agent 3 — narrowest tier: guarantee 1-column footer + tighter
   gap (auto-fit already collapses but we belt-and-brace it here). */
@media (max-width: 480px) {
  .footer-tagline {
    max-width: none;
  }
}

@media (max-width: 640px) {
  .calc-grid {
    /* v22 Agent 3 — tighten the calc gap on phones (32px → 24px) so the
       form + breakdown stack fits more above the fold. */
    gap: var(--space-4);
  }

  .calc-form {
    /* Match: tighter form-internal gaps on phones (32px → 24px). */
    gap: var(--space-4);
  }

  .hero__ctas {
    flex-direction: column;
  }

  .final-cta__actions {
    flex-direction: column;
    align-items: center;
  }

  .stats-grid {
    grid-template-columns: 1fr;
  }
}

/* ── Utility ─────────────────────────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
}

/* v21 phase J.2.4: .text-accent + .text-bronze utilities deleted —
   zero consumers anywhere; replaced by direct token use. */

.hidden {
  display: none !important;
}

.highlight-flash {
  animation: flash var(--t-slow) ease;
}

@keyframes flash {

  0%,
  100% {
    outline: 0 solid transparent;
  }

  30%,
  70% {
    outline: 2px solid var(--mint);
    outline-offset: 4px;
  }
}

/* ══════════════════════════════════════════════════════════
   BOOKING FORM — WhatsApp Dossier Generator
   ══════════════════════════════════════════════════════════ */

.booking-section {
  background: var(--bg-2);
  border-top: 1px solid var(--border);
}

/* Grid: form left, preview right */
.bform-grid {
  display: grid;
  grid-template-columns: 1fr 420px;
  gap: var(--s9);
  align-items: start;
}
/* Responsive: let the booking grid items + fields shrink so the form doesn't
   exceed the viewport on phones (long select options / inputs). */
.bform-grid > *,
.bform-left,
.bform-block { min-width: 0; }
.bform-grid input,
.bform-grid select,
.bform-grid textarea { min-width: 0; max-width: 100%; }

/* ── Form blocks ──────────────────────────────────────────── */
.bform-left {
  display: flex;
  flex-direction: column;
  gap: var(--s5);
}

.bform-block {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s6);
  display: flex;
  flex-direction: column;
  gap: var(--s5);
}

.bform-block__title {
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--txt-1);
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--border);
}

.bform-block__title svg {
  color: var(--accent);
  flex-shrink: 0;
}

.bform-row-2 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s4);
}

/* ── Form fields ──────────────────────────────────────────── */
.bform-field {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
}

.bform-field label {
  /* v22 Agent 3 — contrast + size up: --txt-3 (#7a7268) → --txt-2
     (#b6ada0) lifts contrast ratio ~3.4× → ~5.7× on --bg-card.
     Fluid sizing via --fs-body-sm reaches 14px on desktop while still
     staying 13px on small phones (legible without taking too much
     vertical space). Letter-spacing dialled back .06 → .04 so caps
     don't feel airy at the new size. */
  font-size: var(--fs-body-sm);
  font-weight: 500;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--txt-2);
}

/* dup sweep 2026-08: `.bform-field .req` deleted here — the "Required asterisk"
   rule below re-declares the same colour (and adds weight/offset). */

.bform-field input,
.bform-field select,
.bform-field textarea {
  background: var(--bg);
  color: var(--txt-1);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--s3) var(--s4);
  font-size: var(--fs-body-sm);
  font-family: var(--font-body);
  line-height: 1.5;
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
  width: 100%;
  min-height: var(--touch-min);
}

/* Placeholders were left to the UA default, which is a grey chosen against a
   white page and lands at roughly 2.5:1 on this dark --bg. Only one field on
   the site (.wa-lead-prompt__input) had ever set it. --txt-3 is the muted text
   token and measures 5.30:1 on --bg in dark and 5.54:1 in light, so the hint
   is legible without competing with the value the visitor types. */
.bform-field input::placeholder,
.bform-field textarea::placeholder,
.contact-form input::placeholder,
.contact-form textarea::placeholder {
  color: var(--txt-3);
  opacity: 1;            /* Firefox dims placeholders by default */
}

.bform-field input:focus,
.bform-field select:focus,
.bform-field textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-dim);
}

.bform-field textarea {
  resize: vertical;
  min-height: 80px;
}

/* ── Trip summary chip row ────────────────────────────────── */
.bf-trip-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

.bf-trip-chip {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding: var(--s2) var(--s4);
  background: var(--accent-dim);
  border: 1px solid rgba(255, 255, 255, .06);
  border-radius: var(--r4);
  font-size: var(--fs-caption);
  color: var(--txt-1);
}

.bf-trip-chip svg {
  color: var(--accent);
}

.bf-trip-chip strong {
  color: var(--accent);
}
/* The total chip used an inline color:var(--bronze) to stand out. That token was
   deleted in Phase J, and an undefined var() on an inherited property computes
   to the inherited colour — so the highlighted total actually rendered DULLER
   than its accent-green siblings, the reverse of the intent. Every chip strong
   is already --accent (above), so the highlight now distinguishes itself by
   weight instead of a second colour. */
.bf-trip-chip strong.is-hl {
  font-weight: 700;
}

.bf-trip-empty {
  font-size: var(--fs-body-sm);
  color: var(--txt-3);
  font-style: italic;
}

/* ── Passport rows ────────────────────────────────────────── */
.bf-passport-entry {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--s4) var(--s5);
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  position: relative;
}

.bf-passport-entry__header {
  display: flex;
  align-items: center;
  justify-content: space-between;
}

.bf-passport-entry__label {
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--accent);
}

.bf-passport-entry__remove {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  color: var(--txt-3);
  font-size: var(--fs-body);
  line-height: 1;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
  cursor: pointer;
}

.bf-passport-entry__remove:hover {
  border-color: var(--danger);
  color: var(--danger);
  background: var(--danger-light);
}

.bf-passport-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s3);
}

.bf-passport-grid .bform-field input {
  /* No font-size here: this selector outranks the `max(16px, 1rem)` iOS guard
     further down, and anything under 16px makes Safari zoom the viewport on
     focus. No hardcoded height either — it outranks the coarse-pointer rule
     too, which is why these four fields were 40px while their siblings were 52. */
  padding: var(--s2) var(--s3);
  min-height: var(--touch-min);
}

.bf-passport-grid .bform-field label {
  font-size: var(--fs-2xs);
}

/* ── Upload zone ──────────────────────────────────────────── */
.upload-zone {
  border: 2px dashed var(--border);
  border-radius: var(--r3);
  padding: var(--s8) var(--s6);
  text-align: center;
  cursor: pointer;
  transition: border-color var(--t-fast), background var(--t-fast);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--s3);
}

.upload-zone:hover,
.upload-zone.drag-over {
  border-color: var(--accent);
  background: var(--accent-dim);
}

.upload-zone__icon {
  color: var(--txt-3);
}

.upload-zone p {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  margin: 0;
}

.upload-zone strong {
  color: var(--txt-1);
}

.upload-browse {
  color: var(--accent);
  text-decoration: underline;
  cursor: pointer;
}

.upload-formats {
  font-size: var(--fs-caption);
  color: var(--txt-3);
}

.upload-previews {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-top: var(--s2);
}

.upload-thumb {
  position: relative;
  width: 80px;
  height: 80px;
  border-radius: var(--r2);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.upload-thumb img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.upload-thumb__label {
  position: absolute;
  bottom: 0;
  inset-inline: 0;
  background: rgba(0, 0, 0, .7);
  font-size: var(--fs-2xs);
  text-align: center;
  padding: 2px 4px;
  color: var(--txt-2);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upload-thumb__remove {
  position: absolute;
  top: 3px;
  right: 3px;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  background: var(--danger-bg);
  color: #fff;
  display: grid;
  place-items: center;
  font-size: var(--fs-2xs);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast);
}

.upload-thumb:hover .upload-thumb__remove,
.upload-thumb:focus-within .upload-thumb__remove,
.upload-thumb__remove:focus-visible {
  opacity: 1;
}

/* Touch devices have no hover: keep the remove button always reachable */
@media (hover: none) {
  .upload-thumb__remove {
    opacity: 1;
  }
}

.upload-pdf-icon {
  color: var(--accent);
}

.bform-note {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  line-height: 1.55;
}

.bform-hint {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.6;
}

/* ── Preview panel (sticky right) ───────────────────────────── */
.bform-right {
  position: sticky;
  top: 100px;
}

.bform-preview {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.bform-preview__header {
  padding: var(--s4) var(--s5);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--txt-3);
  display: flex;
  align-items: center;
  gap: var(--s2);
}

.bform-preview__header svg {
  color: var(--wa-green);
}

.bform-preview__content {
  padding: var(--s5);
  max-height: 480px;
  overflow-y: auto;
  scrollbar-width: thin;
}

.bform-preview__content pre {
  font-family: var(--font-body);
  font-size: var(--fs-caption);
  line-height: 1.7;
  color: var(--txt-2);
  white-space: pre-wrap;
  word-break: break-word;
  margin: 0;
}

.bform-preview__empty {
  font-size: var(--fs-body-sm);
  color: var(--txt-3);
  font-style: italic;
  text-align: center;
  padding: var(--s7) 0;
}

.bform-preview__footer {
  padding: var(--s5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

.bform-preview__foot-note {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  text-align: center;
}

/* v21 phase J.2.4: .bform-send-disabled + .btn--copy* family deleted —
   the booking-form's disabled-send state + clipboard-copy button were
   scaffolded but never wired. .bform-preview__actions container kept
   in case future booking redesign reuses it. */
.bform-preview__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}

/* ── Responsive ──────────────────────────────────────────── */
@media (max-width: 1100px) {
  .bform-grid {
    grid-template-columns: 1fr;
  }

  .bform-right {
    position: static;
  }

  .bform-preview__content {
    max-height: 320px;
  }
}

@media (max-width: 640px) {
  .bform-row-2 {
    grid-template-columns: 1fr;
  }

  .bf-passport-grid {
    grid-template-columns: 1fr;
  }

  /* v22 Agent 3 — phone-fit: tighter padding (32 → 24) and tighter
     internal gaps so each form block consumes ~16px less vertical
     real-estate. The desktop visual stays unchanged. */
  .bform-block {
    padding: var(--space-4);
    gap: var(--space-4);
  }

  .bform-left {
    gap: var(--space-4);
  }
}

/* ══════════════════════════════════════════════════════════
   CINEMATIC ENHANCEMENTS — animations + polish
   ══════════════════════════════════════════════════════════ */

/* ── Hero animations (subtle, CSS-only) ─────────────────── */
@keyframes twinkle {

  0%,
  100% {
    opacity: .35;
  }

  50% {
    opacity: 1;
  }
}

/* dead-css sweep 2026-08: @keyframes glow-pulse deleted — its only consumer was
   the .hero__visual-art moon rule removed just below, so nothing animates it
   any more (no JS assigns it either). */

@keyframes drift-slow {
  0% {
    transform: translateX(0) translateY(0);
  }

  50% {
    transform: translateX(-12px) translateY(8px);
  }

  100% {
    transform: translateX(0) translateY(0);
  }
}

/* Twinkling stars: targets all small white circles in hero SVG art */
.hero__visual-art circle[fill="white"],
.trip-card__art circle[fill="white"] {
  animation: twinkle 4.5s ease-in-out infinite;
  transform-origin: center;
}

/* dead-css sweep 2026-08: the three twinkle-stagger rules and the moon
   glow-pulse rule were all scoped to .hero__visual-art alone, whose host was
   deleted in v21 phase J.2.4. The shared twinkle rule above still drives
   .trip-card__art, which is live. */

/* Water/horizon shimmer overlay */
.hero__bg::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse 60% 40% at 50% 110%, var(--accent-glow) 0%, transparent 60%);
  animation: drift-slow 18s ease-in-out infinite;
  pointer-events: none;
}

/* ── Card press-feedback (button :active is in the canonical .btn block above) ── */
.hotel-card:active {
  transition-duration: 50ms;
}

.trip-card:active {
  transform: translateY(-2px) scale(.995);
  transition-duration: 80ms;
}

/* v21 phase D.1: .btn--primary press-feedback ring consolidated
   into the canonical .btn block above (lines ~1175). */

/* ── Scroll reveal stagger ───────────────────────────────── */
html.js .reveal {
  opacity: 0;
  transform: translateY(28px);
  transition: opacity var(--t-slow) var(--ease-spring),
    transform var(--t-slow) var(--ease-spring);
}

html.js .reveal.visible {
  opacity: 1;
  transform: translateY(0);
}

.reveal-stagger>* {
  transition-delay: calc(var(--i, 0) * 60ms);
}

/* ── AOS-compat reveal (v22: replaces michalsnik/aos library) ──
   Mirrors the subset of AOS attributes actually used in our HTML
   (fade-up + zoom-in only — verified 191 of 191 data-aos values).
   `enhance.js#initRevealObserver` adds .visible on intersection;
   `--aos-delay` and `--aos-duration` are set per-element from
   data-aos-delay / data-aos-duration when present.

   Scoped to `html.js` so no-JS / pre-JS users see content normally
   (matches AOS's html:not(.no-js) pattern). The .js class is added
   by an inline script at the head of every page. */
html.js [data-aos] {
  opacity: 0;
  transition:
    opacity var(--aos-duration, 650ms) var(--ease-out, ease-out)
      var(--aos-delay, 0ms),
    transform var(--aos-duration, 650ms) var(--ease-spring, ease-out)
      var(--aos-delay, 0ms);
}
html.js [data-aos="fade-up"]    { transform: translateY(28px); }
html.js [data-aos="fade-left"]  { transform: translateX(28px); }
html.js [data-aos="fade-right"] { transform: translateX(-28px); }
[dir="rtl"] html.js [data-aos="fade-left"]  { transform: translateX(-28px); }
[dir="rtl"] html.js [data-aos="fade-right"] { transform: translateX(28px); }
html.js [data-aos="zoom-in"]    { transform: scale(.92); }
html.js [data-aos].visible {
  opacity: 1;
  transform: none;
}

/* ── Stat counter ─────────────────────────────────────────── */
[data-counter] {
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════
   INCLUS / NON INCLUS — comparison block per trip
   ══════════════════════════════════════════════════════════ */
.inclus-section {
  background: var(--bg);
  border-top: 1px solid var(--border);
}

.inclus-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s5);
}

.inclus-col {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s7);
  display: flex;
  flex-direction: column;
  gap: var(--s5);
  transition: border-color var(--t-fast), transform var(--t-fast);
}

.inclus-col:hover {
  border-color: var(--border-hi);
}

.inclus-col__head {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding-bottom: var(--s4);
  border-bottom: 1px solid var(--border);
}

.inclus-col__icon {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.inclus-col__icon--yes {
  background: var(--sage-light);
  color: var(--sage);
}

.inclus-col__icon--no {
  background: var(--danger-light);
  color: var(--danger);
}

.inclus-col__title {
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-weight: 400;
  color: var(--txt-1);
  line-height: 1.1;
}

.inclus-col__title em {
  font-style: normal;
  color: var(--accent-2);   /* accent em — color carries the emphasis */
}

.inclus-col__count {
  font-size: var(--fs-caption);
  font-weight: 500;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin-top: 2px;
}

.inclus-list {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
}

.inclus-item {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  font-size: var(--fs-body-sm);
  line-height: 1.55;
  color: var(--txt-2);
}

/* dup sweep 2026-08: `.inclus-item svg` deleted here — re-declared with the
   same four values (different source order) in the numbered section below. */

.inclus-item--yes svg {
  color: var(--sage);
}

.inclus-item--no svg {
  color: var(--danger);
  opacity: .7;
}

.inclus-item strong {
  color: var(--txt-1);
  font-weight: 500;
}

/* ══════════════════════════════════════════════════════════
   VOUS AIMEREZ AUSSI — cross-trip recommendations
   ══════════════════════════════════════════════════════════ */
.related-section {
  background: var(--bg-2);
}

.related-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--s5);
}

.related-card {
  display: flex;
  gap: var(--s4);
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s5);
  text-decoration: none;
  color: inherit;
  transition: transform var(--t), box-shadow var(--t), border-color var(--t);
}

.related-card:hover {
  transform: translateY(-3px);
  box-shadow: var(--elev-2);
  border-color: var(--border-hi);
}

.related-card__art {
  width: 96px;
  height: 96px;
  border-radius: var(--r2);
  flex-shrink: 0;
  overflow: hidden;
}

.related-card__art>* {
  width: 100%;
  height: 100%;
}

.related-card__body {
  display: flex;
  flex-direction: column;
  gap: var(--s2);
  flex: 1;
  min-width: 0;
}

.related-card__flag {
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--txt-3);
}

.related-card__title {
  font-family: var(--font-display);
  font-size: 1.125rem;
  font-weight: 400;
  color: var(--txt-1);
  line-height: 1.2;
}

.related-card__price {
  font-size: var(--fs-caption);
  color: var(--txt-2);
  margin-top: auto;
}

.related-card__price strong {
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body);
  font-weight: 600;
}

.related-card__cta {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-caption);
  color: var(--accent);
  margin-top: var(--s1);
}

/* ══════════════════════════════════════════════════════════
   NAV TRIP SWITCHER (dropdown on each trip page)
   ══════════════════════════════════════════════════════════ */
.trip-switcher {
  position: relative;
  display: flex;
  align-items: center;
}

.trip-switcher__trigger {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-size: var(--fs-caption);
  color: var(--txt-2);
  padding: var(--s2) var(--s3);
  border-radius: var(--r2);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast);
}

.trip-switcher__trigger:hover {
  background: var(--bg-card);
  color: var(--txt-1);
  border-color: var(--border);
}

.trip-switcher__trigger svg { color: var(--txt-3); }
/* Rotate only the disclosure chevron (last svg) on open — not the decorative
   globe icon, which used to flip upside-down because the rule wasn't scoped. */
.trip-switcher__trigger svg:last-child {
  transition: transform var(--t-base) var(--ease-spring);
}

.trip-switcher.open .trip-switcher__trigger svg:last-child {
  transform: rotate(180deg);
}

.trip-switcher__menu {
  position: absolute;
  top: calc(100% + 8px);
  right: 0;
  /* v22 follow-up #4: was a static 320px, which on a 320px viewport
     forces overflow because the menu equals the entire viewport width
     while being absolutely positioned to the right of a trigger. Clamp
     to never exceed (100vw - 32px gutter). */
  min-width: min(320px, calc(100vw - 32px));
  background: rgba(20, 22, 28, .95);
  backdrop-filter: blur(18px);
  border: 1px solid var(--border-hi);
  border-radius: var(--r3);
  padding: var(--s2);
  box-shadow: var(--elev-2);
  display: flex;
  flex-direction: column;
  gap: 2px;
  opacity: 0;
  pointer-events: none;
  transform: translateY(-8px) scale(.97);
  transform-origin: top right;
  transition: opacity var(--t-fast) ease, transform var(--t-fast) ease;
  z-index: var(--z-dropdown);
}

.trip-switcher.open .trip-switcher__menu {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0) scale(1);
}

.trip-switcher__item {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s4);
  border-radius: var(--r2);
  font-size: var(--fs-caption);
  color: var(--txt-2);
  transition: background var(--t-fast), color var(--t-fast);
}

.trip-switcher__item:hover {
  background: rgba(255, 255, 255, .05);
  color: var(--txt-1);
}

.trip-switcher__item.current {
  background: var(--accent-dim);
  color: var(--accent);
}

.trip-switcher__item-flag {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
}

.trip-switcher__item-name {
  flex: 1;
  font-weight: 500;
}

.trip-switcher__item-price {
  font-size: var(--fs-2xs);
  color: var(--txt-3);
  font-variant-numeric: tabular-nums;
}

/* ══════════════════════════════════════════════════════════
   TRIP CARD SHARE BUTTON (homepage)
   ══════════════════════════════════════════════════════════ */
/* dup sweep 2026-08: `.trip-card { position: relative }` deleted here — the
   v27 card-root block re-declares it (with isolation + overflow). */

.trip-card__share {
  position: absolute;
  /* .trip-card__from (the always-visible price chip) occupies this same
     top-right corner, top:14px + ~39px of content = bottom edge at 53px
     (desktop), or top:12px + ~49px at <=640px = bottom edge at 61px. This
     sat at top:16px/36px tall (bottom 52px) — nearly full overlap in BOTH
     cases. Invisible on desktop except mid-hover, so unnoticed; permanently
     visible at <=900px (opacity:1, 44px, "no hover on touch" below) where it
     measurably covered half the price. Dropped below the chip with clearance
     for its tallest (mobile) form. */
  top: 72px;
  right: var(--s3);
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: rgba(12, 14, 18, .75);
  backdrop-filter: blur(10px);
  border: 1px solid var(--border);
  display: grid;
  place-items: center;
  color: var(--txt-1);
  cursor: pointer;
  opacity: 0;
  transition: opacity var(--t-fast), background var(--t-fast), border-color var(--t-fast), color var(--t-fast);
  z-index: 2;
}

.trip-card:hover .trip-card__share {
  opacity: 1;
}

.trip-card__share:hover {
  background: var(--mint);
  border-color: var(--mint);
  color: #fff;
  transform: scale(1.08);
}

.trip-card__share:focus-visible {
  opacity: 1;
}

/* Toast (used by share + copy fallback) */
.toast {
  position: fixed;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%) translateY(20px);
  background: rgba(20, 22, 28, .96);
  backdrop-filter: blur(12px);
  border: 1px solid var(--border-hi);
  border-radius: var(--r4);
  padding: var(--s3) var(--s5);
  font-size: var(--fs-caption);
  color: var(--txt-1);
  display: flex;
  align-items: center;
  gap: var(--s2);
  box-shadow: var(--elev-2);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-fast) ease, transform var(--t-fast) ease;
  z-index: var(--z-toast);
}

.toast.show {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}

/* ══════════════════════════════════════════════════════════
   PRINT — clean dossier export
   ══════════════════════════════════════════════════════════ */
@media print {
  body {
    background: white !important;
    color: #111 !important;
  }

  .site-nav,
  .sticky-total,
  .booking-section,
  .final-cta,
  .hero__noise,
  .hero__faded-title,
  .related-section,
  .trip-card__share,
  .toast,
  .breakdown__ctas,
  .nav-cta,
  .nav-links,
  .hero__ctas {
    display: none !important;
  }

  .hero,
  .hero__bg,
  .hero__visual {
    background: white !important;
  }

  .hero__title,
  .hero__lede,
  .section-head__title,
  .inclus-col__title,
  .pkg-name,
  .testi-text,
  .faq-q,
  .faq-a,
  .timeline,
  .tl-title,
  .tl-activities,
  .breakdown__total-amount,
  .hotel-card__name,
  h1,
  h2,
  h3,
  h4,
  p,
  li,
  span {
    color: #111 !important;
  }

  .bg,
  .container,
  section,
  .hotel-card,
  .pkg-card,
  .inclus-col,
  .hl-card,
  .stat-card,
  .testi-card,
  .faq-item,
  .breakdown {
    background: white !important;
    border-color: #ddd !important;
    box-shadow: none !important;
    page-break-inside: avoid;
  }

  .hero__visual-art,
  .hero__bg::before,
  .hero__bg::after {
    display: none !important;
  }

  a {
    color: #111 !important;
    text-decoration: none !important;
  }

  .faq-item {
    border: 1px solid #ddd !important;
    padding: 12px;
    margin-bottom: 8px;
  }

  .faq-item .faq-a {
    max-height: none !important;
    padding: 8px 0 !important;
  }
}

/* ══════════════════════════════════════════════════════════
   RESPONSIVE additions for new components
   ══════════════════════════════════════════════════════════ */
@media (max-width: 768px) {
  .inclus-grid {
    grid-template-columns: 1fr;
  }

  .related-grid {
    /* minmax(0,…): plain 1fr floors the track at the card min-content
       (96px art + gap + longest title + padding = 315px), which overflowed
       320px viewports and clipped the card against html{overflow-x:clip}. */
    grid-template-columns: minmax(0, 1fr);
  }

  .trip-switcher__menu {
    /* v22 follow-up #3: -120px caused a 120px horizontal-scroll leak on
       iPhone SE (320px). Anchor inside the viewport with a 16px gutter,
       cap width at viewport-minus-32. The trigger anchor was the right
       edge of the navbar; we now anchor by translating left within the
       viewport instead of shifting the menu past the parent edge. */
    right: 16px;
    min-width: min(280px, calc(100vw - 32px));
  }
}

/* ══════════════════════════════════════════════════════════
   IMAGE INJECTION — local photos in placeholder wrappers
   Added by _inject_images.py · additive only · no class mods
   ══════════════════════════════════════════════════════════ */
/* v21 phase J.2.5: .hero__visual-img + .hl-card__photo dropped —
   neither is used in HTML. Real consumers (.trip-card__img,
   .hotel-card__photo) keep the shared rule. */
.trip-card__img,
.hotel-card__photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  position: absolute;
  inset: 0;
  z-index: 0;
}

/* dead-css sweep 2026-08: `.hero__visual-art { position: relative }` deleted —
   the v13 hero SVG-art host went with .hero__visual in v21 phase J.2.4. The
   sibling .trip-card__art below is the live consumer of the shared art rules. */

.trip-card__art {
  position: relative;
}

/* Soft dark vignette so light text/badges stay legible over photos */
.hero__visual-art::after,
.trip-card__art::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
      rgba(12, 14, 18, 0) 0%,
      rgba(12, 14, 18, 0) 50%,
      rgba(12, 14, 18, .55) 100%);
  pointer-events: none;
  z-index: 2;
}

.trip-card__flag,
.trip-card__from {
  z-index: 3;
}

/* v21 phase J.2.5: ~43-line duplicate IMAGE-INJECTION block deleted —
   was a verbatim copy of the proper block above, prefixed by a broken
   comment fragment ("Added by _inject_images.py …") whose opening
   `/*` had been eaten by a prior edit. The duplicate was parsing-broken
   anyway because of the corrupted comment; deleting it is pure repair. */

/* ══════════════════════════════════════════════════════════
   ALLIANCE TRAVEL BRAND SYSTEM — Token overrides applied
   Navy var(--navy) · Mint var(--mint) · DM Sans · Waypoint scale
   ══════════════════════════════════════════════════════════ */

/* ── Global focus ring ───────────────────────────────────── */
:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 2px;
  border-radius: var(--r1);
}
:focus:not(:focus-visible) { outline: none; }

/* ── Skip link ───────────────────────────────────────────── */
.skip-link {
  position: absolute;
  top: -100px;
  left: 8px;
  background: var(--mint);
  color: var(--navy);
  font-weight: 600;
  padding: var(--s2) var(--s4);
  border-radius: var(--r2);
  z-index: var(--z-toast);
  transition: top var(--t);
}
.skip-link:focus { top: 8px; }

/* v21 phase J.2.5: .nav-logo-img deleted — the SVG logo lives directly
   inside the .nav-logo anchor and uses its own size attributes. */
.site-nav { gap: var(--s5); }

/* ── Nav scrolled: navy surface ──────────────────────────── */
.site-nav.scrolled {
  background: rgba(0,44,81,0.95);
  border-bottom: 1px solid var(--border);
}

/* v21 phase D.1: .btn--primary token-driven mint+navy declaration
   consolidated into the canonical .btn block at the top of file. */

/* ── Trip cards — Waypoint border/radius ─────────────────── */
.trip-card { border-color: var(--border); border-radius: var(--r3); }
.trip-card:hover { border-color: rgba(156,232,178,0.45); }
.trip-card__flag { border-radius: var(--r1); }
.trip-card__from { border-radius: var(--r2); }

/* ── Hotel cards ─────────────────────────────────────────── */
.hotel-card { border-radius: var(--r3); border-color: var(--border); }
.hotel-card.selected { border-color: var(--mint); box-shadow: 0 0 0 1px var(--mint), var(--elev-2); }
.hotel-card__cta:hover { background: var(--mint-dim); border-color: var(--mint); color: var(--mint); }
.hotel-card.selected .hotel-card__cta { background: var(--mint-dim); border-color: var(--mint); color: var(--mint); }

/* ── Tier tabs ────────────────────────────────────────────── */
.tier-tab[aria-pressed="true"] { border-color: var(--mint); color: var(--mint); }
/* dup sweep 2026-08: `.tier-tab:hover { color: var(--txt-1) }` deleted — the
   numbered tier-tab block below re-declares the identical colour. */

/* ── Calculator ──────────────────────────────────────────── */
.date-chip.active { border-color: var(--mint); background: var(--mint-dim); color: var(--mint); }
.seg-opt.active   { background: var(--mint-dim); color: var(--mint); }
.stepper__btn:hover:not(:disabled) { border-color: var(--mint); color: var(--mint); }
.extra-toggle.checked { border-color: var(--mint); background: var(--mint-dim); }
.extra-toggle.checked .extra-toggle__check { background: var(--mint); border-color: var(--mint); }
.breakdown { border-color: var(--border); border-radius: var(--r3); }

/* ── Booking form ────────────────────────────────────────── */
.bform-block { border-color: var(--border); border-radius: var(--r3); }
.bform-field input:focus,
.bform-field select:focus,
.bform-field textarea:focus {
  border-color: var(--mint);
  box-shadow: 0 0 0 3px rgba(156,232,178,0.2);
}
.bform-preview { border-color: var(--border); border-radius: var(--r3); }

/* ── FAQ ─────────────────────────────────────────────────── */
.faq-item { border-color: var(--border); border-radius: var(--r1); }
.faq-q:hover { color: var(--mint); }

/* ── Packages ────────────────────────────────────────────── */
/* dead-css sweep 2026-08: .pkg-card / .pkg-card.recommended / .pkg-badge
   deleted — remnants of the packages component culled in v21 phase J.2. */

/* ── Inclus panel ────────────────────────────────────────── */
.inclus-col { border-color: var(--border); border-radius: var(--r3); }

/* ── Related cards ───────────────────────────────────────── */
.related-card { border-color: var(--border); border-radius: var(--r3); }
.related-card:hover { border-color: rgba(156,232,178,0.45); }

/* ── Stat / highlight cards ──────────────────────────────── */
.stat-card { border-color: var(--border); }
.hl-card { border-color: var(--border); border-radius: var(--r3); }

/* ── Footer ──────────────────────────────────────────────── */
.site-footer { background: var(--bg-2); border-color: var(--border); }
.footer-bottom { border-color: var(--border); }

/* ── Toast ────────────────────────────────────────────────── */
.toast--success { border-color: var(--mint); }
.toast--success svg { color: var(--mint); }
/* booking-form.js raises 'error' toasts from four paths (field validation,
   an unreadable upload, the incomplete-fields guard and a failed copy) via
   showToast(msg, kind) -> `toast toast--${kind}`. Only the success variant
   was ever written, so every one of those rendered with the neutral base
   style and read as a confirmation. --danger, not --danger-bg: this tints a
   border and an icon, it does not become a fill under light ink. */
.toast--error { border-color: var(--danger); }
.toast--error svg { color: var(--danger); }

/* ── Hero bg — navy accent glow ──────────────────────────── */
.hero__bg::after {
  background: radial-gradient(ellipse 80% 60% at 70% 50%, var(--accent-glow), transparent 70%);
}

/* ══════════════════════════════════════════════════════════
   SECTION HIERARCHY — logical reorder
   Calculator flows directly into Booking form (no gap).
   ══════════════════════════════════════════════════════════ */

/* The calculator and booking form share the same bg (--bg-2)
   and flow as one unified "Configure & Book" zone */
/* Two classes on purpose: `section.section` (:6931) is (0,1,1) and outranks
   the single-class form, which left 96px above the step divider against the
   40px the sibling rule below already applies underneath it. */
.calc-section.section {
  padding-bottom: var(--s7);   /* tighter bottom — booking starts right below */
}
.calc-section + .booking-section {
  padding-top: var(--s7);      /* tighter top — flows from calc */
  border-top: 1px solid var(--border);
}

/* Visual zone connector: subtle divider between step 1 and step 2 */
.calc-section + .booking-section::before {
  content: '';
  display: block;
  width: 48px;
  height: 2px;
  background: var(--mint);
  margin: 0 auto var(--s8);
  opacity: 0.6;
}

/* 2026-09-05: the `:has(+ .section-head__title)` tracking override was deleted —
   it gave eyebrows 1.1px on one section and 1.54px on the next depending on the
   following sibling's class. One value now lives on .section-head__eyebrow. */

/* ══════════════════════════════════════════════════════════
   MIGRATION v2 — Logo centered · Theme switcher · Light mode
   ══════════════════════════════════════════════════════════ */

/* ── Nav: 3-column grid (logo center, links left, cta right) ── */
.site-nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: var(--s4) var(--s7);
  gap: var(--s5);
}
.site-nav .nav-logo {
  grid-column: 2;
  justify-self: center;
}
.nav-logo svg {
  height: 52px !important;
  width: auto;
}
.site-nav .nav-links {
  grid-column: 1;
  justify-self: start;
  display: flex;
  align-items: center;
  gap: var(--s6);
}
/* v21 phase J.2.5: .nav-right deleted — was for a 3-column grid nav
   that the current flex-based nav doesn't use. */
@media (max-width: 768px) {
  .site-nav { grid-template-columns: auto 1fr auto; gap: var(--s3); padding: var(--s3) var(--s5); }
  .site-nav .nav-links { display: none; }
  .nav-logo svg { height: 40px !important; }
}

/* ── Theme toggle button ─────────────────────────────────── */
.theme-toggle {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 50%;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  color: var(--txt-1);
  cursor: pointer;
  transition: border-color var(--t), color var(--t), transform var(--t);
}
.theme-toggle:hover {
  border-color: var(--mint);
  color: var(--mint);
  transform: rotate(15deg);
}
.theme-toggle__sun { display: none; }
.theme-toggle__moon { display: block; }
[data-theme="light"] .theme-toggle__sun { display: block; }
[data-theme="light"] .theme-toggle__moon { display: none; }

/* Smooth theme transition */
html { transition: background-color var(--t-base) ease; }
body, .hero, .hero__bg, .site-nav, section, .breakdown,
.hotel-card, .trip-card, .pkg-card, .testi-card, .stat-card,
.hl-card, .faq-item, .related-card, .inclus-col, .bform-block,
.bform-preview, .value-card, .toast, .trip-switcher__menu {
  transition: background-color var(--t-base) ease, border-color var(--t-base) ease, color var(--t-base) ease;
}
@media (prefers-reduced-motion: reduce) {
  html, body, .hero, .hero__bg, .site-nav, section, .breakdown,
  .hotel-card, .trip-card, .pkg-card, .testi-card, .stat-card,
  .hl-card, .faq-item, .related-card, .inclus-col, .bform-block,
  .bform-preview, .value-card, .toast, .trip-switcher__menu {
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════════
   LIGHT MODE — component-level overrides
   (Token definitions for light mode live in the canonical :root
    block at the top of this file.)
   ══════════════════════════════════════════════════════════ */
:root[data-theme="light"] body { background: var(--bg); }

:root[data-theme="light"] .site-nav.scrolled {
  background: rgba(251,248,241,0.95);
  border-bottom: 1px solid var(--border);
}

/* Logo: swap cream fills to navy in light mode */
:root[data-theme="light"] .nav-logo svg path[fill="#efe8df"] { fill: var(--navy) !important; }

/* Make the "Travel" wordmark legible at small sizes — the original SVG
   geometry is hairline-thin so add a matching-color stroke to thicken
   the visual weight without changing the artwork. paint-order ensures
   the stroke sits behind the fill so corners stay crisp. */
.nav-logo svg path[fill="#efe8df"] {
  stroke: #efe8df;
  stroke-width: 0.8;
  paint-order: stroke fill;
}
:root[data-theme="light"] .nav-logo svg path[fill="#efe8df"] {
  stroke: var(--navy);
}

/* Hero: cream gradient instead of black */
:root[data-theme="light"] .hero__bg {
  background: linear-gradient(165deg, #fbf8f1 0%, #f5e6d6 60%, #ebd9c2 100%);
}
:root[data-theme="light"] .hero__bg::before,
:root[data-theme="light"] .hero__bg::after { opacity: 0.5; }
:root[data-theme="light"] .hero__noise { opacity: 0.015; }
/* dead-css sweep 2026-08: light-theme .hero__faded-title / .hero__visual /
   .hero__strip rules deleted — all three hosts went in v21 phase J.2.4. */

:root[data-theme="light"] .hero__visual-art::after,
:root[data-theme="light"] .trip-card__art::after {
  background: linear-gradient(180deg, rgba(0,44,81,0) 0%, rgba(0,44,81,0) 50%, rgba(0,44,81,.5) 100%);
}

/* All cards on white background in light mode */
:root[data-theme="light"] .breakdown,
:root[data-theme="light"] .hotel-card,
:root[data-theme="light"] .trip-card,
:root[data-theme="light"] .pkg-card,
:root[data-theme="light"] .testi-card,
:root[data-theme="light"] .stat-card,
:root[data-theme="light"] .hl-card,
:root[data-theme="light"] .faq-item,
:root[data-theme="light"] .related-card,
:root[data-theme="light"] .inclus-col,
:root[data-theme="light"] .bform-block,
:root[data-theme="light"] .bform-preview,
:root[data-theme="light"] .value-card,
:root[data-theme="light"] .breakdown__total {
  background: #ffffff;
  border-color: var(--border);
}

:root[data-theme="light"] .nav-cta,
:root[data-theme="light"] .btn--primary,
:root[data-theme="light"] .hotel-card__cta,
:root[data-theme="light"] .trip-sticky-bar__cta,
:root[data-theme="light"] .skip-link,
:root[data-theme="light"] .branch-flag,
:root[data-theme="light"] .trip-card__share:hover {
  /* navy on the darkened light accent measured 2.67:1 on the three added here.
     Two more join them: .branch-flag is real text ("Siege"/"Agence") on the
     homepage map, and .trip-card__share:hover is forced to navy-on-mint by an
     !important rule further down — an icon, so it fails the 3:1 bar too. This
     selector is (0,4,0) and outranks that (0,2,0) rule regardless of order. */
  color: #ffffff !important;
}
/* dead-css sweep 2026-08: light-theme .pkg-badge deleted — the packages
   component was culled in v21 phase J.2 (see the note near .highlights). */
:root[data-theme="light"] .btn--ghost {
  background: rgba(255,255,255,0.6);
  border-color: var(--border-hi);
}

:root[data-theme="light"] .bform-field input,
:root[data-theme="light"] .bform-field select,
:root[data-theme="light"] .bform-field textarea {
  background: #ffffff;
  color: var(--txt-1);
  border-color: var(--border);
}
:root[data-theme="light"] .bf-passport-entry { background: #fdfaf2; border-color: var(--border); }

:root[data-theme="light"] .home-hero__bg {
  background: radial-gradient(ellipse 90% 60% at 60% 40%, rgba(46,139,87,.12) 0%, transparent 70%),
              linear-gradient(145deg, #fbf8f1 0%, #f3ede1 60%, #ebd9c2 100%);
}
/* v21 phase E.1: .home-hero__faded watermark removed */

:root[data-theme="light"] .site-footer { background: var(--bg-2); }
:root[data-theme="light"] .toast {
  background: rgba(255,255,255,0.96);
  border-color: rgba(0,44,81,0.2);
}
:root[data-theme="light"] .trip-switcher__menu {
  background: rgba(255,255,255,0.96);
  border-color: rgba(0,44,81,0.18);
}
:root[data-theme="light"] .trip-switcher__trigger:hover { background: rgba(0,44,81,0.04); }

/* ══════════════════════════════════════════════════════════
   REGIONAL THEME — per-trip atmosphere via body[data-region]
   ══════════════════════════════════════════════════════════ */

[data-region="egypt"] .hero__bg::before {
  background-image: radial-gradient(circle at 20% 80%, rgba(201,135,46,0.18), transparent 50%),
                     radial-gradient(circle at 80% 20%, rgba(180,100,30,0.12), transparent 60%);
}

[data-region="azerbaijan"] .hero__bg::before {
  background-image: radial-gradient(circle at 50% 100%, rgba(232,93,47,0.15), transparent 50%),
                     radial-gradient(circle at 30% 30%, rgba(58,175,175,0.18), transparent 55%);
}

[data-region="istanbul"] .hero__bg::before {
  background-image: radial-gradient(circle at 70% 80%, rgba(224,112,64,0.14), transparent 55%),
                     radial-gradient(circle at 30% 30%, rgba(91,158,201,0.15), transparent 60%);
}

[data-region="malaysia"] .hero__bg::before {
  background-image: radial-gradient(circle at 50% 50%, rgba(76,175,130,0.15), transparent 60%),
                     radial-gradient(circle at 80% 20%, rgba(150,210,180,0.10), transparent 50%);
}

[data-region="sharm"] .hero__bg::before {
  background-image: radial-gradient(circle at 50% 70%, rgba(40,180,212,0.18), transparent 55%),
                     radial-gradient(circle at 70% 30%, rgba(232,138,58,0.10), transparent 60%);
}

/* Section eyebrow gets a regional accent dash */
[data-region] .section-head__eyebrow {
  position: relative;
  padding-left: 18px;
}
[data-region] .section-head__eyebrow::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 12px; height: 1px;
  background: var(--accent);
  transform: translateY(-50%);
}

/* ══════════════════════════════════════════════════════════
   FLOATING NAV — single-row pill, override grid layout
   ══════════════════════════════════════════════════════════ */

.site-nav {
  display: flex !important;
  flex-direction: row !important;
  flex-wrap: nowrap !important;
  align-items: center;
  position: fixed;
  top: 16px;
  left: clamp(16px, 3vw, 40px);
  right: clamp(16px, 3vw, 40px);
  /* The pill was 1828px wide at 1920 while the content column is 1280, so the
     logo sat 249px outside it. Cap it on the container and centre (visual audit A8). */
  max-width: calc(1280px + 2 * 40px);
  margin-inline: auto;
  height: 64px;
  padding: 0 var(--s4);
  background: rgba(0, 44, 81, 0.5);
  backdrop-filter: blur(24px) saturate(180%);
  -webkit-backdrop-filter: blur(24px) saturate(180%);
  border: 1px solid rgba(156, 232, 178, 0.16);
  border-radius: var(--r4);
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.32),
              inset 0 1px 0 rgba(255, 255, 255, 0.04);
  z-index: var(--z-nav);
  gap: var(--s3);
  grid-template-columns: none !important;
  grid-template-rows: none !important;
}

.site-nav.scrolled {
  /* Measured live: at 0.78 the fixed pill still let scrolled-under card titles
     read through clearly (not a blurred smudge, actual legible white text
     under a translucent bar) — reads as broken, not as glass. Raised until the
     backing itself is what you see. */
  background: rgba(0, 44, 81, 0.96);
  border-color: rgba(156, 232, 178, 0.22);
}

/* Logo absolute-centered in the pill */
.site-nav .nav-logo {
  position: absolute;
  left: 50%;
  top: 50%;
  transform: translate(-50%, -50%);
  grid-column: auto !important;
  grid-row: auto !important;
  justify-self: auto !important;
}
.nav-logo svg { height: 40px !important; }

/* Left side: nav-links */
.site-nav .nav-links {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-items: center;
  gap: var(--s5);
  list-style: none;
  margin: 0;
  padding: 0;
  grid-column: auto !important;
  grid-row: auto !important;
}
.site-nav .nav-links li { list-style: none; }
.site-nav .nav-links a {
  font-size: var(--fs-body-sm);
  white-space: nowrap;
  color: var(--txt-1);
  opacity: 0.85;
  transition: opacity var(--t-fast) ease, color var(--t-fast) ease;
}
.site-nav .nav-links a:hover { opacity: 1; color: var(--mint); }

/* Hover/focus underline: a hairline that wipes out from the centre. scaleX on a
   pseudo-element keeps it off the layout (no reflow, no shifting siblings) and
   transform-origin:center is direction-agnostic, so RTL needs no override. */
.site-nav .nav-links a {
  position: relative;
  padding-block: 4px;
}
.site-nav .nav-links a::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  height: 1.5px;
  border-radius: var(--r1);
  background: var(--mint);
  transform: scaleX(0);
  transform-origin: center;
  transition: transform var(--t-fast) var(--ease-out);
}
.site-nav .nav-links a:hover::after,
.site-nav .nav-links a:focus-visible::after,
.site-nav .nav-links a[aria-current]::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .site-nav .nav-links a::after { transition: none; }
}

/* Right group: first sibling among toggle/switcher/cta gets margin-left:auto */
.site-nav > .theme-toggle {
  margin-left: auto;
  grid-column: auto !important;
  grid-row: auto !important;
}
.site-nav > .trip-switcher,
.site-nav > .nav-cta {
  grid-column: auto !important;
  grid-row: auto !important;
  flex-shrink: 0;
}

.site-nav .theme-toggle {
  width: 36px;
  height: 36px;
  flex-shrink: 0;
}

.site-nav .nav-cta {
  height: 40px;
  padding: 0 var(--s4);
  font-size: var(--fs-body-sm);
  white-space: nowrap;
  display: inline-flex;
  align-items: center;
  gap: 6px;
}

.site-nav .trip-switcher__trigger {
  font-size: var(--fs-caption);
  white-space: nowrap;
  padding: 6px 10px;
  height: 36px;
}
.site-nav .trip-switcher__trigger span { white-space: nowrap; }

/* Hide "Tous les voyages" label on smaller widths to save space */
@media (max-width: 1100px) {
  .site-nav .trip-switcher__trigger > span:first-of-type { display: none; }
}

/* Mobile: collapse links, shrink everything */
@media (max-width: 768px) {
  .site-nav {
    height: 56px;
    padding: 0 var(--s3);
    gap: var(--s2);
    top: 10px;
    left: 10px;
    right: 10px;
  }
  /* Direct-child scope only. `.nav-links` is MOVED into `.nav-drawer`
     (which lives inside `.site-nav`) by initNavDrawer(); a descendant
     selector here also matches `.nav-drawer .nav-links` and only fails to
     hide it because of the `display:flex !important` at L669. Scope to the
     inline slot (`>`) to match the sibling `> .nav-cta` / `> .theme-toggle`
     rules below and the 900px block's own `.site-nav > .nav-links` hide. */
  .site-nav > .nav-links { display: none; }
  .nav-logo svg { height: 32px !important; }
  /* Direct-child only: the drawer's moved-in .nav-cta / .theme-toggle must NOT
     inherit these mobile-nav-bar shrink sizes — they render full-size inside
     the open drawer. */
  .site-nav > .nav-cta {
    height: 36px;
    padding: 0 var(--s3);
    font-size: var(--fs-caption);
  }
  .site-nav > .theme-toggle { width: 32px; height: 32px; }
  .site-nav > .theme-toggle { margin-left: auto; }
}

/* Light mode: white-tinted pill */
:root[data-theme="light"] .site-nav {
  background: rgba(255, 255, 255, 0.65);
  border-color: rgba(0, 44, 81, 0.12);
  box-shadow: 0 8px 32px rgba(0, 44, 81, 0.12),
              inset 0 1px 0 rgba(255, 255, 255, 0.5);
}
:root[data-theme="light"] .site-nav.scrolled {
  /* Same measurement as the dark rule above, which was raised 0.78 → 0.96 in
     f19e0c0. This is a different, higher-specificity selector, so that fix
     never reached light theme and it sat at 0.88 — the same "legible text
     reads through the glass" failure, just on the theme nobody re-checked.
     Mobile was already covered by its own 0.98 !important override. */
  background: rgba(255, 255, 255, 0.96);
  border-color: rgba(0, 44, 81, 0.18);
}
:root[data-theme="light"] .site-nav .nav-links a { color: var(--navy); opacity: 0.85; }
:root[data-theme="light"] .site-nav .nav-links a:hover { color: var(--mint); opacity: 1; }

/* ══════════════════════════════════════════════════════════
   v3 — Logo LEFT + visibility fixes for photo overlays
   ══════════════════════════════════════════════════════════ */

/* ── Logo on the LEFT (override centered absolute positioning) ── */
.site-nav .nav-logo {
  position: static !important;
  left: auto !important;
  top: auto !important;
  transform: none !important;
  order: 0;
  flex-shrink: 0;
}

/* Nav-links centered between logo and right-controls */
.site-nav .nav-links {
  order: 1;
  margin-inline: auto;
}

.site-nav > .theme-toggle {
  order: 2;
  margin-left: 0 !important;
}
.site-nav > .trip-switcher { order: 3; }
.site-nav > .nav-cta       { order: 4; }

/* ── Photo-overlay badges — theme-INDEPENDENT (always dark glass + light text) ── */
/* These sit on top of hotel/trip photos and must read regardless of page theme */

.trip-card__flag {
  background: rgba(12, 14, 18, 0.78) !important;
  color: rgba(255, 255, 255, 0.85) !important;
  border-color: rgba(255, 255, 255, 0.08) !important;
}

.trip-card__from {
  background: rgba(12, 14, 18, 0.85) !important;
  color: rgba(255, 255, 255, 0.7) !important;
  border-color: rgba(255, 255, 255, 0.12) !important;
}
.trip-card__from strong {
  color: #ffffff !important;
}

.hotel-card__ribbon {
  background: rgba(12, 14, 18, 0.88) !important;
  color: rgba(255, 255, 255, 0.85) !important;
}

.trip-card__share {
  background: rgba(12, 14, 18, 0.78) !important;
  color: #ffffff !important;
  border-color: rgba(255, 255, 255, 0.12) !important;
}
.trip-card__share:hover {
  background: var(--mint) !important;
  border-color: var(--mint) !important;
  color: var(--navy) !important;
}

/* dead-css sweep 2026-08: the light-theme readability overrides for
   .hero__strip / .trust-pill and for .hero__dep-card / .dep-pill were left
   behind when those families were deleted in v21 phase J.2.4 (see the notes
   near .hero__ctas). Nine !important declarations went with them. */

/* Final CTA scarcity pill — danger red on dark hero gradient */
:root[data-theme="light"] .final-cta__scarcity {
  background: rgba(185, 64, 64, 0.12) !important;
  color: var(--danger) !important;
}

/* dead-css sweep 2026-08: the light-theme .hero__faded-title override is gone
   with the watermark itself (deleted in v21 phase J.2.4). */

/* ══════════════════════════════════════════════════════════
   v3.1 — WCAG fixes (token values folded into canonical
   :root[data-theme="light"] at top of file). Component-level
   overrides below remain.
   ══════════════════════════════════════════════════════════ */

/* Section eyebrows: use brand mint (dark) in light mode regardless of per-page accent
   This gives consistent typographic hierarchy + AA contrast on cream */
:root[data-theme="light"] .section-head__eyebrow {
  color: var(--mint) !important;
}

/* Trip card "Voir ce voyage" CTA: brand mint in light mode (was using per-page accent
   which was a low-contrast gold/teal on white) */
:root[data-theme="light"] .trip-card__cta {
  color: var(--mint) !important;
}

/* Highlight card icons: use mint container instead of per-page color in light mode */
:root[data-theme="light"] .hl-card__icon {
  background: var(--mint-dim);
  color: var(--mint);
}

/* dead-css sweep 2026-08: last surviving .hero__strip .trust-pill override
   deleted — the v13 hero trust strip is gone (v21 phase J.2.4). */

/* CTA buttons: .btn--primary font-weight 600 is set in canonical .btn block.
   .nav-cta keeps its own weight bump for nav-context readability. */
.nav-cta {
  font-weight: 600;
}

/* Per-page accent text on light bg gets darkened too — applies to section heads,
   itinerary day labels, trip-card art glow, etc. Don't override the dark-mode
   dramatic accent gradients in hero — only fix readability of small text */
:root[data-theme="light"] [data-region="egypt"] .section-head__eyebrow,
:root[data-theme="light"] [data-region="azerbaijan"] .section-head__eyebrow,
:root[data-theme="light"] [data-region="istanbul"] .section-head__eyebrow,
:root[data-theme="light"] [data-region="malaysia"] .section-head__eyebrow,
:root[data-theme="light"] [data-region="sharm"] .section-head__eyebrow {
  color: var(--mint) !important;
}

/* ══════════════════════════════════════════════════════════
   v4 — Algeria map · Travel animations · Hero paper plane
   ══════════════════════════════════════════════════════════ */

/* ── Algeria map section ─────────────────────────────────── */
.algeria-section {
  position: relative;
  background: var(--bg);
  overflow: hidden;
  border-top: 1px solid var(--border);
}
.algeria-section::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse at 30% 20%, var(--mint-glow), transparent 50%),
    radial-gradient(ellipse at 80% 70%, rgba(0,44,81,.15), transparent 60%);
  pointer-events: none;
}

/* dead-css sweep 2026-08: .algeria-map-wrap deleted — 921b4f4 dropped the
   wrapper element around #algeria-map when the agences bento landed; the map
   container is now a direct child of the bento cell. */

/* dead-css sweep 2026-08: the whole .branch-card family (.branch-card,
   :hover, --hq, --hq::before, header, h3, a[href^="tel:"], .branch-addr,
   .branch-phones and @keyframes card-pulse) is deleted. 921b4f4 replaced that
   markup with .branches-bento in site/index.html, leaving these rules with no
   host element. .branch-list, .branch-flag and .branch-flag--alt below are
   STILL IN USE by the bento — do not remove those. */

/* Branch cards grid */
.branch-list {
  display: grid;
  /* min(240px,100%) so a narrow container (contact card) can't be forced wider
     than the viewport — was causing sideways page scroll ~1025–1146px. */
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: var(--s4);
  margin-top: var(--s7);
  min-width: 0;
}
.contact-card { min-width: 0; }
.branch-flag {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .12em;
  padding: 3px 9px;
  border-radius: var(--r1);
  background: var(--mint);
  color: var(--navy);
}
.branch-flag--alt {
  background: var(--bg-card);
  border: 1px solid var(--border);
  color: var(--txt-3);
}

/* v21 phase J.2: .hero__plane orphan + @keyframes plane-arc deleted.
   The paper-plane mascot survey-tagged for keeping had its HTML host
   removed in an earlier session; only the CSS animation hung around
   with no element to animate. ~38 lines deleted (selector + keyframe
   + ::after trail). */

/* v21-phase-C: tilt-bob culled — related-card icon stays still on hover.
   Decoration that competed with the lift+shadow already on the parent card. */

.hl-card:hover .hl-card__icon {
  transform: rotate(-6deg) scale(1.05);
}

.bform-block__title svg { transition: transform var(--t-fast) ease; }
.bform-block:hover .bform-block__title svg { transform: rotate(-8deg); }

/* Responsive */
@media (max-width: 768px) {
  .branch-list { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
  .branch-card--hq::before,
  .hl-card:hover .hl-card__icon {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}

/* dead-css sweep 2026-08: light-mode .branch-card / .branch-card--hq overrides
   deleted along with the base component (see the note above .branch-list). */

/* ══════════════════════════════════════════════════════════
   v5 — Per-region atmospheric backgrounds
   Body patterns + hero decorative silhouettes per destination
   ══════════════════════════════════════════════════════════ */

/* ── Body pattern overlay (subtle, fixed, doesn't scroll) ──── */
body[data-region]::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image: var(--region-pattern);
  background-size: var(--region-pattern-size, 240px);
  background-position: center;
  background-repeat: repeat;
  opacity: var(--region-pattern-opacity, 0.06);
  pointer-events: none;
  z-index: 0;
  mix-blend-mode: screen;
}

/* Light mode uses overlay blend instead of screen */
:root[data-theme="light"] body[data-region]::before {
  mix-blend-mode: multiply;
  opacity: var(--region-pattern-opacity-light, 0.08);
}

/* ══════════════════════════════════════════════════════════
   EGYPT — sand-gold hieroglyph chevrons
   ══════════════════════════════════════════════════════════ */
[data-region="egypt"] {
  --region-pattern-size: 200px;
  --region-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><g fill='none' stroke='%23C9872E' stroke-width='0.6' opacity='0.9'><path d='M0 100 L20 80 L40 100 L60 80 L80 100 L100 80 L120 100 L140 80 L160 100 L180 80 L200 100'/><path d='M0 130 L20 110 L40 130 L60 110 L80 130 L100 110 L120 130 L140 110 L160 130 L180 110 L200 130'/><circle cx='100' cy='40' r='10'/><line x1='100' y1='25' x2='100' y2='35'/><line x1='100' y1='45' x2='100' y2='55'/><line x1='85' y1='40' x2='95' y2='40'/><line x1='105' y1='40' x2='115' y2='40'/><path d='M100 165 L110 175 L100 185 L90 175 Z' /></g></svg>");
}

[data-region="egypt"] .hero__bg::after {
  background: radial-gradient(ellipse 80% 60% at 70% 50%, rgba(201,135,46,0.28), transparent 70%),
              radial-gradient(circle at 20% 100%, rgba(140,80,30,0.4), transparent 50%);
}

/* ══════════════════════════════════════════════════════════
   AZERBAIJAN — Caspian flame & geometric rug
   ══════════════════════════════════════════════════════════ */
[data-region="azerbaijan"] {
  --region-pattern-size: 220px;
  --region-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 220 220'><g fill='none' stroke='%233AAFAF' stroke-width='0.7' opacity='0.9'><path d='M110 30 Q 120 60 110 90 Q 100 60 110 30 Z' fill='%23E85D2F' fill-opacity='0.08' stroke='%23E85D2F'/><path d='M40 130 L60 110 L80 130 L100 110 L120 130 L140 110 L160 130 L180 110' /><circle cx='110' cy='180' r='14'/><circle cx='110' cy='180' r='6'/><path d='M30 30 L50 50 M30 50 L50 30 M170 30 L190 50 M170 50 L190 30'/></g></svg>");
}

[data-region="azerbaijan"] .hero__bg::after {
  background: radial-gradient(ellipse 80% 60% at 50% 100%, rgba(232,93,47,0.22), transparent 60%),
              radial-gradient(ellipse 70% 50% at 30% 30%, rgba(58,175,175,0.25), transparent 65%);
}

/* ══════════════════════════════════════════════════════════
   ISTANBUL — Ottoman 8-point star tile
   ══════════════════════════════════════════════════════════ */
[data-region="istanbul"] {
  --region-pattern-size: 180px;
  --region-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'><g fill='none' stroke='%2370b8e0' stroke-width='0.7' opacity='0.9'><path d='M90 30 L110 70 L150 70 L120 100 L130 140 L90 120 L50 140 L60 100 L30 70 L70 70 Z'/><circle cx='90' cy='90' r='12'/><circle cx='90' cy='90' r='4'/></g></svg>");
}

[data-region="istanbul"] .hero__bg::after {
  background: radial-gradient(ellipse 70% 60% at 70% 80%, rgba(224,112,64,0.20), transparent 60%),
              radial-gradient(ellipse 60% 50% at 30% 30%, rgba(112,184,224,0.20), transparent 65%);
}

/* ══════════════════════════════════════════════════════════
   MALAYSIA — Tropical leaf batik
   ══════════════════════════════════════════════════════════ */
[data-region="malaysia"] {
  --region-pattern-size: 200px;
  --region-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 200 200'><g fill='none' stroke='%234CAF82' stroke-width='0.7' opacity='0.9'><path d='M100 30 Q 130 60 130 100 Q 130 140 100 170 Q 70 140 70 100 Q 70 60 100 30 Z'/><line x1='100' y1='30' x2='100' y2='170'/><path d='M100 50 L120 65 M100 70 L125 85 M100 90 L128 105 M100 110 L125 125 M100 130 L120 145 M100 150 L115 160'/><path d='M100 50 L80 65 M100 70 L75 85 M100 90 L72 105 M100 110 L75 125 M100 130 L80 145 M100 150 L85 160'/><circle cx='30' cy='30' r='3' fill='%234CAF82' opacity='0.4'/><circle cx='170' cy='170' r='3' fill='%234CAF82' opacity='0.4'/></g></svg>");
}

[data-region="malaysia"] .hero__bg::after {
  background: radial-gradient(ellipse 70% 60% at 50% 50%, rgba(76,175,130,0.22), transparent 65%),
              radial-gradient(ellipse 50% 40% at 80% 20%, rgba(150,210,180,0.18), transparent 60%);
}

/* ══════════════════════════════════════════════════════════
   SHARM — Coral wave & bubble
   ══════════════════════════════════════════════════════════ */
[data-region="sharm"] {
  --region-pattern-size: 180px;
  --region-pattern: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 180 180'><g fill='none' stroke='%2328B4D4' stroke-width='0.7' opacity='0.9'><path d='M0 60 Q 30 30 60 60 T 120 60 T 180 60'/><path d='M0 120 Q 30 90 60 120 T 120 120 T 180 120'/><circle cx='40' cy='30' r='3'/><circle cx='100' cy='25' r='2'/><circle cx='150' cy='35' r='4'/><circle cx='30' cy='150' r='2'/><circle cx='80' cy='160' r='3'/><circle cx='140' cy='150' r='2'/></g></svg>");
}

[data-region="sharm"] .hero__bg::after {
  background: radial-gradient(ellipse 70% 60% at 50% 70%, rgba(40,180,212,0.25), transparent 60%),
              radial-gradient(ellipse 50% 40% at 70% 30%, rgba(232,138,58,0.15), transparent 60%);
}

/* ══════════════════════════════════════════════════════════
   HOMEPAGE — global travel constellation
   ══════════════════════════════════════════════════════════ */
body:not([data-region])::before {
  content: '';
  position: fixed;
  inset: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 300 300'><g fill='%239ce8b2' opacity='0.6'><circle cx='30' cy='40' r='1'/><circle cx='80' cy='25' r='1.5'/><circle cx='150' cy='50' r='1'/><circle cx='220' cy='30' r='1.2'/><circle cx='270' cy='60' r='1'/><circle cx='50' cy='110' r='1.3'/><circle cx='130' cy='140' r='1'/><circle cx='200' cy='120' r='1.1'/><circle cx='260' cy='160' r='1.4'/><circle cx='40' cy='200' r='1'/><circle cx='110' cy='220' r='1.2'/><circle cx='180' cy='250' r='1'/><circle cx='250' cy='240' r='1.3'/><circle cx='90' cy='280' r='1'/></g><g fill='none' stroke='%239ce8b2' stroke-width='0.3' opacity='0.25'><path d='M30 40 L80 25 L150 50' /><path d='M150 50 L220 30 L270 60'/><path d='M50 110 L130 140 L200 120 L260 160'/><path d='M40 200 L110 220 L180 250 L250 240'/></g></svg>");
  background-size: 360px;
  background-repeat: repeat;
  opacity: 0.06;
  pointer-events: none;
  z-index: 0;
  mix-blend-mode: screen;
}

:root[data-theme="light"] body:not([data-region])::before {
  mix-blend-mode: multiply;
  opacity: 0.10;
}

/* Make sure body content sits above the pattern overlay (do NOT touch .site-nav — it must stay z-index 100 fixed) */
main, footer, section, .home-hero { position: relative; z-index: 1; }

/* ══════════════════════════════════════════════════════════
   v5.2 — Real photographic backgrounds (full-bleed hero atmospheres)
   The destination photo becomes the hero's full backdrop
   with strong dark-side gradient so text stays readable.
   ══════════════════════════════════════════════════════════ */

/* Generic full-bleed hero photo backdrop layer */
.hero {
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
}

/* Stronger left-side darken so the headline reads cleanly over the photo */
.hero__bg {
  background:
    linear-gradient(90deg, rgba(0,0,0,.75) 0%, rgba(0,0,0,.55) 35%, rgba(0,0,0,.25) 65%, rgba(0,0,0,.15) 100%),
    var(--hero-gradient, linear-gradient(135deg,#1a1208 0%,#0a0c12 60%,#0c1420 100%));
}

/* Per-region hero photo backdrops with WebP-first via image-set().
   Browsers that support WebP pick it; the rest fall back to JPG.
   Mobile media query swaps to a smaller crop for a ~70% byte reduction.
   Paths are relative to this CSS file (site/assets/css/styles.css):
     ../images/heroes/* -> site/assets/images/heroes/* */

/* Mobile (<=768px): use the smaller cropped variants — ~70% smaller files */

/* Override .hero__bg per region: keep the per-region tinted gradient
   AND the photo behind it. The pseudo-elements remain for atmosphere */
[data-region] .hero__bg {
  background:
    linear-gradient(95deg,
      rgba(0,0,0,.85) 0%,
      rgba(0,0,0,.65) 30%,
      rgba(0,0,0,.30) 60%,
      rgba(0,0,0,.10) 100%);
}

/* Light mode: invert overlay so cream text shows */
:root[data-theme="light"] [data-region] .hero__bg {
  background:
    linear-gradient(95deg,
      rgba(251,248,241,.85) 0%,
      rgba(251,248,241,.65) 30%,
      rgba(251,248,241,.30) 60%,
      rgba(251,248,241,.10) 100%);
}

/* ══════════════════════════════════════════════════════════
   HOMEPAGE — atmospheric photo collage backdrop
   ══════════════════════════════════════════════════════════ */
.home-hero {
  position: relative;
  isolation: isolate;
}

.home-hero__photos {
  position: absolute;
  inset: 0;
  z-index: -1;
  overflow: hidden;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
}

.home-hero__photos img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: saturate(0.85) brightness(0.55);
  opacity: 0.55;
  transition: opacity var(--t-slow) ease, filter var(--t-slow) ease;
  animation: photo-fade 12s ease-in-out infinite;
}

/* Staggered so the five tiles cross-fade out of phase. Selected through
   :nth-child on the PICTURE, not the img: every tile is wrapped in <picture>,
   so each <img> is the last child of its own wrapper and never the 1st-5th
   child of .home-hero__photos — these five rules had quietly stopped matching
   anything and all five tiles faded in unison. The sibling rule above already
   selects `picture:nth-child(n+3)`, which is the shape that still works. */
.home-hero__photos picture:nth-child(1) img { animation-delay: 0s; }
.home-hero__photos picture:nth-child(2) img { animation-delay: -2.4s; }
.home-hero__photos picture:nth-child(3) img { animation-delay: -4.8s; }
.home-hero__photos picture:nth-child(4) img { animation-delay: -7.2s; }
.home-hero__photos picture:nth-child(5) img { animation-delay: -9.6s; }

/* Lazy-tile placeholder fill (tiles 2-5). The 1x1 SVG src paints nothing,
   so without this dark background the parent collage bleeds through until
   hero-collage-lazy.js swaps the real srcset in after window.load + idle. */
.home-hero__photos picture[data-lazy-hero] > img {
  background: #111;
}

@keyframes photo-fade {
  0%, 100% { opacity: 0.35; transform: scale(1.0); }
  50%      { opacity: 0.7;  transform: scale(1.04); }
}

/* Heavy overlay on the photo strip so text stays readable */
.home-hero__photos::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, rgba(10,8,5,.65) 0%, rgba(10,8,5,.55) 50%, rgba(10,8,5,.85) 100%),
    radial-gradient(ellipse at 60% 40%, transparent 30%, rgba(10,8,5,.45) 80%);
  pointer-events: none;
}

/* The original gradient .home-hero__bg should layer ABOVE the photos
   to maintain the warm bronze atmosphere */
.home-hero__bg {
  z-index: -1;
  mix-blend-mode: multiply;
  opacity: 0.85;
}

/* Light mode: photos lighten and desaturate further. The `opacity` here is
   inert — photo-fade animates opacity on the same element, and an animation
   outranks a normal declaration — so the extra dimming goes on the CONTAINER,
   where it multiplies with the animated value: 0.35 x 0.45 = 0.16. At the old
   effective 0.35 the two tiles behind the H1 stayed present enough to meet in
   a hard vertical seam under the lede (visual audit B5). */
:root[data-theme="light"] .home-hero__photos {
  opacity: 0.45;
}
:root[data-theme="light"] .home-hero__photos img {
  filter: saturate(0.55) brightness(1.08);
}
:root[data-theme="light"] .home-hero__photos::after {
  background:
    linear-gradient(180deg, rgba(251,248,241,.55) 0%, rgba(251,248,241,.4) 50%, rgba(251,248,241,.7) 100%);
}

/* Mobile: stack into 2 columns + reduce intensity */
@media (max-width: 768px) {
  .home-hero__photos {
    grid-template-columns: repeat(2, 1fr);
    grid-template-rows: repeat(3, 1fr);
  }
  .home-hero__photos img:nth-child(5) { display: none; }
  [data-region] .hero {
    background-position: 70% center;  /* keep subject visible on narrow screens */
  }
}

@media (prefers-reduced-motion: reduce) {
  .home-hero__photos img { animation: none !important; }
}

/* Reinforce nav layering — explicit override against v5 sibling rules */
.site-nav { z-index: var(--z-nav) !important; }

/* ══════════════════════════════════════════════════════════
   v6 — Professional motion polish layer
   Cinematic hero parallax, magnetic CTAs, premium reveals,
   spring-curve micro-interactions, scroll progress bar.
   Designed to layer on top of v5.2 without changing identity.
   ══════════════════════════════════════════════════════════ */

/* ---- 6.0 — Motion tokens folded into canonical :root at top of file ---- */

/* ---- 6.1 — Ken Burns hero removed (2026-06-12): selector
   `[data-region] .hero` matched no element (trip pages use .scroll-hero),
   and the keyframes animated background-size/position (paint-storm if it
   ever matched). Dead code deleted. ---- */

.hero__bg {
  transform: translate3d(0, calc(var(--scroll-y, 0) * 0.18px), 0);
  /* will-change removed (v22): the scroll handler re-applies the transform
     every frame while scrolling, so the compositor layer is created on-demand
     and torn down when scroll settles — keeping it permanent leaks GPU memory. */
}
[data-region] .hero {
  background-attachment: scroll;
}

[data-region] .hero::after {
  content: "";
  position: absolute; inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse 70% 80% at 30% 50%, transparent 30%, rgba(0,0,0,.45) 95%);
  opacity: .55;
  z-index: 1;
  mix-blend-mode: multiply;
}
:root[data-theme="light"] [data-region] .hero::after {
  background: radial-gradient(ellipse 70% 80% at 30% 50%, transparent 35%, rgba(255,255,255,.55) 95%);
  mix-blend-mode: screen;
}
.hero__inner, .hero__content { position: relative; z-index: 3; }

.home-hero__photos img {
  /* photo-fade is an infinite keyframe animation — layer must stay composited.
     Gated below ≤640px (collage limited to 2 visible photos per perf-gate). */
  will-change: transform, opacity;
  transform-origin: center;
}

/* ---- 6.2 — Premium scroll-reveal classes ---- */
[data-fx] {
  opacity: 0;
  transition:
    opacity var(--t-cinema) var(--ease-spring),
    transform var(--t-cinema) var(--ease-spring),
    filter   var(--t-cinema) var(--ease-spring);
  /* will-change removed (v22): one-time entrance fires once on intersection.
     The browser composites the transform on-demand when the transition runs. */
}
[data-fx="up"]      { transform: translate3d(0, 32px, 0); }
[data-fx="down"]    { transform: translate3d(0, -28px, 0); }
[data-fx="left"]    { transform: translate3d(-40px, 0, 0); }
[data-fx="right"]   { transform: translate3d(40px, 0, 0); }
[data-fx="zoom"]    { transform: scale(.94); }
[data-fx="blur"]    { filter: blur(8px); transform: translate3d(0, 16px, 0); }
[data-fx="rise"]    { transform: translate3d(0, 60px, 0) scale(.97); }
[data-fx="reveal"]  { clip-path: inset(0 0 100% 0); transform: none; opacity: 1; }

[data-fx].is-in {
  opacity: 1;
  transform: none;
  filter: none;
  clip-path: inset(0 0 0 0);
}

[data-fx-stagger] > * {
  opacity: 0;
  transform: translate3d(0, 24px, 0);
  transition:
    opacity var(--t-slow) var(--ease-spring),
    transform var(--t-slow) var(--ease-spring);
  transition-delay: calc(var(--d, 0) * 70ms);
  /* will-change removed (v22): one-time stagger entrance — layer per child
     would multiply mobile compositor pressure linearly with list length. */
}
[data-fx-stagger].is-in > * {
  opacity: 1;
  transform: none;
}

/* ---- 6.3 — Magnetic buttons ---- */
.btn,
.nav-cta,
a.btn--primary,
a.btn--ghost,
.calc-cta {
  --mx: 0px;
  --my: 0px;
  transform: translate3d(var(--mx), var(--my), 0);
  transition:
    transform var(--t-fast) var(--ease-spring-soft),
    background var(--t-fast) var(--ease-snap),
    color var(--t-fast) var(--ease-snap),
    box-shadow var(--t-base) var(--ease-spring),
    border-color var(--t-fast) var(--ease-snap);
}
/* will-change only during hover/focus — the magnet effect runs JS rAF
   updates of --mx/--my while pointer is over the button. Outside hover,
   transform never changes so no compositor layer needed (v22). */
.btn:hover, .btn:focus-visible,
.nav-cta:hover, .nav-cta:focus-visible,
a.btn--primary:hover, a.btn--primary:focus-visible,
a.btn--ghost:hover, a.btn--ghost:focus-visible,
.calc-cta:hover, .calc-cta:focus-visible {
  will-change: transform;
}
.btn--primary {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn--primary::before {
  content: "";
  position: absolute;
  inset: -2px;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 50%),
              rgba(255,255,255,.35) 0%, transparent 45%);
  opacity: 0;
  transition: opacity var(--t-base) var(--ease-snap);
  pointer-events: none;
  z-index: -1;
}
.btn--primary:hover::before { opacity: 1; }
.btn--primary:hover {
  box-shadow: 0 14px 30px -12px rgba(156, 232, 178, .35),
              0 0 0 1px rgba(156, 232, 178, .25) inset;
}

/* ---- 6.4 — Cards: spring-feel hover ---- */
.trip-card,
.hotel-card,
.value-card,
.branch-card,
.faq__item {
  transition:
    transform var(--t-base) var(--ease-spring-soft),
    box-shadow var(--t-base) var(--ease-spring),
    border-color var(--t-fast) var(--ease-snap),
    background var(--t-fast) var(--ease-snap);
  cursor: pointer;
}
.trip-card:hover,
.hotel-card:hover,
.value-card:hover,
.branch-card:hover {
  transform: translate3d(0, -6px, 0);
  /* will-change scoped to hover: layer created on enter, dropped on leave
     so 12+ cards in a grid don't sit as permanent compositor layers (v22). */
  will-change: transform;
  box-shadow: 0 28px 50px -22px rgba(0, 0, 0, .55),
              0 0 0 1px rgba(156, 232, 178, .12);
}
:root[data-theme="light"] .trip-card:hover,
:root[data-theme="light"] .hotel-card:hover,
:root[data-theme="light"] .value-card:hover,
:root[data-theme="light"] .branch-card:hover {
  box-shadow: 0 24px 44px -22px rgba(0, 44, 81, .25),
              0 0 0 1px rgba(35, 122, 74, .18);
}

/* dup sweep 2026-08: `.trip-card__hero { overflow: hidden }` deleted — the v27
   "Image fill behind everything" rule re-declares it identically. */
.trip-card__art,
.trip-card img {
  transition: transform 1.2s var(--ease-spring);
}
.trip-card:hover .trip-card__art,
.trip-card:hover img {
  transform: scale(1.06);
  /* layer scoped to parent :hover — created on enter, freed on leave (v22) */
  will-change: transform;
}

/* dup sweep 2026-08: `.trip-card { position: relative; isolation: isolate }`
   deleted — the v27 card-root block re-declares both, same values. */
.trip-card::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: linear-gradient(90deg, transparent, var(--accent, var(--mint)), transparent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-slow) var(--ease-spring);
  z-index: 2;
  pointer-events: none;
}
/* dup sweep 2026-08: `.trip-card:hover::after { transform: scaleX(1) }` deleted
   — re-declared identically in the v27 card block. */

/* ---- 6.5 — Section reveal ---- */
section { scroll-margin-top: 90px; }

.section-head .section-head__eyebrow,
.section-head h2,
.section-head__title {
  opacity: 0;
  transform: translate3d(0, 20px, 0);
  transition:
    opacity var(--t-cinema) var(--ease-spring),
    transform var(--t-cinema) var(--ease-spring);
  /* will-change removed (v22): one-time entrance from observer.
     Permanent layer on every section header inflates mobile GPU. */
}
.section-head.is-in .section-head__eyebrow { opacity: 1; transform: none; transition-delay: 0ms; }
.section-head.is-in h2,
.section-head.is-in .section-head__title { opacity: 1; transform: none; transition-delay: 120ms; }

/* ---- 6.6 — Scroll progress bar ---- */
.scroll-progress {
  position: fixed;
  top: 0; left: 0;
  height: 2px;
  width: 100%;
  z-index: var(--z-sticky);
  pointer-events: none;
  background: transparent;
}
.scroll-progress__fill {
  height: 100%;
  width: var(--p, 0%);
  background: linear-gradient(90deg,
    rgba(156, 232, 178, 0) 0%,
    var(--mint) 30%,
    var(--mint) 70%,
    rgba(156, 232, 178, 0) 100%);
  transform-origin: left;
  transition: width 80ms linear;
  box-shadow: 0 0 12px var(--mint);
}
:root[data-theme="light"] .scroll-progress__fill {
  background: linear-gradient(90deg, transparent, #237a4a 30%, #237a4a 70%, transparent);
  box-shadow: 0 0 8px rgba(35, 122, 74, .5);
}

/* ---- 6.7 — Floating quick-WhatsApp ----
   v21 prod-prep: rewritten to comply with Performance Contract §0a item 1
   (GPU props only — no animated box-shadow). The "glow" pulse now lives
   on a ::before pseudo-element that scales + fades — pure compositor work,
   no paint cost per frame. Edge spacing bumped to 24px so the shadow
   no longer clips against the viewport corner. */
.fab-whatsapp {
  position: fixed;
  right: 24px;
  bottom: 24px;
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--wa-green);
  color: #fff;
  display: grid;
  place-items: center;
  z-index: var(--z-fab);
  /* Static shadow only — not animated. Tighter than before so it fits
     within the 24px breathing room without clipping at the viewport edge. */
  box-shadow: 0 6px 16px -2px rgba(37, 211, 102, .45),
              0 2px 8px rgba(0, 0, 0, .25);
  transition: transform var(--t-base) var(--ease-spring),
              box-shadow var(--t-base) var(--ease-out);
  text-decoration: none;
  opacity: 0;
  transform: translate3d(0, 14px, 0) scale(.85);
  pointer-events: none;
}
/* GPU-only pulse ring — scales + fades via transform + opacity */
.fab-whatsapp::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: var(--wa-green);
  opacity: 0;
  pointer-events: none;
  z-index: -1;
  animation: fab-pulse 2.6s ease-out infinite;
  will-change: transform, opacity;
}
.fab-whatsapp.is-visible {
  opacity: 1;
  transform: translate3d(0, 0, 0) scale(1);
  pointer-events: auto;
}
.fab-whatsapp:hover {
  transform: translate3d(0, -3px, 0) scale(1.07);
  box-shadow: 0 10px 22px -4px rgba(37, 211, 102, .55),
              0 4px 12px rgba(0, 0, 0, .3);
}
.fab-whatsapp svg { width: 26px; height: 26px; position: relative; z-index: 1; }

/* Pause the pulse when the FAB itself is hidden (saves ~60 RAF/sec) */
.fab-whatsapp:not(.is-visible)::before { animation: none; }

@keyframes fab-pulse {
  0%   { transform: scale(1);   opacity: .55; }
  100% { transform: scale(1.6); opacity: 0;   }
}

/* ---- 6.8 — Micro-interactions ---- */
.nav-links a {
  position: relative;
  transition: color var(--t-fast) var(--ease-snap);
}
.nav-links a::after {
  content: "";
  position: absolute;
  left: 0; bottom: -4px;
  width: 100%;
  height: 1.5px;
  background: var(--mint);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--t-base) var(--ease-spring);
}
.nav-links a:hover::after,
.nav-links a:focus-visible::after {
  transform: scaleX(1);
  transform-origin: left;
}

.trip-tag,
.tag {
  transition: background var(--t-fast) var(--ease-snap), transform var(--t-fast) var(--ease-spring-soft);
}
.trip-tag:hover { transform: translateY(-1px); }

/* ---- 6.9 — Counter punch on reveal ---- */
@keyframes counter-punch {
  0%   { transform: scale(.85); }
  60%  { transform: scale(1.08); }
  100% { transform: scale(1); }
}
[data-counter].is-in {
  animation: counter-punch var(--t-cinema) var(--ease-spring-soft) both;
  display: inline-block;
}

/* ---- 6.10 — Improved focus rings ---- */
.btn:focus-visible,
.nav-cta:focus-visible,
.theme-toggle:focus-visible,
.trip-card:focus-visible,
.nav-links a:focus-visible,
.fab-whatsapp:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible {
  outline: 2px solid var(--mint);
  outline-offset: 3px;
  border-radius: var(--r2, 8px);
}

/* ---- 6.11 — Cursor pointer ---- */
.trip-card,
.hotel-card,
.value-card,
.branch-card,
.faq__item summary,
.theme-toggle,
.nav-hamburger,
.trip-card__share,
[role="button"] {
  cursor: pointer;
}

/* ---- 6.12 — Image-load fade-in ---- */
img.fx-img {
  opacity: 0;
  transform: scale(1.02);
  transition: opacity var(--t-slow) var(--ease-spring), transform 1.2s var(--ease-spring);
}
img.fx-img.loaded {
  opacity: 1;
  transform: scale(1);
}

/* ---- 6.13 — Section dividers ---- */
section + section {
  position: relative;
}
section + section::before {
  content: "";
  position: absolute;
  top: 0;
  left: 50%;
  width: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--border), transparent);
  transform: translateX(-50%);
  transition: width 1.4s var(--ease-spring);
  pointer-events: none;
}
section + section.is-in::before { width: 60%; }

/* ---- 6.14 — Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  [data-region] .hero { animation: none !important; }
  .home-hero__photos img { animation: none !important; }
  [data-fx], [data-fx-stagger] > *, .section-head .section-head__eyebrow,
  .section-head h2, .section-head__title {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    clip-path: none !important;
    transition: none !important;
  }
  .fab-whatsapp { animation: none !important; }
  section + section::before { transition: none !important; width: 60% !important; }
  .btn, .nav-cta, .trip-card, .hotel-card, .value-card, .branch-card {
    transform: none !important;
    transition: none !important;
  }
  .scroll-progress__fill { transition: none !important; }
}

/* ---- 6.15 — Mobile tweaks ---- */
@media (max-width: 640px) {
  [data-region] .hero {
    animation-duration: 36s;
    background-size: cover;
  }
  .fab-whatsapp { width: 50px; height: 50px; right: 14px; bottom: 14px; }
  .fab-whatsapp svg { width: 22px; height: 22px; }
}

/* ══════════════════════════════════════════════════════════
   v7 — Industry-pattern polish layer
   Synthesized from 20 leading travel sites:
   sticky inquiry bar, trust strip, press logos, lightbox,
   accordion itinerary, soft-urgency badges, FAB tooltip,
   premium destination cards, scroll-snap testimonials.
   ══════════════════════════════════════════════════════════ */

/* ---- 7.1 — Trust strip (just below hero) ---- */
.trust-strip {
  position: relative;
  z-index: 4;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(12px, 2vw, 36px);
  padding: 18px clamp(16px, 4vw, 40px);
  background: rgba(12, 14, 18, 0.55);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-top: 1px solid rgba(255, 255, 255, 0.06);
  border-bottom: 1px solid rgba(255, 255, 255, 0.06);
  font-size: var(--fs-caption);
  color: var(--txt-2, #c9cdd4);
  letter-spacing: 0.01em;
  margin-top: -1px;
}
:root[data-theme="light"] .trust-strip {
  background: rgba(251, 248, 241, 0.85);
  border-color: rgba(0, 44, 81, 0.08);
  color: var(--txt-2);
}
.trust-strip__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  white-space: nowrap;
}
.trust-strip__item svg {
  flex-shrink: 0;
  color: var(--mint, var(--mint));
}
.trust-strip__item strong {
  color: var(--txt-1);
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.trust-strip__sep {
  width: 1px;
  height: 18px;
  background: rgba(255, 255, 255, 0.12);
  display: none;
}
@media (min-width: 720px) {
  .trust-strip__sep { display: block; }
}
:root[data-theme="light"] .trust-strip__sep {
  background: rgba(0, 44, 81, 0.15);
}

/* ---- 7.2 — Sticky inquiry bar (trip pages, slides in after hero) ---- */
.trip-sticky-bar {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: var(--z-sticky);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 10px clamp(16px, 4vw, 32px);
  background: rgba(12, 14, 18, 0.92);
  backdrop-filter: blur(20px) saturate(160%);
  -webkit-backdrop-filter: blur(20px) saturate(160%);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  transform: translateY(-100%);
  transition: transform var(--t-base) var(--ease-spring);
  pointer-events: none;
  box-shadow: 0 8px 32px rgba(0, 0, 0, 0.25);
}
.trip-sticky-bar.is-visible {
  transform: translateY(0);
  pointer-events: auto;
}
:root[data-theme="light"] .trip-sticky-bar {
  background: rgba(251, 248, 241, 0.96);
  border-color: rgba(0, 44, 81, 0.10);
}
.trip-sticky-bar__info {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
  flex: 1;
}
.trip-sticky-bar__name {
  font-weight: 600;
  font-size: var(--fs-body-sm);
  color: var(--txt-1);
  line-height: 1.2;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.trip-sticky-bar__meta {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  letter-spacing: 0.02em;
}
.trip-sticky-bar__price {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  line-height: 1.1;
  text-align: end;
}
.trip-sticky-bar__price-from {
  font-size: var(--fs-2xs);
  color: var(--txt-3);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.trip-sticky-bar__price-num {
  font-weight: 700;
  font-size: 1.05rem;
  color: var(--mint);
  font-variant-numeric: tabular-nums;
}
.trip-sticky-bar__cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 18px;
  background: var(--mint);
  color: var(--navy, var(--navy));
  font-weight: 600;
  font-size: var(--fs-body-sm);
  border-radius: var(--r4);
  text-decoration: none;
  white-space: nowrap;
  transition: transform var(--t-fast) var(--ease-spring), box-shadow var(--t-fast) ease;
  box-shadow: 0 6px 16px -4px rgba(156, 232, 178, 0.45);
}
.trip-sticky-bar__cta:hover {
  transform: translateY(-1px);
  box-shadow: 0 10px 22px -4px rgba(156, 232, 178, 0.55);
}
.trip-sticky-bar__cta svg {
  width: 16px;
  height: 16px;
}
@media (max-width: 640px) {
  .trip-sticky-bar { padding: 8px 12px; gap: 8px; }
  .trip-sticky-bar__name { font-size: var(--fs-caption); }
  .trip-sticky-bar__price { display: none; }
  .trip-sticky-bar__cta { padding: 8px 14px; font-size: var(--fs-caption); }
  .trip-sticky-bar__meta { display: none; }
}

/* ---- 7.3 — Lightbox photo gallery ---- */
.lightbox {
  position: fixed;
  inset: 0;
  background: rgba(5, 6, 9, 0.96);
  z-index: var(--z-modal);
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base) ease;
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
.lightbox.is-open {
  opacity: 1;
  pointer-events: auto;
}
.lightbox__img {
  max-width: 92vw;
  max-height: 86vh;
  object-fit: contain;
  border-radius: var(--r2);
  box-shadow: 0 30px 80px -10px rgba(0, 0, 0, 0.7);
  transform: scale(0.96);
  transition: transform var(--t-base) var(--ease-spring);
}
.lightbox.is-open .lightbox__img {
  transform: scale(1);
}
.lightbox__close,
.lightbox__nav {
  position: absolute;
  background: rgba(255, 255, 255, 0.08);
  border: 1px solid rgba(255, 255, 255, 0.18);
  color: #fff;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background var(--t-fast) ease, transform var(--t-fast) var(--ease-spring);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
}
.lightbox__close:hover,
.lightbox__nav:hover {
  background: rgba(255, 255, 255, 0.18);
  transform: scale(1.06);
}
.lightbox__close { top: 20px; right: 20px; }
.lightbox__nav  { top: 50%; transform: translateY(-50%); }
.lightbox__nav:hover { transform: translateY(-50%) scale(1.06); }
.lightbox__nav--prev { left: 20px; }
.lightbox__nav--next { right: 20px; }
.lightbox__counter {
  position: absolute;
  top: 22px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.7);
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.04em;
}
.lightbox__caption {
  position: absolute;
  bottom: 20px;
  left: 50%;
  transform: translateX(-50%);
  max-width: 80vw;
  text-align: center;
  color: rgba(255, 255, 255, 0.85);
  font-size: var(--fs-body-sm);
  background: rgba(0, 0, 0, 0.4);
  padding: 8px 16px;
  border-radius: var(--r4);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
}
@media (max-width: 640px) {
  .lightbox__nav { width: 38px; height: 38px; }
  .lightbox__nav--prev { left: 10px; }
  .lightbox__nav--next { right: 10px; }
  .lightbox__close { top: 12px; right: 12px; }
}

/* Hover affordance on images that participate in the lightbox */
img.lb-target {
  cursor: zoom-in;
  transition: filter var(--t-fast) ease, transform var(--t-slow) var(--ease-spring);
}
img.lb-target:hover {
  filter: brightness(1.05) saturate(1.05);
}

/* ---- 7.4 — Itinerary accordion (auto-converts existing timeline) ---- */
[data-accordion] {
  display: block;
  border-radius: var(--r3);
  overflow: hidden;
  background: var(--bg-card, rgba(255, 255, 255, 0.02));
  border: 1px solid var(--border, rgba(255, 255, 255, 0.06));
  transition: border-color var(--t-fast) ease, background var(--t-fast) ease;
}
[data-accordion] + [data-accordion] {
  margin-top: 10px;
}
[data-accordion] summary {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 18px 22px;
  cursor: pointer;
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--txt-1);
  list-style: none;
  position: relative;
  user-select: none;
}
[data-accordion] summary::-webkit-details-marker { display: none; }
[data-accordion] summary::after {
  content: "";
  margin-left: auto;
  width: 14px;
  height: 14px;
  border-right: 2px solid var(--mint, currentColor);
  border-bottom: 2px solid var(--mint, currentColor);
  /* translate before rotate so the 2px nudge doesn't orbit the origin mid-spin */
  transform: translate(-2px, -2px) rotate(45deg);
  transition: transform var(--t-base) var(--ease-spring);
  flex-shrink: 0;
}
[data-accordion][open] summary::after {
  transform: translate(-2px, -2px) rotate(-135deg);
}
[data-accordion]:hover {
  border-color: var(--border-hi, rgba(156, 232, 178, 0.18));
}
[data-accordion][open] {
  border-color: rgba(156, 232, 178, 0.22);
  background: var(--bg-card, rgba(156, 232, 178, 0.03));
}
[data-accordion] .acc-day-num {
  display: inline-grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 50%;
  background: var(--mint-dim, rgba(156, 232, 178, 0.15));
  color: var(--mint, var(--mint));
  font-weight: 700;
  font-size: var(--fs-caption);
  flex-shrink: 0;
  letter-spacing: -0.02em;
}
[data-accordion] .acc-body {
  padding: 0 22px 22px 70px;
  color: var(--txt-2);
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  animation: acc-slide var(--t-base) var(--ease-spring);
}
@keyframes acc-slide {
  from { opacity: 0; transform: translateY(-6px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (max-width: 640px) {
  [data-accordion] summary { padding: 14px 16px; gap: 10px; font-size: var(--fs-body-sm); }
  [data-accordion] .acc-body { padding: 0 16px 18px 60px; font-size: var(--fs-body-sm); }
  [data-accordion] .acc-day-num { width: 30px; height: 30px; font-size: var(--fs-caption); }
}

/* v21 phase J.2.2: .badge* family + .departures-table block deleted.
   ~80 lines covering 9 selectors + @keyframes badge-pulse. The
   soft-urgency badge system and the per-trip departures availability
   table were both scaffolded but never wired into HTML. */

/* ---- 7.6 — Testimonials horizontal scroll-snap on mobile ---- */
@media (max-width: 768px) {
  .testimonials-grid {
    display: flex !important;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    gap: 14px;
    padding: 4px 16px 16px;
    margin: 0 -16px;
    scrollbar-width: none;
    -ms-overflow-style: none;
  }
  .testimonials-grid::-webkit-scrollbar { display: none; }
  .testimonials-grid > .testi-card {
    flex: 0 0 86%;
    scroll-snap-align: start;
    min-width: 260px;
  }
}

/* ---- 7.7 — FAB first-scroll tooltip ----
   v21 prod-prep: redundant `.fab-whatsapp { position: relative }` removed.
   It was overriding the canonical `position: fixed` declared above, which
   broke the FAB's bottom-right anchor. `position: fixed` already creates
   a positioning context for absolutely-positioned children, so the
   tooltip's `.fab-whatsapp__tooltip { position: absolute }` anchors
   correctly without the redundant relative declaration. */
.fab-whatsapp__tooltip {
  position: absolute;
  right: calc(100% + 12px);
  top: 50%;
  transform: translateY(-50%) translateX(8px);
  background: rgba(12, 14, 18, 0.96);
  color: #fff;
  padding: 10px 14px;
  border-radius: var(--r3);
  font-size: var(--fs-caption);
  font-weight: 500;
  white-space: nowrap;
  box-shadow: 0 12px 28px -8px rgba(0, 0, 0, 0.5);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-base) ease, transform var(--t-base) var(--ease-spring);
  border: 1px solid rgba(255, 255, 255, 0.08);
}
.fab-whatsapp__tooltip::after {
  content: "";
  position: absolute;
  right: -5px;
  top: 50%;
  transform: translateY(-50%) rotate(45deg);
  width: 10px;
  height: 10px;
  background: rgba(12, 14, 18, 0.96);
  border-right: 1px solid rgba(255, 255, 255, 0.08);
  border-top: 1px solid rgba(255, 255, 255, 0.08);
}
.fab-whatsapp.tooltip-shown .fab-whatsapp__tooltip {
  opacity: 1;
  transform: translateY(-50%) translateX(0);
}
:root[data-theme="light"] .fab-whatsapp__tooltip {
  background: rgba(0, 44, 81, 0.96);
  color: #fff;
}
:root[data-theme="light"] .fab-whatsapp__tooltip::after {
  background: rgba(0, 44, 81, 0.96);
}
@media (max-width: 640px) {
  .fab-whatsapp__tooltip { display: none; }
}

/* ---- 7.8 — Press / partner logo strip (greyscale) ---- */
.press-strip {
  padding: 36px clamp(16px, 4vw, 40px);
  text-align: center;
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--bg-2, rgba(255, 255, 255, 0.01));
}
.press-strip__label {
  font-size: var(--fs-2xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--txt-3);
  margin-bottom: 18px;
  font-weight: 500;
}
.press-strip__items {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: clamp(20px, 4vw, 56px);
}
.press-strip__item {
  font-family: var(--font-display, "DM Sans", sans-serif);
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--txt-3);
  opacity: 0.65;
  filter: grayscale(1);
  transition: opacity var(--t-base) ease, color var(--t-base) ease, filter var(--t-base) ease, transform var(--t-base) var(--ease-spring);
  cursor: default;
}
.press-strip__item:hover {
  opacity: 1;
  color: var(--mint);
  filter: grayscale(0);
  transform: translateY(-1px);
}

/* ---- 7.9 — "À partir de" pricing emphasis ---- */
/* v21 phase J.2.4: .price-from__label + .price-from__suffix deleted
   — never wired. .price-from__num kept; it's used by sticky inquiry
   bar's price display via document.querySelector. */

/* ---- 7.10 — Destination cards: refined hover-zoom + gradient overlay ---- */
/* dup sweep 2026-08: third `.trip-card { position: relative }` copy deleted —
   the v27 card-root block re-declares it. */
.trip-card__hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 45%,
    rgba(0, 0, 0, 0.45) 90%,
    rgba(0, 0, 0, 0.55) 100%);
  pointer-events: none;
  transition: opacity var(--t-base) ease;
  opacity: 0.85;
  z-index: 1;
}
.trip-card:hover .trip-card__hero::after {
  opacity: 0.7;
}

/* Dim non-hovered siblings (industry pattern from luxury tour operators) */
.trips-grid:hover .trip-card:not(:hover) {
  opacity: 0.7;
  filter: saturate(0.85);
  transition: opacity var(--t-base) ease, filter var(--t-base) ease;
}
.trips-grid:hover .trip-card:hover {
  opacity: 1;
  filter: saturate(1.05);
}
.trips-grid .trip-card { transition: opacity var(--t-base) ease, filter var(--t-base) ease, transform var(--t-base) var(--ease-spring); }
@media (hover: none) {
  .trips-grid:hover .trip-card:not(:hover) { opacity: 1; filter: none; }
}

/* v21 phase J.2.5: .hotel-amenities + .amenity (non-pill) + .amenity svg
   deleted — amenities row on hotel cards was scaffolded but never used.
   Real hotel cards use .amenity-pill (different styling). */

/* ---- 7.12 — 3-icon value-prop row (universal travel-site pattern) ---- */
.value-props-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(20px, 3vw, 40px);
  padding: clamp(40px, 6vw, 80px) clamp(16px, 4vw, 40px);
  max-width: 1200px;
  margin: 0 auto;
}
.value-prop {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
}
.value-prop__icon {
  width: 56px;
  height: 56px;
  display: grid;
  place-items: center;
  border-radius: var(--r-card);
  background: var(--mint-dim, rgba(156, 232, 178, 0.12));
  color: var(--mint);
  margin-bottom: 4px;
  transition: transform var(--t-base) var(--ease-spring), background var(--t-base) ease;
}
.value-prop:hover .value-prop__icon {
  transform: translateY(-3px) scale(1.05);
  background: var(--mint);
  color: var(--navy, var(--navy));
}
.value-prop__icon svg { width: 26px; height: 26px; }
.value-prop__title {
  font-family: var(--font-display, "DM Sans", sans-serif);
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--txt-1);
  letter-spacing: -0.01em;
}
.value-prop__text {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.55;
  max-width: 26ch;
}
@media (max-width: 720px) {
  .value-props-3 { grid-template-columns: 1fr; gap: 28px; padding: 36px 16px; }
  .value-prop__text { max-width: 32ch; }
}

/* ---- 7.14 — Reduced-motion + nav-clearance for sticky bar ---- */
@media (prefers-reduced-motion: reduce) {
  .trip-sticky-bar,
  .lightbox,
  .lightbox__img,
  .fab-whatsapp__tooltip {
    transition: none !important;
    animation: none !important;
  }
  .trips-grid:hover .trip-card:not(:hover) { opacity: 1; filter: none; }
}

/* When sticky bar visible, push the floating site-nav slightly so they don't overlap.
   Use a body-class toggle (set by JS) instead of :has() so we work in
   Firefox <121 and older Safari. */
body.has-sticky-bar .site-nav {
  transform: translateY(48px);
  transition: transform var(--t-base) var(--ease-spring);
}
/* When the mobile nav drawer is open, drop the scroll transform. A transform
   makes .site-nav the containing block for its position:fixed drawer child,
   trapping the drawer inside the ~56px nav box — this is the root cause of the
   "mobile nav breaks when scrolled/resized" bug. Removing it instantly (no
   transition) while open lets the drawer resolve against the viewport again.
   The nav sits under the backdrop while open, so the reset is invisible. */
body.has-sticky-bar.nav-scroll-lock .site-nav {
  transform: none;
  transition: none;
}

/* Class-based scroll lock used by the lightbox — non-destructive,
   doesn't clobber any overflow style set by an outer app/component */
:root[data-scroll-lock] body { overflow: hidden; }

/* ══════════════════════════════════════════════════════════
   v9 — Real-geography Algeria branches map (MapLibre GL)
   Replaces the v4 hand-drawn SVG outline.
   ══════════════════════════════════════════════════════════ */

/* The map container — explicit responsive height so MapLibre can measure
   it correctly during init. (aspect-ratio alone collapses to the
   intrinsic content height of the fallback div before MapLibre takes
   over the canvas sizing.) */
#algeria-map {
  position: relative;
  width: 100%;
  height: clamp(540px, 60vw, 720px);
  border-radius: var(--r3, 12px);
  overflow: hidden;
  background: var(--bg-2, #0f1218);
  border: 1px solid var(--border, rgba(255,255,255,.08));
  box-shadow: var(--elev-map);
  isolation: isolate;
  /* Pre-paint state — JS adds .algeria-map--ready once MapLibre boots */
}

/* Subtle inner ring on top of the canvas so it feels framed */
#algeria-map::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(156, 232, 178, .12);
  z-index: 5;
}

/* Mobile: taller portrait orientation for one-hand reach */
@media (max-width: 720px) {
  #algeria-map { height: clamp(540px, 110vw, 720px); }
}

/* MapLibre's own canvas picks up our border-radius via overflow: hidden */
#algeria-map .maplibregl-canvas { outline: none; }
#algeria-map .maplibregl-canvas:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}

/* Override MapLibre's default control styling to match brand */
#algeria-map .maplibregl-ctrl-group {
  background: rgba(12, 14, 18, .82) !important;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(156, 232, 178, .18) !important;
  border-radius: var(--r2, 8px) !important;
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .5) !important;
}
#algeria-map .maplibregl-ctrl-group button {
  background: transparent !important;
  filter: invert(1) hue-rotate(180deg);
}
#algeria-map .maplibregl-ctrl-attrib {
  background: rgba(12, 14, 18, .65) !important;
  color: rgba(255, 255, 255, .7) !important;
}
#algeria-map .maplibregl-ctrl-attrib a { color: var(--mint, var(--mint)) !important; }

/* Light theme — flip the chrome */
:root[data-theme="light"] #algeria-map {
  background: var(--bg-2, #f3ede1);
  border-color: rgba(0, 44, 81, .14);
  box-shadow: var(--elev-map);
}
:root[data-theme="light"] #algeria-map .maplibregl-ctrl-group {
  background: rgba(255, 255, 255, .92) !important;
  border-color: rgba(35, 122, 74, .18) !important;
}
:root[data-theme="light"] #algeria-map .maplibregl-ctrl-group button {
  filter: none;
}
:root[data-theme="light"] #algeria-map .maplibregl-ctrl-attrib {
  background: rgba(255, 255, 255, .8) !important;
  color: rgba(0, 44, 81, .6) !important;
}

/* ─── HQ marker (Bordj Bou Arreridj) ─────────────────────── */
.amap-hq {
  position: relative;
  width: 28px;
  height: 28px;
  cursor: pointer;
}
.amap-hq__dot {
  position: absolute;
  left: 50%; top: 50%;
  width: 16px; height: 16px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mint, var(--mint));
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .95),
    0 4px 10px -2px rgba(0, 0, 0, .35);
  z-index: 3;
}
.amap-hq__halo {
  position: absolute;
  left: 50%; top: 50%;
  width: 28px; height: 28px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mint, var(--mint));
  opacity: .55;
  z-index: 1;
  animation: amap-pulse 1.9s ease-out infinite;
}
.amap-hq__halo--2 {
  animation-delay: -.95s;
  opacity: .35;
}
.amap-hq__label {
  position: absolute;
  left: 50%;
  top: -22px;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: .02em;
  color: var(--mint, var(--mint));
  text-shadow:
    0 0 4px rgba(0, 0, 0, .55),
    0 1px 2px rgba(0, 0, 0, .4);
  pointer-events: none;
  padding: 2px 8px;
  background: rgba(12, 14, 18, .55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: var(--r4);
}
:root[data-theme="light"] .amap-hq__label {
  color: #fff;
  background: rgba(35, 122, 74, .92);
  text-shadow: none;
}

@keyframes amap-pulse {
  0%   { transform: translate(-50%, -50%) scale(.5); opacity: .65; }
  100% { transform: translate(-50%, -50%) scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .amap-hq__halo, .amap-hq__halo--2 { animation: none; opacity: .25; }
}

/* ─── Branch markers (partner cities) ─────────────────────── */
.amap-branch {
  position: relative;
  width: 18px;
  height: 18px;
  cursor: pointer;
}
.amap-branch__dot {
  position: absolute;
  left: 50%; top: 50%;
  width: 10px; height: 10px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mint, var(--mint));
  box-shadow:
    0 0 0 2.5px rgba(255, 255, 255, .9),
    0 3px 6px -1px rgba(0, 0, 0, .3);
  transition: transform var(--t-fast) var(--ease-spring);
}
.amap-branch:hover .amap-branch__dot {
  transform: translate(-50%, -50%) scale(1.3);
}
.amap-branch__label {
  position: absolute;
  left: 50%;
  top: -16px;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: var(--fs-2xs);
  font-weight: 600;
  letter-spacing: .02em;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .8), 0 0 8px rgba(0, 0, 0, .4);
  pointer-events: none;
}
:root[data-theme="light"] .amap-branch__label {
  color: var(--navy, var(--navy));
  text-shadow: 0 1px 3px rgba(255, 255, 255, .9), 0 0 8px rgba(255, 255, 255, .6);
}

/* Future-network cities: smaller, dimmer, no popup */
.amap-branch--future .amap-branch__dot {
  width: 7px; height: 7px;
  opacity: .55;
  box-shadow:
    0 0 0 2px rgba(255, 255, 255, .7),
    0 2px 4px rgba(0, 0, 0, .25);
}
.amap-branch--future .amap-branch__label {
  font-size: var(--fs-2xs);
  opacity: .6;
}

/* ─── Popup styling — matches brand ─────────────────────────── */
.maplibregl-popup-content {
  background: rgba(12, 14, 18, .96) !important;
  color: var(--txt-1, #efe8df) !important;
  border-radius: var(--r2, 8px) !important;
  border: 1px solid rgba(156, 232, 178, .22) !important;
  padding: 12px 14px !important;
  box-shadow: 0 14px 30px -8px rgba(0, 0, 0, .55) !important;
  font-family: var(--font-body, 'DM Sans', sans-serif);
}
.maplibregl-popup-tip {
  border-top-color: rgba(12, 14, 18, .96) !important;
  border-bottom-color: rgba(12, 14, 18, .96) !important;
}
:root[data-theme="light"] .maplibregl-popup-content {
  background: #fff !important;
  color: var(--txt-1, var(--navy)) !important;
  border-color: rgba(35, 122, 74, .22) !important;
}
:root[data-theme="light"] .maplibregl-popup-tip {
  border-top-color: #fff !important;
  border-bottom-color: #fff !important;
}

.amap-popup__role {
  font-size: var(--fs-2xs);
  letter-spacing: .14em;
  font-weight: 700;
  color: var(--mint, var(--mint));
  margin-bottom: 4px;
  text-transform: uppercase;
}
.amap-popup__name {
  font-size: var(--fs-body);
  font-weight: 700;
  margin: 0 0 4px;
  letter-spacing: -.01em;
}
.amap-popup__addr {
  font-size: var(--fs-caption);
  color: var(--txt-2, #c9cdd4);
  margin: 0 0 8px;
}
.amap-popup__phone {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--mint, var(--mint)) !important;
  text-decoration: none;
  padding: 4px 0;
}
.amap-popup__phone:hover { text-decoration: underline; }
:root[data-theme="light"] .amap-popup__addr { color: var(--txt-2, #4a5b6f); }
:root[data-theme="light"] .amap-popup__phone { color: var(--mint, #237a4a) !important; }

/* ─── Fallback / loading overlay ────────────────────────────────
   Absolute-positioned so it doesn't push the container's height
   (which would defeat the explicit clamp() height above and let the
   canvas collapse to ~40px). Sits centred over the (still-blank)
   container until MapLibre paints; auto-hidden once .algeria-map--ready
   adds. Stays visible if .algeria-map--fallback signals CDN failure. */
.amap-fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--s7, 32px);
  background: linear-gradient(135deg, var(--bg-2, #0f1218), var(--bg, #0a0c12));
  z-index: 1;
  transition: opacity var(--t-base) ease;
}
.amap-fallback > * { max-width: 480px; }

/* Once the map is ready, hide the loading message */
.algeria-map--ready .amap-fallback { opacity: 0; pointer-events: none; }
/* If the CDN failed, keep the fallback fully opaque */
.algeria-map--fallback .amap-fallback { opacity: 1 !important; pointer-events: auto !important; }
.amap-fallback__title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--txt-1);
  margin: 0 0 8px;
}
.amap-fallback__sub {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.55;
  margin: 0;
}
.amap-fallback__sub strong { color: var(--mint); }

/* ══════════════════════════════════════════════════════════
   v10 — Trip itinerary map (vanilla MapLibre GL)
   Used on every trip page. Three pin categories + hub labels.
   ══════════════════════════════════════════════════════════ */

#trip-map {
  position: relative;
  width: 100%;
  height: clamp(560px, 64vw, 760px);
  border-radius: var(--r3, 12px);
  overflow: hidden;
  background: var(--bg-2, #0f1218);
  border: 1px solid var(--border, rgba(255,255,255,.08));
  box-shadow: var(--elev-map);
  isolation: isolate;
}
#trip-map::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(156, 232, 178, .12);
  z-index: 5;
}
@media (max-width: 720px) {
  #trip-map { height: clamp(540px, 110vw, 720px); }
}

#trip-map .maplibregl-canvas { outline: none; }
#trip-map .maplibregl-canvas:focus-visible {
  outline: none;
  box-shadow: 0 0 0 3px var(--ring);
}
#trip-map .maplibregl-ctrl-group {
  background: rgba(12, 14, 18, .82) !important;
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(156, 232, 178, .18) !important;
  border-radius: var(--r2, 8px) !important;
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .5) !important;
}
#trip-map .maplibregl-ctrl-group button {
  background: transparent !important;
  filter: invert(1) hue-rotate(180deg);
}
#trip-map .maplibregl-ctrl-attrib {
  background: rgba(12, 14, 18, .65) !important;
  color: rgba(255, 255, 255, .7) !important;
}
#trip-map .maplibregl-ctrl-attrib a { color: var(--mint, var(--mint)) !important; }

:root[data-theme="light"] #trip-map {
  background: var(--bg-2, #f3ede1);
  border-color: rgba(0, 44, 81, .14);
  box-shadow: var(--elev-map);
}
:root[data-theme="light"] #trip-map .maplibregl-ctrl-group {
  background: rgba(255, 255, 255, .92) !important;
  border-color: rgba(35, 122, 74, .18) !important;
}
:root[data-theme="light"] #trip-map .maplibregl-ctrl-group button { filter: none; }
:root[data-theme="light"] #trip-map .maplibregl-ctrl-attrib {
  background: rgba(255, 255, 255, .8) !important;
  color: rgba(0, 44, 81, .6) !important;
}

/* ─── Generic pin (hotels, sites, tours) ───────────────────── */
.tmap-pin {
  position: relative;
  cursor: pointer;
  width: 28px;
  height: 28px;
}
.tmap-pin__dot {
  position: absolute;
  left: 50%; top: 50%;
  width: 16px; height: 16px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  display: grid;
  place-items: center;
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .95),
    0 4px 10px -1px rgba(0, 0, 0, .4);
  transition: transform var(--t-fast) var(--ease-spring),
              box-shadow var(--t-fast) ease;
  color: var(--navy, var(--navy));
}
.tmap-pin:hover .tmap-pin__dot {
  transform: translate(-50%, -50%) scale(1.35);
}
.tmap-pin__label {
  position: absolute;
  left: 50%;
  top: -18px;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .01em;
  color: #fff;
  text-shadow: 0 1px 3px rgba(0, 0, 0, .9), 0 0 10px rgba(0, 0, 0, .6);
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-fast) ease;
  padding: 2px 7px;
  background: rgba(12, 14, 18, .55);
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  border-radius: var(--r4);
}
/* Default: only featured/hover/focus labels visible.
   When the user zooms in past ~9 (JS adds .is-zoomed-in to #trip-map),
   ALL labels reveal — overview stays clean, detail view is informative. */
.tmap-pin:hover .tmap-pin__label,
.tmap-pin:focus-visible .tmap-pin__label,
.tmap-pin--featured .tmap-pin__label,
#trip-map.is-zoomed-in .tmap-pin__label,
#algeria-map.is-zoomed-in .tmap-pin__label {
  opacity: 1;
}
:root[data-theme="light"] .tmap-pin__label {
  color: #fff;
  background: rgba(35, 122, 74, .92);
  text-shadow: none;
}

/* Hotel pins — mint with white bed icon. Always slightly larger than
   site/tour pins so users can spot bookable accommodation at a glance. */
.tmap-pin--hotel .tmap-pin__dot {
  background: var(--mint, var(--mint));
  width: 22px; height: 22px;
}
.tmap-pin--hotel .tmap-pin__dot svg {
  width: 13px; height: 13px;
  stroke: var(--navy, var(--navy));
}

/* Site pins — warm amber */
.tmap-pin--site .tmap-pin__dot {
  background: var(--warn);       /* amber */
}
.tmap-pin--site.tmap-pin--featured .tmap-pin__dot {
  width: 22px; height: 22px;
  box-shadow:
    0 0 0 3.5px rgba(255, 255, 255, .98),
    0 0 0 7px rgba(224, 160, 74, .35),
    0 4px 12px -1px rgba(0, 0, 0, .45);
}
.tmap-pin--site.tmap-pin--featured::after {
  content: '';
  position: absolute;
  left: 50%; top: 50%;
  width: 32px; height: 32px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: rgba(224, 160, 74, .35);
  z-index: -1;
  animation: tmap-pulse 2s ease-out infinite;
  pointer-events: none;
}

/* Tour pins — turquoise */
.tmap-pin--tour .tmap-pin__dot {
  background: #3aa3a8;       /* turquoise */
}

@keyframes tmap-pulse {
  0%   { transform: translate(-50%, -50%) scale(.5); opacity: .55; }
  100% { transform: translate(-50%, -50%) scale(2.6); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .tmap-pin--site.tmap-pin--featured::after { animation: none; opacity: 0; }
}

/* ─── Hubs (big city labels) ───────────────────────────────── */
.tmap-hub {
  position: relative;
  width: 28px;
  height: 28px;
  cursor: default;
}
.tmap-hub__dot {
  position: absolute;
  left: 50%; top: 50%;
  width: 14px; height: 14px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mint, var(--mint));
  box-shadow:
    0 0 0 3px rgba(255, 255, 255, .95),
    0 4px 10px -2px rgba(0, 0, 0, .4);
  z-index: 3;
}
.tmap-hub__halo {
  position: absolute;
  left: 50%; top: 50%;
  width: 28px; height: 28px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--mint, var(--mint));
  opacity: .5;
  z-index: 1;
  animation: tmap-pulse 2s ease-out infinite;
}
.tmap-hub__label {
  position: absolute;
  left: 50%;
  top: -22px;
  transform: translateX(-50%);
  white-space: nowrap;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: .015em;
  color: var(--mint, var(--mint));
  text-shadow: 0 0 4px rgba(0, 0, 0, .6), 0 1px 2px rgba(0, 0, 0, .5);
  pointer-events: none;
  padding: 3px 10px;
  background: rgba(12, 14, 18, .58);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-radius: var(--r4);
}
.tmap-hub__days {
  font-weight: 500;
  opacity: .82;
  font-size: var(--fs-2xs);
}
:root[data-theme="light"] .tmap-hub__label {
  color: #fff;
  background: rgba(35, 122, 74, .94);
  text-shadow: none;
}
@media (prefers-reduced-motion: reduce) {
  .tmap-hub__halo { animation: none; opacity: .25; }
}

/* ─── Popups (shared with algeria-map styling, scoped here too) ── */
#trip-map .maplibregl-popup-content {
  background: rgba(12, 14, 18, .96) !important;
  color: var(--txt-1, #efe8df) !important;
  border-radius: var(--r2, 8px) !important;
  border: 1px solid rgba(156, 232, 178, .22) !important;
  padding: 12px 14px !important;
  box-shadow: 0 14px 30px -8px rgba(0, 0, 0, .55) !important;
  font-family: var(--font-body, 'DM Sans', sans-serif);
}
#trip-map .maplibregl-popup-tip {
  border-top-color: rgba(12, 14, 18, .96) !important;
  border-bottom-color: rgba(12, 14, 18, .96) !important;
}
:root[data-theme="light"] #trip-map .maplibregl-popup-content {
  background: #fff !important;
  color: var(--txt-1, var(--navy)) !important;
  border-color: rgba(35, 122, 74, .22) !important;
}
:root[data-theme="light"] #trip-map .maplibregl-popup-tip {
  border-top-color: #fff !important;
  border-bottom-color: #fff !important;
}
.tmap-popup__role {
  font-size: var(--fs-2xs);
  letter-spacing: .14em;
  font-weight: 700;
  color: var(--mint, var(--mint));
  margin-bottom: 4px;
  text-transform: uppercase;
}
.tmap-popup__name {
  font-size: var(--fs-body);
  font-weight: 700;
  margin: 0 0 4px;
  letter-spacing: -.01em;
}
.tmap-popup__addr {
  font-size: var(--fs-caption);
  color: var(--txt-2, #c9cdd4);
  margin: 0;
}
:root[data-theme="light"] .tmap-popup__addr { color: var(--txt-2, #4a5b6f); }

/* ─── Loading / fallback overlay ───────────────────────────── */
.tmap-fallback {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  text-align: center;
  padding: var(--s7, 32px);
  background: linear-gradient(135deg, var(--bg-2, #0f1218), var(--bg, #0a0c12));
  z-index: 1;
  transition: opacity var(--t-base) ease;
}
.tmap-fallback > * { max-width: 480px; }
.tmap-fallback__title {
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--txt-1);
  margin: 0 0 8px;
}
.tmap-fallback__sub {
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.55;
  margin: 0;
}
.trip-map--ready .tmap-fallback { opacity: 0; pointer-events: none; }
.trip-map--fallback .tmap-fallback { opacity: 1 !important; pointer-events: auto !important; }

/* ─── Section wrapper around the map ───────────────────────── */
.trip-map-section {
  background: var(--bg);
  border-top: 1px solid var(--border);
}
.trip-map-section .section-head { margin-bottom: var(--s7, 32px); }

/* Compact legend strip below the map */
.trip-map-legend {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--s5, 24px);
  margin-top: var(--s5, 24px);
  font-size: var(--fs-caption);
  color: var(--txt-2);
}
.trip-map-legend__item {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.trip-map-legend__chip {
  display: inline-block;
  width: 12px; height: 12px;
  border-radius: 50%;
  box-shadow: 0 0 0 2px rgba(255,255,255,.85);
}
.trip-map-legend__chip--hotel { background: var(--mint, var(--mint)); }
.trip-map-legend__chip--site  { background: var(--warn); }
.trip-map-legend__chip--tour  { background: #3aa3a8; }

/* ─── Recenter button (floats bottom-left over the map) ───────
   Appears once the map is loaded; clicking it re-fits bounds to
   the original POI cluster so users who panned away can reset.
   JS attaches the click handler in trip-map.js + algeria-map.js. */
.tmap-recenter,
.amap-recenter {
  position: absolute;
  bottom: 14px;
  left: 14px;
  z-index: 6;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 7px 12px 7px 10px;
  background: rgba(12, 14, 18, .85);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  color: var(--mint, var(--mint));
  border: 1px solid rgba(156, 232, 178, .25);
  border-radius: var(--r4);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .01em;
  cursor: pointer;
  box-shadow: 0 6px 18px -8px rgba(0, 0, 0, .55);
  transition: transform var(--t-fast) var(--ease-spring),
              background var(--t-fast) ease,
              opacity var(--t-fast) ease;
  opacity: 0;
  pointer-events: none;
}
.algeria-map--ready .amap-recenter,
.trip-map--ready .tmap-recenter {
  opacity: 1;
  pointer-events: auto;
}
.tmap-recenter:hover,
.amap-recenter:hover {
  background: rgba(156, 232, 178, .15);
  transform: translateY(-1px);
}
.tmap-recenter svg,
.amap-recenter svg {
  width: 14px; height: 14px;
  flex-shrink: 0;
}
:root[data-theme="light"] .tmap-recenter,
:root[data-theme="light"] .amap-recenter {
  background: rgba(255, 255, 255, .92);
  color: var(--mint, #237a4a);
  border-color: rgba(35, 122, 74, .25);
}
@media (prefers-reduced-motion: reduce) {
  .tmap-recenter, .amap-recenter { transition: none !important; }
}
@media (max-width: 480px) {
  .tmap-recenter, .amap-recenter { font-size: var(--fs-2xs); padding: 6px 10px 6px 8px; }
}

/* ══════════════════════════════════════════════════════════
   v11 — Anti-clutter engine for trip-map + algeria-map
   Hides colliding labels, stacks overlapping pins with +N badges,
   adds click-to-isolate dim, hover always reveals label even if
   collision-hidden. JS in trip-map.js / algeria-map.js drives the
   class toggles; this file is the visual layer.
   ══════════════════════════════════════════════════════════ */

/* ─── Pin stack absorbed (lower-priority pin in a cluster) ─── */
.tmap-collide-hidden,
.amap-collide-hidden {
  opacity: 0 !important;
  pointer-events: none !important;
  /* Stay in DOM so the absorber's screen position math stays stable */
}

/* ─── Stack-count badge (+N chip on the top-of-stack pin) ─── */
.tmap-pin[data-stack-count],
.tmap-hub[data-stack-count],
.amap-branch[data-stack-count],
.amap-hq[data-stack-count] {
  cursor: zoom-in;   /* signals "click to expand the cluster" */
}
.tmap-pin[data-stack-count]::after,
.tmap-hub[data-stack-count]::after,
.amap-branch[data-stack-count]::after,
.amap-hq[data-stack-count]::after {
  content: attr(data-stack-count);
  position: absolute;
  top: -8px;
  right: -10px;
  min-width: 18px;
  height: 18px;
  padding: 0 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--mint, var(--mint));
  color: var(--navy, var(--navy));
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: -.01em;
  line-height: 1;
  border-radius: var(--r4);
  border: 2px solid #fff;
  box-shadow: 0 2px 6px -1px rgba(0, 0, 0, .35);
  pointer-events: none;
  z-index: 4;
  animation: tmap-stack-pop var(--t-base) var(--ease-bounce) both;
}
@keyframes tmap-stack-pop {
  0%   { transform: scale(.4); opacity: 0; }
  60%  { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}
:root[data-theme="light"] .tmap-pin[data-stack-count]::after,
:root[data-theme="light"] .tmap-hub[data-stack-count]::after,
:root[data-theme="light"] .amap-branch[data-stack-count]::after,
:root[data-theme="light"] .amap-hq[data-stack-count]::after {
  background: #237a4a;
  color: #fff;
}

/* ─── Label collision (hidden by algorithm, but hover always wins) ─── */
.tmap-pin__label.tmap-label-collide,
.tmap-hub__label.tmap-label-collide,
.amap-branch__label.amap-label-collide,
.amap-hq__label.amap-label-collide {
  opacity: 0 !important;
  visibility: hidden;
  transition: opacity 160ms ease, visibility 0s linear 160ms;
}
/* Direct pointer/keyboard hover always overrides the collision-hide,
   so users can still read every label on demand. */
.tmap-pin:hover .tmap-pin__label,
.tmap-pin:focus-visible .tmap-pin__label,
.tmap-hub:hover .tmap-hub__label,
.amap-branch:hover .amap-branch__label,
.amap-branch:focus-visible .amap-branch__label,
.amap-hq:hover .amap-hq__label {
  opacity: 1 !important;
  visibility: visible !important;
  transition: opacity 160ms ease, visibility 0s !important;
  z-index: 20;
}

/* ─── Click-to-isolate (sibling pins dim while the focused one stands out) ─── */
#trip-map.is-isolating .tmap-pin:not(.is-focused),
#trip-map.is-isolating .tmap-hub:not(.is-focused),
#algeria-map.is-isolating .amap-branch:not(.is-focused),
#algeria-map.is-isolating .amap-hq:not(.is-focused) {
  opacity: 0.32;
  filter: saturate(.5);
  transition: opacity var(--t-fast) ease, filter var(--t-fast) ease;
}
#trip-map .tmap-pin.is-focused,
#trip-map .tmap-hub.is-focused,
#algeria-map .amap-branch.is-focused,
#algeria-map .amap-hq.is-focused {
  z-index: 25;
  transition: filter var(--t-fast) ease;
}
/* Halo behind the focused pin so it visibly "pops" out of the dim group */
#trip-map .tmap-pin.is-focused .tmap-pin__dot,
#algeria-map .amap-branch.is-focused .amap-branch__dot {
  box-shadow:
    0 0 0 3px #fff,
    0 0 0 6px var(--mint, var(--mint)),
    0 6px 14px -2px rgba(0, 0, 0, .5) !important;
}

/* ─── Reduced motion: kill animations on the badges + isolation transitions ─── */
@media (prefers-reduced-motion: reduce) {
  .tmap-pin[data-stack-count]::after,
  .tmap-hub[data-stack-count]::after,
  .amap-branch[data-stack-count]::after,
  .amap-hq[data-stack-count]::after {
    animation: none !important;
  }
  #trip-map.is-isolating .tmap-pin:not(.is-focused),
  #trip-map.is-isolating .tmap-hub:not(.is-focused),
  #algeria-map.is-isolating .amap-branch:not(.is-focused),
  #algeria-map.is-isolating .amap-hq:not(.is-focused) {
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════════
   v12 — Hierarchy & UX Audit Pass (2026-05-06)
   Implements the 8-section UX critique:
   1. Page flow — phase markers (Découvrir → Comparer → Calculer → Réserver)
   2. Visual hierarchy — hero price as canonical block, tighter section heads
   3. Layout & spacing — consistent vertical rhythm, FAQ Q/A separator,
      hotel card price restructure, calc+recap visual binding
   4. Typography — uppercase labels normalized, fewer inline bolds win
   5. Interaction cues — tier tabs as chips, stepper as real buttons,
      hotel "Sélectionner" as solid primary
   6. IA dedup — canonical price block (no inline price competition)
   7. Trust — stat-card + testi-card refinement
   8. Cross-sell + footer — phone group with icons
   ══════════════════════════════════════════════════════════ */

/* ── 1. Phase markers ─────────────────────────────────────── */
.phase-marker {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--accent);
  background: var(--accent-dim);
  border: 1px solid var(--border);
  padding: 4px 10px 4px 4px;
  border-radius: var(--r4);
  margin-bottom: var(--s4);
  font-variant-numeric: tabular-nums;
}
.phase-marker__num {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: var(--accent-2);   /* v28 amber step badge */
  color: var(--bg);
  display: grid;
  place-items: center;
  font-size: var(--fs-2xs);
  font-weight: 800;
}
.phase-marker__label {
  padding-right: 4px;
}
:root[data-theme="light"] .phase-marker {
  background: rgba(0, 44, 81, .06);
  border-color: rgba(0, 44, 81, .12);
}

/* ── 2. Hero price — canonical, dominant block ────────────── */

/* ── 3. Hero CTAs — clear primary/secondary hierarchy ──────── */
.hero__ctas {
  margin-top: var(--s5);
  gap: var(--s3);
}
/* Both buttons in a hero cluster share one size — they were 15px/32px next to
   14px/24px, which read as a rendering accident (visual audit A20). */
.hero__ctas .btn--primary,
.hero__ctas .btn--ghost {
  font-size: var(--fs-body-sm);
  padding: var(--s4) var(--s6);
  font-weight: 600;
  letter-spacing: .01em;
}
.hero__ctas .btn--ghost {
  opacity: .9;
}

/* ── 4. Tier tabs as chips (clear affordance) ─────────────── */
.tier-tabs {
  border-bottom: none;
  gap: var(--s2);
  margin-bottom: var(--s6);
  flex-wrap: wrap;
}
.tier-tab {
  border: 1px solid var(--border-hi);
  border-radius: var(--r4);
  padding: 8px 16px;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--txt-2);
  background: transparent;
  margin-bottom: 0;
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-snap), color var(--t-fast) var(--ease-snap), background var(--t-fast) var(--ease-snap), box-shadow var(--t-fast) var(--ease-snap), filter var(--t-fast) var(--ease-snap);
  letter-spacing: .02em;
}
.tier-tab:hover {
  border-color: var(--accent);
  color: var(--txt-1);
  background: var(--accent-dim);
}
.tier-tab[aria-pressed="true"] {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  box-shadow: 0 1px 0 rgba(0, 0, 0, .08), inset 0 1px 0 rgba(255, 255, 255, .15);
}
.tier-tab[aria-pressed="true"]:hover {
  filter: brightness(1.05);
}

/* ── 5. Hotel card price — explicit structure ─────────────── */
.hotel-card__body {
  gap: var(--s2);
}
.hotel-card__amenities {
  margin-bottom: var(--s2);
}
.hotel-card__price {
  display: flex;
  flex-direction: column;
  gap: 1px;
  padding-top: var(--s4);
  margin-top: auto;
  border-top: 1px solid var(--border);
}
.hotel-card__price-label {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.hotel-card__price strong {
  font-size: 1.625rem;
  font-weight: 700;
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
  line-height: 1.05;
  display: block;
  letter-spacing: -.01em;
}
.hotel-card__price-meta {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  margin-top: 4px;
}

/* ── 6. Hotel card CTA — solid primary button ─────────────── */
.hotel-card__cta {
  background: var(--accent);
  color: var(--bg);
  border: 1px solid var(--accent);
  font-weight: 600;
  padding: var(--s4) var(--s5);
  margin-top: var(--s4);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s2);
  border-radius: var(--r2);
  cursor: pointer;
  transition: filter var(--t-fast), transform var(--t-fast), box-shadow var(--t-fast);
  letter-spacing: .01em;
}
.hotel-card__cta::after {
  content: "→";
  display: inline-block;
  transition: transform var(--t-fast);
  font-weight: 400;
}
.hotel-card__cta:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 4px 12px rgba(0, 0, 0, .15);
}
.hotel-card__cta:hover::after {
  transform: translateX(2px);
}
.hotel-card.selected .hotel-card__cta {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  filter: brightness(.95);
}
.hotel-card.selected .hotel-card__cta::before {
  content: "✓ ";
  font-weight: 700;
}

/* ── 7. Stepper as real buttons (rounded squares, not chars) ── */
.stepper__btn {
  width: 38px;
  height: 38px;
  border-radius: var(--r2);
  background: var(--bg);
  border: 1px solid var(--border-hi);
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--txt-1);
  cursor: pointer;
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
  display: grid;
  place-items: center;
  line-height: 1;
}
.stepper__btn:hover:not(:disabled) {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  transform: scale(1.04);
}
.stepper__btn:active:not(:disabled) {
  transform: scale(.96);
}
.stepper__val {
  min-width: 32px;
  font-size: 1.0625rem;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  text-align: center;
  color: var(--txt-1);
}

/* ── 8. FAQ — Q/A clear separator + breathing room ────────── */
.faq-list {
  gap: var(--s3);
  display: flex;
  flex-direction: column;
}
.faq-item {
  border-radius: var(--r3);
  transition: border-color var(--t-fast), box-shadow var(--t-fast);
}
.faq-item.open,
.faq-item[open] {
  border-color: var(--border-mint);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .04);
}
.faq-q {
  padding: var(--s5) var(--s6);
  font-weight: 600;
  font-size: var(--fs-body-sm);
  line-height: 1.4;
}
.faq-q:hover {
  background: var(--bg-card);
}
/* .faq-item has overflow:hidden, so the default 3px-outside focus ring is
   clipped away entirely. Draw it inside the button instead — same fix, same
   value as the structurally identical .info-card__head accordion. */
.faq-q:focus-visible {
  outline-offset: -2px;
}
.faq-a {
  font-size: var(--fs-body-sm);
  line-height: 1.7;
}
.faq-item.open .faq-a {
  max-height: 800px;
  padding: var(--s4) var(--s6) var(--s5);
  border-top: 1px solid var(--border);
  margin-top: 0;
}
/* FAQ inline price lists — give them their own line */
.faq-a strong {
  font-variant-numeric: tabular-nums;
  color: var(--txt-1);
}
/* dead-css sweep 2026-08: the three `.faq-a ul.faq-prices` rules are deleted —
   no FAQ answer in any page or template emits a ul.faq-prices. */

/* ── 9. Calculator + recap — visually bound panel ─────────── */
.calc-grid {
  align-items: start;
}
.breakdown {
  position: sticky;
  top: 96px;
  background: var(--bg-card);
  border: 1px solid var(--border-hi);
  border-radius: var(--r3);
  padding: var(--s5);
  box-shadow: 0 4px 20px rgba(0, 0, 0, .04);
}
.breakdown__header {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-3);
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--border);
  margin: 0 0 var(--s4);
}
.breakdown__lines {
  margin-bottom: var(--s3);
}
.breakdown__line {
  font-size: var(--fs-body-sm);
  padding: 6px 0;
}
.breakdown__total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin: var(--s4) calc(var(--s5) * -1) calc(var(--s4) * -1);
  padding: var(--s4) var(--s5);
  background: var(--accent-dim);
  border-radius: 0 0 var(--r3) var(--r3);
  border-top: 1px solid var(--border);
}
.breakdown__total-label {
  font-size: var(--fs-caption);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .12em;
  color: var(--txt-2);
}
.breakdown__total-amount {
  font-size: 1.625rem;
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  line-height: 1;
}
.breakdown__ctas {
  margin-top: var(--s5);
}
.breakdown__why {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px dashed var(--border);
}
.breakdown__why summary {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  cursor: pointer;
}

/* ── 10. Calc form — clear group separation ───────────────── */
.calc-form-group {
  padding-bottom: var(--s5);
  border-bottom: 1px solid var(--border);
  margin-bottom: var(--s5);
}
.calc-form-group:last-child {
  border-bottom: none;
  padding-bottom: 0;
  margin-bottom: 0;
}
.calc-form-label {
  /* v22 Agent 3 — bring this v12 cascade override in line with the
     foundation: --txt-3 → --txt-2 (contrast lift), fluid --fs-body-sm,
     letter-spacing dialled from .12 → .04 (was airy at .75rem caps;
     even airier at the new fluid size if left at .12). Weight kept
     at 700 because this is the v12 stronger-form spec. */
  display: block;
  font-size: var(--fs-body-sm);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
  color: var(--txt-2);
  margin-bottom: var(--s3);
}

/* ── 11. Date chips ───────────────────────────────────────── */
.date-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
}
.date-chip {
  padding: 8px 14px;
  border: 1px solid var(--border-hi);
  border-radius: var(--r4);
  background: transparent;
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--txt-2);
  cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
  letter-spacing: .01em;
}
.date-chip:hover {
  border-color: var(--accent);
  color: var(--txt-1);
  background: var(--accent-dim);
}
.date-chip.active {
  background: var(--accent);
  color: var(--bg);
  border-color: var(--accent);
  font-weight: 600;
}
/* v26 mobile-ux: at ≤640px the FR date labels wrap to 2–3 rows; raise the
   inter-chip gap (--s2→--space-3) and horizontal padding (14px→--space-3) so
   wrapped 44px chips separate clearly. */
@media (max-width: 640px) {
  .date-chips {
    gap: var(--space-3);
  }
  .date-chip {
    padding: 8px var(--space-3);
  }
}

/* ── 12. Segmented control — proper visual ────────────────── */
.segmented {
  display: inline-flex;
  /* .calc-form-group (:1153) is a column flex container, which blockifies the
     inline-flex above and then stretches it to the full column — a 544px
     bordered bar wrapped around 72px of options. flex-start restores the
     content-width sizing inline-flex was asking for; width:fit-content is
     belt-and-braces. The ≤640px block below re-stretches it to 100%. */
  align-self: flex-start;
  width: fit-content;
  background: var(--bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r2);
  padding: 3px;
  gap: 0;
}
.seg-opt {
  padding: 8px 14px;
  font-size: var(--fs-caption);
  font-weight: 500;
  color: var(--txt-2);
  background: transparent;
  border-radius: var(--r2);
  cursor: pointer;
  transition: color var(--t-fast), background var(--t-fast);
  border: none;
}
.seg-opt:hover {
  color: var(--txt-1);
}
.seg-opt.active {
  background: var(--accent);
  color: var(--bg);
  font-weight: 600;
}
/* v26 mobile-ux: the inline-flex duplicate above holds the room-type control
   at content width. At ≤640px stretch it full-width so it aligns with the
   chips/select, and split it into as many equal parts as there are options.
   The old `repeat(3, 1fr)` hardcoded three room types, so tunisie (1 option)
   and istanbul (2) rendered one or two empty bordered thirds; going flex here
   also activates the `.seg-opt { flex: 1 }` below, which was dead under grid.
   Coarse-pointer min-height (44px, :126) kept. */
@media (max-width: 640px) {
  .segmented {
    display: flex;
    width: 100%;
  }
  .seg-opt {
    flex: 1;
    min-width: 0;
  }
}

/* ── 13. Footer — phone group with icons ──────────────────── */
.footer-col {
  display: flex;
  flex-direction: column;
  gap: 2px;
}
.footer-col h4 {
  margin-bottom: var(--s3);
}
.phone-group {
  display: flex;
  flex-direction: column;
  margin-bottom: var(--s4);
}
.phone-group:last-child {
  margin-bottom: 0;
}
.phone-group__head {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-3);
  margin: 0 0 var(--s2);
}
.phone-group__head svg {
  color: var(--accent);
  width: 13px;
  height: 13px;
  flex-shrink: 0;
}
.phone-group a {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  letter-spacing: .02em;
  padding: 3px 0;
  color: var(--txt-1);
  transition: color var(--t-fast);
}
.phone-group a:hover {
  color: var(--accent);
}

/* ── 14. Section spacing — v22 foundation-aligned ─────── */
section.section {
  padding-block: var(--section-y, clamp(48px, 8vw, 96px));
  scroll-margin-top: calc(var(--nav-h, 72px) + 16px);
  position: relative;
}

/* dead-css sweep 2026-08: the `.phase-block` alternating-background pair is
   deleted — no page has ever shipped the class, so the second rule (which
   requires a preceding .phase-block sibling) could never match either. */

/* ── 15. Section heads — tighter, more disciplined ────────── */
.section-head {
  margin-bottom: var(--s7);
}
.section-head__eyebrow {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--accent);
}
.section-head__title {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: -.015em;
  margin-top: var(--s3);
}
/* migrated from the removed duplicate block (~L998) */
.section-head__title em {
  font-style: normal;
  color: var(--accent-2);   /* accent em — color carries the emphasis */
}
.section-head__sub {
  margin-top: var(--s3);
  font-size: var(--fs-body);
  color: var(--txt-2);
  max-width: 56ch;
  line-height: 1.6;
}

/* Centered modifier (HTML wave adds .section-head--center). The region
   eyebrow dash (~L3876) keeps its inline-block flow so its ::before dash
   sits immediately left of the centered text. */
.section-head--center {
  text-align: center;
}
.section-head--center .section-head__eyebrow {
  display: inline-block;
  margin-inline: auto;
}
.section-head--center .section-head__sub {
  margin-inline: auto;
}

/* ── 16. Stat cards — bounded, readable ───────────────────── */
.stat-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s5);
  text-align: start;
}
.stat-card__num {
  font-size: clamp(1.75rem, 3vw, 2.25rem);
  font-weight: 700;
  color: var(--accent);
  font-variant-numeric: tabular-nums;
  line-height: 1;
  letter-spacing: -.02em;
}
.stat-card__label {
  margin-top: var(--s2);
  font-size: var(--fs-caption);
  color: var(--txt-2);
  line-height: 1.5;
}

/* ── 17. Testimonial cards — bounded, structured ──────────── */
.testi-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3);
  padding: var(--s6);
  display: flex;
  flex-direction: column;
  gap: var(--s4);
}
.testi-stars {
  color: var(--star-gold);
  letter-spacing: 2px;
  font-size: var(--fs-body-sm);
}
.testi-text {
  font-size: var(--fs-body);
  line-height: 1.65;
  color: var(--txt-1);
  font-style: italic;
}
.testi-author {
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding-top: var(--s3);
  border-top: 1px solid var(--border);
}
.testi-avatar {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--accent);
  color: var(--bg);
  display: grid;
  place-items: center;
  font-size: var(--fs-caption);
  font-weight: 700;
  flex-shrink: 0;
}
.testi-name {
  font-weight: 600;
  font-size: var(--fs-body-sm);
  color: var(--txt-1);
}
.testi-trip {
  font-size: var(--fs-caption);
  color: var(--txt-3);
  margin-top: 1px;
}

/* ── 18. Hero strip — removed ─────────────────────────────── */
/* dead-css sweep 2026-08: the `.hero__strip { display:none }` demotion is gone
   with the rest of the v13 trust-strip family (see the v21 phase J.2.4 note
   near .hero__ctas). .highlights + .trust-strip carry this content now. */

/* ── 19. Final CTA — demote (duplicates booking) ──────────── */
.final-cta {
  padding-block: var(--s8);
  background: var(--bg-2);
}
.final-cta__title {
  font-size: clamp(1.5rem, 3vw, 2.25rem);
}
.final-cta__sub {
  font-size: var(--fs-body-sm);
  margin-bottom: var(--s5);
}
.final-cta__actions {
  gap: var(--s3);
}

/* ── 20. Related (cross-sell) — demote, smaller scale ─────── */
/* Two classes for the same reason as .calc-section.section (:3661): the
   single-class form loses to `section.section` (:6931), so this density
   tightening rendered as 96px/96px instead of the declared 40px/40px. */
.related-section.section {
  padding-block: var(--s7) var(--s8);
}
.related-section .section-head__title {
  font-size: clamp(1.375rem, 2.5vw, 1.75rem);
}
.related-grid {
  gap: var(--s4);
}
.related-card {
  border-radius: var(--r2);
}
.related-card__body {
  padding: var(--s4);
}
.related-card__title {
  font-size: var(--fs-body);
}
.related-card__price {
  font-size: var(--fs-caption);
  color: var(--txt-2);
}
.related-card__price strong {
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
}

/* ── 21. Inclus columns — list breathing room ─────────────── */
.inclus-list {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}
.inclus-item {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  padding: var(--s2) 0;
  font-size: var(--fs-body-sm);
  line-height: 1.55;
}
.inclus-item svg {
  flex-shrink: 0;
  width: 16px;
  height: 16px;
  margin-top: 3px;
}
.inclus-item--yes svg {
  color: var(--accent);
}
.inclus-item--no svg {
  color: var(--txt-3);
}
.inclus-item strong {
  font-weight: 600;
}

/* ── 22. Mobile — collapse breakdown sticky, stack ─────────── */
@media (max-width: 900px) {
  .breakdown {
    position: static;
  }
  .calc-grid {
    grid-template-columns: 1fr;
  }
  .hotel-card__cta {
    padding: var(--s3) var(--s4);
  }
  .stepper__btn {
    width: 36px;
    height: 36px;
  }
}

/* v22 Agent 3 — phone touch targets: the stepper +/- buttons must hit
   44×44 minimum on phones (Apple HIG + WCAG 2.5.5). The ≤900px rule
   above set 36×36 for tablet density; this overrides for phones. */
@media (max-width: 640px) {
  .stepper__btn {
    width: var(--touch-min);
    height: var(--touch-min);
    font-size: 1.375rem;
  }
  .stepper {
    gap: var(--s4);
  }
  /* v26 mobile-ux: tighten stepper row density so the 2-line helper rows don't
     push the running total further down — padding --s3(16px)→--space-2(8px).
     The 44px buttons above set the row height, so vertical rhythm is unchanged. */
  .stepper-item {
    padding: var(--space-2) 0;
  }
  /* v26 mobile-ux: lift helper-copy contrast --txt-3→--txt-2 to match the
     .calc-form-label uplift already shipped (:7343). */
  .stepper-item__info p {
    color: var(--txt-2);
  }
}

/* ── 23. Reduce inline-bold-noise — promote structure ──────── */
.inclus-item strong,
.faq-a strong,
.testi-text strong {
  font-weight: 600;
  color: var(--txt-1);
}

/* End v12 ─────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════
   v15 — Validation, A11y polish, Transparency disclaimers
   Pairs with _v15_a11y_migrate.py + booking-form.js validate()
   ══════════════════════════════════════════════════════════ */

/* ── Booking form validation states ───────────────────────── */
.bform-field input.is-invalid,
.bform-field textarea.is-invalid {
  border-color: var(--danger);
  box-shadow: 0 0 0 3px rgba(208, 68, 68, .12);
  background: rgba(208, 68, 68, .04);
}
.bform-field input.is-invalid:focus,
.bform-field textarea.is-invalid:focus {
  outline: none;
  border-color: var(--danger);
  box-shadow: 0 0 0 4px rgba(208, 68, 68, .22);
}
.bform-field input[aria-invalid="true"] + .bf-field-err,
.bform-field input + .bf-field-err {
  /* The hidden attribute on the <p> handles default visibility,
     but we style the visible state here */
}
.bf-field-err {
  margin: 6px 0 0;
  font-size: var(--fs-caption);
  color: var(--danger);
  font-weight: 500;
  display: flex;
  align-items: flex-start;
  gap: 6px;
  line-height: 1.4;
}
.bf-field-err::before {
  content: "⚠";
  display: inline-block;
  font-size: var(--fs-body-sm);
  flex-shrink: 0;
  margin-top: -1px;
}
.bf-field-hint {
  margin: 4px 0 0;
  font-size: var(--fs-caption);
  color: var(--txt-3, #8a99a8);
  line-height: 1.45;
  font-style: italic;
}

/* Required asterisk colored for visibility */
.bform-field .req {
  color: var(--danger);
  font-weight: 700;
  margin-left: 2px;
}

/* ── Validation banner above WhatsApp preview ─────────────── */
.bf-validation-banner {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  margin-bottom: 12px;
  background: rgba(208, 68, 68, .08);
  border: 1px solid rgba(208, 68, 68, .25);
  border-radius: var(--r2, 8px);
  color: var(--danger);
  font-size: var(--fs-body-sm);
  font-weight: 500;
  line-height: 1.4;
}
.bf-validation-banner svg {
  color: var(--danger);
  flex-shrink: 0;
}
:root[data-theme="light"] .bf-validation-banner {
  background: rgba(208, 68, 68, .06);
  color: var(--danger);
}

/* ── Disabled send button (when form invalid) ─────────────── */
.btn.is-disabled,
.btn--wa.is-disabled,
.btn--ghost.is-disabled {
  pointer-events: none;
  opacity: .5;
  cursor: not-allowed;
  filter: grayscale(.4);
}

/* dead-css sweep 2026-08: .hero-fineprint (à-partir-de disclaimer) base rule
   deleted — no page has carried the element since the v14 hero rewrite. The
   class survives only as a colour-list entry further down; harmless. */

/* ── Date chips: keyboard focus + active visual ──────────── */
.date-chip:focus-visible {
  outline: 2px solid var(--accent, var(--mint));
  outline-offset: 2px;
}
.date-chip[aria-checked="true"] {
  /* Already styled by .date-chip.active in v12; aria-checked mirror */
  background: var(--accent, var(--mint));
  color: var(--bg, #0a0c12);
  border-color: var(--accent, var(--mint));
  font-weight: 600;
}

/* ── Single-hotel mode: hide hotel select group ──────────── */
[data-single-hotel="true"] {
  display: none !important;
}

/* End v15 ─────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════
   v15 — Info block section (Paiement / Annulation / Formalités / Assurance)
   Native <details>/<summary> for the accordion behavior — zero JS,
   keyboard-accessible by default, screen-reader friendly.
   ══════════════════════════════════════════════════════════ */

.info-block-section {
  background: var(--bg, #0a0c12);
}
.info-block-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(320px, 100%), 1fr));
  gap: var(--s4, 16px);
  /* start, not stretch: an open card grew its row, stretching the CLOSED
     sibling to the same height → it showed a tall empty box ("others open
     empty" bug). align-items:start lets each card own its height. */
  align-items: start;
}

/* ── Card (collapsible) ───────────────────────────────────── */
.info-card {
  background: var(--bg-card, rgba(255,255,255,.03));
  border: 1px solid var(--border, rgba(255,255,255,.08));
  border-radius: var(--r3, 12px);
  overflow: hidden;
  transition: border-color var(--t-fast) ease, box-shadow var(--t-fast) ease;
}
.info-card[open] {
  border-color: var(--border-hi, rgba(255,255,255,.16));
  box-shadow: 0 4px 20px rgba(0, 0, 0, .04);
}
.info-card[open] .info-card__chevron {
  transform: rotate(180deg);
}

/* ── Summary (the always-visible row) ─────────────────────── */
.info-card__head {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 18px 20px;
  cursor: pointer;
  list-style: none;
  user-select: none;
  font-weight: 600;
  font-size: var(--fs-body);
  color: var(--txt-1, #fbf8f1);
  transition: background var(--t-fast) ease;
}
.info-card__head::-webkit-details-marker { display: none; }
.info-card__head:hover { background: rgba(255, 255, 255, .02); }
.info-card__head:focus-visible {
  outline: 2px solid var(--accent, var(--mint));
  outline-offset: -2px;
}

.info-card__icon {
  width: 36px;
  height: 36px;
  border-radius: var(--r3);
  background: var(--accent-dim, rgba(156, 232, 178, .12));
  color: var(--accent, var(--mint));
  display: grid;
  place-items: center;
  flex-shrink: 0;
}

.info-card__title {
  flex: 1;
  letter-spacing: -.005em;
}

.info-card__chevron {
  flex-shrink: 0;
  color: var(--txt-3, #8a99a8);
  transition: transform var(--t-fast) var(--ease-snap);
}

/* ── Body (the expanded content) ──────────────────────────── */
.info-card__body {
  padding: 4px 20px 22px;
  font-size: var(--fs-body-sm);
  line-height: 1.65;
  color: var(--txt-2, #c9cdd4);
}
.info-card__body > * + * { margin-top: 14px; }

.info-card__lede {
  font-weight: 500;
  color: var(--txt-1, #fbf8f1);
}

.info-card__note {
  margin-top: 14px;
  padding: 12px 14px;
  background: rgba(156, 232, 178, .06);
  border-left: 3px solid var(--accent, var(--mint));
  border-radius: 0 8px 8px 0;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
}
.info-card__note strong { color: var(--txt-1, #fbf8f1); }

/* ── Lists inside body ────────────────────────────────────── */
.info-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.info-list li {
  position: relative;
  padding-left: 18px;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
}
.info-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 9px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--accent, var(--mint));
}
.info-list li strong {
  color: var(--txt-1, #fbf8f1);
  font-weight: 600;
}

/* Tiered list (annulation cancellation thresholds) */
.info-list--tiered li {
  padding: 10px 14px 10px 32px;
  background: rgba(255, 255, 255, .02);
  border-radius: var(--r2);
  border: 1px solid var(--border, var(--border));
}
.info-list--tiered li::before {
  left: 14px;
  top: 18px;
}
:root[data-theme="light"] .info-list--tiered li {
  background: rgba(0, 44, 81, .03);
  border-color: rgba(0, 44, 81, .08);
}

/* ── Mobile ──────────────────────────────────────────────── */
@media (max-width: 768px) {
  .info-block-grid {
    grid-template-columns: 1fr;
  }
  .info-card__head {
    padding: 16px 16px;
    font-size: var(--fs-body-sm);
  }
  .info-card__body {
    padding: 4px 16px 18px;
  }
}

/* End v15 info-block ──────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════
   v16 — Design audit fixes (selective)
   Implements Priority 1 + Priority 2 + 3 items from the
   external design-system audit. Skips items already addressed
   in v12/v14/v15 (verified by live inspection).
   ══════════════════════════════════════════════════════════ */

/* ── P1-A · Ghost button contrast on hero contexts ──────────
   Original .btn--ghost: transparent bg, 25% white border, txt-1 color.
   Over a hero photo with bright regions (sand, sky), text and border
   both fade. Fix: scope only to hero contexts — give a frosted-glass
   backdrop, stronger border, and a text-shadow safety net. */
.home-hero .btn--ghost,
.hero .btn--ghost {
  background: rgba(0, 0, 0, .35);
  border: 1.5px solid rgba(255, 255, 255, .55);
  color: #fff;
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  text-shadow: 0 1px 2px rgba(0, 0, 0, .35);
  font-weight: 600;
  transition: background var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
}
.home-hero .btn--ghost:hover,
.hero .btn--ghost:hover {
  background: rgba(0, 0, 0, .55);
  border-color: rgba(255, 255, 255, .85);
  transform: translateY(-1px);
}
:root[data-theme="light"] .home-hero .btn--ghost,
:root[data-theme="light"] .hero .btn--ghost {
  background: rgba(255, 255, 255, .85);
  border-color: rgba(0, 44, 81, .25);
  color: var(--navy, var(--navy));
  text-shadow: none;
}

/* v21 phase H: .calc-cta-hint rules removed — HTML element was
   deleted from all 5 trip pages in phase E.2 (calculator UI is
   self-explanatory, didn't need the explainer copy). */

/* ── P2-C · Destination filter pills on homepage ───────────
   Sits above the trip-card grid. Active state matches tier-tab styling.
   On filter change, JS toggles trip cards via data-region attribute. */
.dest-filter {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  justify-content: center;
  margin: var(--s5, 24px) auto var(--s7, 48px);
  max-width: 100%;
}
.dest-filter__pill {
  padding: 8px 16px;
  background: transparent;
  border: 1px solid var(--border-hi, rgba(255, 255, 255, .16));
  border-radius: var(--r4);
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--txt-2, #c9cdd4);
  cursor: pointer;
  transition: border-color var(--t-fast), color var(--t-fast), background var(--t-fast);
  letter-spacing: .02em;
}
.dest-filter__pill:hover {
  border-color: var(--accent, var(--mint));
  color: var(--txt-1, #fbf8f1);
  background: var(--accent-dim, rgba(156, 232, 178, .08));
}
.dest-filter__pill[aria-pressed="true"] {
  background: var(--accent, var(--mint));
  color: var(--bg, #0a0c12);
  border-color: var(--accent, var(--mint));
}
.dest-filter__pill .dest-filter__count {
  display: inline-block;
  margin-left: 6px;
  font-size: var(--fs-2xs);
  font-weight: 500;
  opacity: .7;
}

/* Hidden trip cards via filter — collapsed nicely */
.trip-card.is-filtered-out {
  display: none;
}

/* ── P1-C · Homepage contact form ──────────────────────────
   Sits inside #contact section. Name + city + phone + voyage select.
   On submit, builds wa.me link with prefilled message. */
/* Single column. The fields themselves now sit in .contact-form__grid, so the
   form's own children are the field block, the submit row and the status line —
   stacking them. This used to be repeat(auto-fit, minmax(240px,1fr)), which
   would now drop the submit button beside the fields. */
.contact-form {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s4, 16px);
  margin-top: var(--s5, 24px);
  padding: var(--s5, 24px);
  background: var(--bg-card, rgba(255, 255, 255, .03));
  border: 1px solid var(--border-hi, rgba(255, 255, 255, .16));
  border-radius: var(--r3, 12px);
}
/* Responsive fix: the trip <select>'s longest <option> was forcing the contact
   grid's 1fr column to its ~442px min-content, clipping the form on narrow
   phones. Let the grid items + form controls shrink below their intrinsic min. */
.contact-section > * { min-width: 0; }
.contact-form,
.contact-form__field { min-width: 0; }
.contact-form input,
.contact-form select,
.contact-form textarea { min-width: 0; max-width: 100%; }
.contact-form__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.contact-form__field label {
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--txt-3, #8a99a8);
}
.contact-form__field input,
.contact-form__field select {
  padding: 12px 14px;
  background: var(--bg, #0a0c12);
  border: 1px solid var(--border, rgba(255, 255, 255, .08));
  border-radius: var(--r2, 8px);
  color: var(--txt-1, #fbf8f1);
  font-size: var(--fs-body-sm);
  font-family: inherit;
  transition: border-color var(--t-fast);
}
.contact-form__field input:focus,
.contact-form__field select:focus {
  outline: none;
  border-color: var(--accent, var(--mint));
  box-shadow: 0 0 0 3px var(--accent-dim, rgba(156, 232, 178, .15));
}
.contact-form__submit-wrap {
  grid-column: 1 / -1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 8px;
}
.contact-form__hint {
  font-size: var(--fs-caption);
  color: var(--txt-3, #8a99a8);
  font-style: italic;
  flex: 1;
  min-width: 200px;
  line-height: 1.45;
}

/* ── P3-D · Social media links in footer ───────────────────
   Discrete row of icon links. Even as placeholder hrefs, signals brand
   maturity and is a known trust factor (audit P3-D). */
.footer-social {
  display: flex;
  gap: 10px;
  margin-top: var(--s4, 16px);
  flex-wrap: wrap;
}
.footer-social a {
  /* 44×44 hit area = WCAG 2.5.5 AAA enhanced target size
     (was 36×36 which already met the 2.5.8 AA 24×24 minimum). */
  width: 44px;
  height: 44px;
  border-radius: 50%;
  background: var(--bg-card, rgba(255, 255, 255, .04));
  border: 1px solid var(--border, rgba(255, 255, 255, .08));
  display: grid;
  place-items: center;
  color: var(--txt-2, #c9cdd4);
  transition: background var(--t-fast), color var(--t-fast), border-color var(--t-fast), transform var(--t-fast);
  text-decoration: none;
}
.footer-social a:hover {
  background: var(--accent, var(--mint));
  color: var(--bg, #0a0c12);
  border-color: var(--accent, var(--mint));
  transform: translateY(-2px);
}
.footer-social a svg {
  width: 16px;
  height: 16px;
}

/* ── Mobile tuning ─────────────────────────────────────── */
@media (max-width: 640px) {
  .dest-filter {
    justify-content: flex-start;
    overflow-x: auto;
    flex-wrap: nowrap;
    padding: 4px;
    margin-inline: -16px;
    padding-inline: 16px;
  }
  .dest-filter__pill {
    flex-shrink: 0;
  }
  .contact-form {
    padding: var(--s4, 16px);
  }
  /* One field per row on phones — two 220px columns would otherwise survive
     down to ~470px and squeeze the labels. */
  .contact-form__grid {
    grid-template-columns: 1fr;
  }
  .contact-form__submit-wrap {
    flex-direction: column;
    align-items: stretch;
  }
  .contact-form__submit-wrap .btn {
    width: 100%;
    justify-content: center;
  }
}

/* End v16 ─────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   v18 — Neo-brutalist hotel cards
   Adapted from a Uiverse pattern: bold border, hard offset shadow
   (no blur), tilted tag, cut corner with star, dashed price divider
   with scissors, hard-shadow CTA. All within Alliance Travel's palette
   (mint var(--mint), navy var(--navy), cream #fbf8f1).

   Overrides v1/v12 .hotel-card rules via source-order cascade.
   ════════════════════════════════════════════════════════════ */

/* ── Card shell ─────────────────────────────────────────────── */
.hotel-card {
  --hc-text:        var(--txt-1, #fbf8f1);
  --hc-bg:          var(--bg-card, #0f1218);
  --hc-accent:      var(--accent, #9ce8b2);
  --hc-accent-dim:  var(--accent-dim, rgba(156, 232, 178, .14));
  --hc-shadow:      #000;
  --hc-border:      var(--accent, #9ce8b2);
  --hc-pattern:     rgba(255, 255, 255, .04);

  position: relative;
  width: 100%;
  background: var(--hc-bg);
  color: var(--hc-text);
  border: 3px solid var(--hc-border);
  border-radius: var(--r3);
  box-shadow:
    8px 8px 0 var(--hc-shadow),
    inset 0 0 0 1px rgba(255, 255, 255, .03);
  transition: transform var(--t-base) var(--ease-spring),
              box-shadow var(--t-base) var(--ease-spring);
  overflow: hidden;
  cursor: pointer;
  display: flex;
  flex-direction: column;
  font-family: inherit;
  isolation: isolate;
}

:root[data-theme="light"] .hotel-card {
  --hc-text:        #002c51;
  --hc-bg:          #ffffff;
  --hc-accent:      #237a4a;
  --hc-accent-dim:  rgba(35, 122, 74, .10);
  --hc-shadow:      #002c51;
  --hc-border:      #002c51;
  --hc-pattern:     rgba(0, 44, 81, .04);
}

.hotel-card:hover {
  transform: translate(-4px, -4px);
  box-shadow:
    12px 12px 0 var(--hc-shadow),
    inset 0 0 0 1px rgba(255, 255, 255, .04);
}

.hotel-card:active {
  transform: translate(2px, 2px);
  box-shadow: 4px 4px 0 var(--hc-shadow);
  transition: transform 80ms ease, box-shadow 80ms ease;
}

/* Cut-corner accent triangle (top-right) */
.hotel-card::before {
  content: "";
  position: absolute;
  top: -28px;
  right: -28px;
  width: 64px;
  height: 64px;
  background: var(--hc-accent);
  transform: rotate(45deg);
  z-index: 4;
  pointer-events: none;
}

/* Star inside the cut corner */
.hotel-card::after {
  content: "★";
  position: absolute;
  top: 6px;
  right: 10px;
  color: var(--hc-bg);
  font-size: var(--fs-body-sm);
  font-weight: 800;
  z-index: 5;
  pointer-events: none;
  line-height: 1;
}

/* Subtle grid pattern behind everything (shows on hover) */
.hotel-card__body::before {
  content: "";
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, var(--hc-pattern) 1px, transparent 1px),
    linear-gradient(to bottom, var(--hc-pattern) 1px, transparent 1px);
  background-size: 8px 8px;
  pointer-events: none;
  opacity: 0;
  transition: opacity var(--t-base) ease;
  z-index: 0;
}
.hotel-card:hover .hotel-card__body::before {
  opacity: 1;
}

/* ── Photo block ────────────────────────────────────────────── */
.hotel-card__img {
  aspect-ratio: 16 / 9;   /* v27 density: 16/10→16/9 shaves ~17px/card */
  position: relative;
  overflow: hidden;
  background: var(--hc-accent-dim);
  border-bottom: 3px solid var(--hc-border);
}

.hotel-card__photo {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  transition: transform var(--t-slow) var(--ease-spring);
  filter: contrast(1.04) saturate(1.05);
}
.hotel-card:hover .hotel-card__photo {
  transform: scale(1.05);
}

/* Diagonal stripe overlay on photo bottom — adds the brutalist texture */
.hotel-card__img::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 28%;
  background:
    repeating-linear-gradient(
      45deg,
      rgba(0, 0, 0, .35),
      rgba(0, 0, 0, .35) 8px,
      transparent 8px,
      transparent 16px
    ),
    linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, .55) 100%);
  pointer-events: none;
  z-index: 1;
  mix-blend-mode: multiply;
}

/* ── Tilted ribbon (tier badge) ─────────────────────────────── */
.hotel-card__ribbon {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 3;
  background: var(--hc-bg);
  color: var(--hc-text);
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  padding: 5px 10px;
  border: 2px solid var(--hc-border);
  border-radius: var(--r-tag);
  box-shadow: 3px 3px 0 var(--hc-shadow);
  transform: rotate(-3deg);
  transition: transform var(--t-base) var(--ease-spring),
              box-shadow var(--t-base) ease;
}
.hotel-card:hover .hotel-card__ribbon {
  transform: rotate(2deg) scale(1.06);
  box-shadow: 4px 4px 0 var(--hc-shadow);
}

/* ── Body ──────────────────────────────────────────────────── */
.hotel-card__body {
  position: relative;
  padding: 14px 16px 16px;   /* v27 density: was 18px 20px 20px */
  display: flex;
  flex-direction: column;
  gap: 8px;                   /* v27 density: was 10px */
  flex: 1;
  z-index: 1;
}

.hotel-card__body > * {
  position: relative;
  z-index: 1;
}

.hotel-card__stars {
  font-size: var(--fs-body-sm);
  color: var(--star-gold);
  letter-spacing: 2px;
  line-height: 1;
}

.hotel-card__name {
  font-size: var(--fs-body);           /* v27 density: was 17px */
  font-weight: 700;
  color: var(--hc-text);
  line-height: 1.25;
  letter-spacing: -.005em;
  margin: 0;
}

/* Amenity pills — bordered, subtle */
.hotel-card__amenities {
  display: flex;
  gap: 6px;
  flex-wrap: wrap;
  margin-top: 2px;
  margin-bottom: 4px;
}
.hotel-card .amenity-pill {
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--hc-accent);
  background: var(--hc-accent-dim);
  border: 1.5px solid var(--hc-accent);
  border-radius: var(--r4);
  padding: 3px 9px;
  line-height: 1.4;
}

/* ── Price block — dashed divider with scissors ─────────── */
.hotel-card__price {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 6px;           /* v27 density: was 8px */
  padding-top: 14px;         /* v27 density: was 18px */
  border-top: 2px dashed rgba(0, 0, 0, 0);
  background:
    linear-gradient(to right,
      var(--hc-text) 0,
      var(--hc-text) 6px,
      transparent 6px,
      transparent 14px
    ) top left / 14px 2px repeat-x;
  background-position: top center;
  /* Note: the `border-top: 2px dashed` plus background-position trick gives
     a sharp dashed line that matches the brutalist aesthetic better than
     the default browser dashed rendering. */
}

.hotel-card__price::before {
  content: "✂";
  position: absolute;
  top: -10px;
  left: 50%;
  transform: translateX(-50%) rotate(90deg);
  background: var(--hc-bg);
  padding: 0 6px;
  font-size: var(--fs-caption);
  color: var(--hc-text);
  opacity: .6;
  line-height: 1;
}

.hotel-card__price-label {
  font-size: var(--fs-2xs);
  font-weight: 800;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--hc-text);
  opacity: .6;
}

.hotel-card__price strong {
  font-size: 28px;
  font-weight: 800;
  color: var(--hc-text);
  font-variant-numeric: tabular-nums;
  line-height: 1.1;
  letter-spacing: -.015em;
  display: inline-block;
  position: relative;
  align-self: flex-start;
  padding: 0 2px;
}
/* Underline accent — a thick mint highlight behind the number */
/* v18 had a mint highlight bar behind the price number (fake-marker effect)
   but it hurt readability on small renders — removed. The bold number alone
   reads as the focal point. */

.hotel-card__price-meta {
  font-size: var(--fs-caption);
  color: var(--hc-text);
  opacity: .65;
  margin-top: 4px;
  line-height: 1.45;
}

/* ── CTA — solid accent with hard offset shadow ─────────── */
.hotel-card__cta {
  position: relative;
  width: 100%;
  margin-top: 10px;          /* v27 density: was 14px */
  background: var(--hc-accent);
  color: var(--hc-shadow);
  font-size: var(--fs-caption);
  font-weight: 800;
  padding: 10px 16px;        /* v27 density: was 12px 16px */
  border: 2.5px solid var(--hc-shadow);
  border-radius: var(--r2);
  box-shadow: 4px 4px 0 var(--hc-shadow);
  cursor: pointer;
  transition: transform var(--t-fast) ease, box-shadow var(--t-fast) ease, background var(--t-fast) ease;
  text-transform: uppercase;
  letter-spacing: .05em;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  overflow: hidden;
}

/* Sliding shimmer on hover */
.hotel-card__cta::before {
  content: "";
  position: absolute;
  top: 0; left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(
    90deg,
    transparent 0%,
    rgba(255, 255, 255, .35) 50%,
    transparent 100%
  );
  transition: left var(--t-slow) ease;
  pointer-events: none;
}

/* Trailing arrow */
.hotel-card__cta::after {
  content: "→";
  display: inline-block;
  font-weight: 600;
  transition: transform var(--t-fast) ease;
}

.hotel-card__cta:hover {
  transform: translate(-2px, -2px);
  box-shadow: 6px 6px 0 var(--hc-shadow);
  background: var(--hc-accent);
  filter: brightness(1.05);
}
.hotel-card__cta:hover::before { left: 100%; }
.hotel-card__cta:hover::after  { transform: translateX(4px); }

.hotel-card__cta:active {
  transform: translate(2px, 2px);
  box-shadow: 1px 1px 0 var(--hc-shadow);
  transition: transform 80ms ease, box-shadow 80ms ease;
}

/* Selected hotel — solid CTA flips into a "✓ Sélectionné" state */
.hotel-card.selected {
  border-color: var(--hc-accent);
  box-shadow: 8px 8px 0 var(--hc-accent);
}
.hotel-card.selected:hover {
  box-shadow: 12px 12px 0 var(--hc-accent);
}
.hotel-card.selected .hotel-card__cta {
  background: var(--hc-shadow);
  color: var(--hc-accent);
}
.hotel-card.selected .hotel-card__cta::after {
  content: "✓";
}

/* ── Mobile tuning ──────────────────────────────────────── */
@media (max-width: 640px) {
  /* v26 mobile-ux: lighten stacked cards — border 3px→2px, hard-shadow offset
     8px→4px so 6 full-width cards read shorter/lighter. The mint
     .hotel-card.selected ring is defined elsewhere and is left intact. */
  .hotel-card {
    border-width: 2px;
    box-shadow: 4px 4px 0 var(--hc-shadow);
  }
  .hotel-card:hover {
    transform: translate(-2px, -2px);
    box-shadow: 6px 6px 0 var(--hc-shadow);
  }

  /* v22 Agent 3 — when cards stack in 1-col, the 16/10 photo gets too
     wide and pulls the card too tall. Switch to 4/3 so stacked cards
     keep uniform image heights and the price block stays in reach. */
  .hotel-card__img {
    aspect-ratio: 4 / 3;
  }

  /* v22 Agent 3 — readable price even on tiny screens. */
  .hotel-card__price strong { font-size: 24px; }
  .hotel-card__price-meta   { font-size: var(--fs-body-sm); }

  /* v22 Agent 3 — CTA hit area enforced to 44px (WCAG 2.5.5).
     Previous 11/14 padding × 12px font-size totalled ≈34px tap height. */
  .hotel-card__cta {
    padding: 13px 16px;
    font-size: var(--fs-caption);
    min-height: var(--touch-min);
  }

  /* v22 Agent 3 — stars upsized so 5-star rendering doesn't look like noise. */
  .hotel-card__stars { font-size: var(--fs-body); }
}

/* ── Reduced motion ─────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .hotel-card,
  .hotel-card__photo,
  .hotel-card__ribbon,
  .hotel-card__cta,
  .hotel-card__cta::before,
  .hotel-card__cta::after,
  .hotel-card__body::before {
    transition: none !important;
  }
  .hotel-card:hover {
    transform: none;
    box-shadow: 8px 8px 0 var(--hc-shadow);
  }
  .hotel-card:hover .hotel-card__photo {
    transform: none;
  }
}

/* End v18 ──────────────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   v20 — Trip-card hover refinement (replaces v19 slide-up pattern)
   v19 yanked the title + subtitle 58px upward on hover to make room
   for a separate price + CTA strip. The motion popped elements out
   of the visual frame and felt incoherent. v20 keeps every meaningful
   element ANCHORED at all times:
     • monument disc top-left (always visible)
     • price chip top-right (always visible — glass-blur, accent-tint)
     • title + 2-line description bottom (always visible)
     • "Voir ce voyage" pill bottom-right (always visible)
   Hover only does subtle moves — no element travels more than 4px:
     • card lifts -4px
     • image gently scales 1.05
     • monument & price chip border tints to accent
     • CTA pill fills with accent + arrow nudges +3px right
     • bottom accent line slides in left → right
   No translateY shenanigans on text. Same DOM hooks as v19; the
   monument-injection migration script is unaffected.
   ══════════════════════════════════════════════════════════════ */

/* ── Grid container ───────────────────────────────────────── */
.trips-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
  max-width: 1320px;
  margin: 0 auto;
  padding: 0;
}

/* ── Card root ────────────────────────────────────────────── */
.trip-card {
  --tc-fg: #fff;
  --tc-fg-muted: rgba(255, 255, 255, .82);
  --tc-fg-faint: rgba(255, 255, 255, .55);
  --tc-accent: var(--tc-region-accent, var(--accent, #9ce8b2));
  --tc-ink: #050609;   /* on-accent CTA text ink (matches the card bg hex) */

  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  border-radius: var(--r-card);
  overflow: hidden;
  background: #050609;
  color: var(--tc-fg);
  text-decoration: none;
  isolation: isolate;
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .05) inset,
    0 10px 22px -12px rgba(0, 0, 0, .55),
    0 22px 44px -24px rgba(0, 0, 0, .35);
  transition: transform var(--t-base) var(--ease-spring),
              box-shadow var(--t-base) var(--ease-spring);
  cursor: pointer;
  font-family: inherit;
}

.trip-card:hover {
  transform: translateY(-4px);
  box-shadow:
    0 1px 0 rgba(255, 255, 255, .07) inset,
    0 14px 28px -12px rgba(0, 0, 0, .6),
    0 30px 56px -24px rgba(0, 0, 0, .45);
}

.trip-card:focus-visible {
  outline: 3px solid var(--tc-accent);
  outline-offset: 4px;
}

/* Per-region accent — overrides default mint with the trip's signature hue */
.trip-card[data-region="egypt"]      { --tc-region-accent: var(--warn); }
.trip-card[data-region="azerbaijan"] { --tc-region-accent: #e07b5a; }
.trip-card[data-region="istanbul"]   { --tc-region-accent: #5cb1c1; }
.trip-card[data-region="malaysia"]   { --tc-region-accent: #8acaa1; }
.trip-card[data-region="sharm"]      { --tc-region-accent: #5cc4c1; }
.trip-card[data-region="omra"]       { --tc-region-accent: var(--accent); }

/* Omra is the eighth tile on the homepage and the one destination with no
   photograph in the library. Rather than borrow an unrelated image, the card
   is a designed surface: a deep green field with the Kaaba glyph at low
   opacity. It also fills the orphan slot the 7-card grid left (A23/D18). */
.trip-card[data-region="omra"] .trip-card__art {
  background: radial-gradient(120% 90% at 50% 0%, #14342a 0%, #0a1a16 55%, #050609 100%) !important;
}
.trip-card__glyph {
  position: absolute;
  inset: 0;
  margin: auto;
  width: 56%;
  height: 56%;
  color: var(--accent);
  opacity: .18;
  transition: opacity var(--t-slow) var(--ease-spring), transform var(--t-slow) var(--ease-spring);
}
.trip-card:hover .trip-card__glyph {
  opacity: .26;
  transform: scale(1.04);
}

/* ── Image fill behind everything ─────────────────────────── */
.trip-card__hero {
  position: absolute !important;
  inset: 0;
  z-index: 0;
  width: 100%;
  height: 100%;
  background: none !important;
  border: 0 !important;
  margin: 0 !important;
  padding: 0 !important;
  overflow: hidden;
}

.trip-card__art {
  position: absolute;
  inset: 0;
  background: #050609 !important;
  border-radius: 0 !important;
  overflow: hidden;
}

.trip-card__img {
  position: absolute;
  inset: 0;
  width: 100% !important;
  height: 100% !important;
  object-fit: cover;
  object-position: center;
  transition: transform var(--t-slow) var(--ease-spring);
  filter: saturate(1.05);
}

.trip-card:hover .trip-card__img {
  transform: scale(1.05);
}

/* Gradient overlay — slightly stronger bottom band so the always-
   visible title + 2-line description read cleanly without needing a
   slide-up reveal. Keeps top half airy so monument + price chip are
   legible, then darkens through the lower 40% of the frame. */
.trip-card__hero::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg,
      rgba(0, 0, 0, .35) 0%,
      rgba(0, 0, 0, .08) 28%,
      rgba(0, 0, 0, .35) 55%,
      rgba(0, 0, 0, .80) 82%,
      rgba(0, 0, 0, .96) 100%);
  pointer-events: none;
  z-index: 1;
  transition: opacity var(--t-base) ease;
}

/* "Égypte · Juin 2026" floating chip — redundant once region accent
   line + monument convey identity. Hidden in v20 too. */
.trip-card__flag {
  display: none !important;
}

/* ── Price chip top-right (always visible — repurposed from the old
   .trip-card__from element so the markup stays unchanged) ─────── */
.trip-card__from {
  position: absolute !important;
  top: 14px;
  right: 14px;
  z-index: 4;
  display: inline-flex !important;
  flex-direction: column !important;
  align-items: flex-end;
  gap: 1px;
  margin: 0 !important;
  padding: 7px 12px !important;
  background: rgba(0, 0, 0, .42) !important;
  border: 1.5px solid rgba(255, 255, 255, .25) !important;
  border-radius: var(--r4) !important;
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  color: var(--tc-fg-muted) !important;
  font-size: var(--fs-2xs) !important;
  font-weight: 600 !important;
  letter-spacing: .12em !important;
  text-transform: uppercase !important;
  line-height: 1 !important;
  white-space: nowrap;
  transition: border-color var(--t-base) ease, background var(--t-base) ease;
}
.trip-card__from > strong {
  display: block;
  font-size: var(--fs-caption);
  font-weight: 700;
  letter-spacing: 0;
  text-transform: none;
  color: var(--tc-fg);
  margin: 3px 0 0 !important;
}
.trip-card:hover .trip-card__from {
  border-color: var(--tc-accent) !important;
  background: rgba(0, 0, 0, .58) !important;
}

/* ── Monument SVG icon top-left ───────────────────────────── */
.trip-card__monument {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 4;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(0, 0, 0, .42);
  border: 1.5px solid rgba(255, 255, 255, .25);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  display: grid;
  place-items: center;
  color: var(--tc-fg);
  transition: transform var(--t-base) var(--ease-spring),
              border-color var(--t-base) ease,
              background var(--t-base) ease;
}
.trip-card:hover .trip-card__monument {
  transform: rotate(-4deg) scale(1.05);
  border-color: var(--tc-accent);
  background: rgba(0, 0, 0, .58);
}
.trip-card__monument svg {
  width: 20px;
  height: 20px;
  stroke: currentColor;
  stroke-width: 1.8;
  fill: none;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* ── Body content (overlaid on photo, anchored to bottom) ─── */
/* Reserve bottom space for the always-visible CTA pill so it doesn't
   overlap with the title/subtitle stack. */
.trip-card__body {
  position: absolute !important;
  inset: 0 !important;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 22px 22px 70px !important;
  z-index: 3;
  background: none !important;
  border: 0 !important;
  margin: 0 !important;
  pointer-events: none;
}

/* Hide chrome the new design doesn't surface (date/duration meta + tags) */
.trip-card__meta { display: none !important; }
.trip-card__tags { display: none !important; }

.trip-card__title {
  font-family: var(--font-display, "DM Sans", system-ui, sans-serif);
  font-size: clamp(20px, 1.6vw, 26px);
  font-weight: 700;
  line-height: 1.18;
  letter-spacing: -.012em;
  color: var(--tc-fg);
  margin: 0 0 8px;
  text-shadow: 0 2px 18px rgba(0, 0, 0, .45);
}

.trip-card__subtitle {
  font-size: var(--fs-caption);
  line-height: 1.55;
  color: var(--tc-fg-muted);
  margin: 0;
  max-width: 36ch;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  text-shadow: 0 1px 12px rgba(0, 0, 0, .35);
}

/* ── CTA pill — always visible, bottom-left of the card ────── */
/* The original markup carries <span>Voir ce voyage</span><svg arrow/>
   plus the v19-injected <span class="trip-card__cta-price"> — we hide
   the duplicate price (it's surfaced as the top-right chip now) and
   render the action span as a glass pill. */
/* ONE pill, containing both the label and the arrow.
   It used to be two: the <span> drew a left-rounded half and the <svg> a
   right-rounded cap, pulled together with margin-left:-6px. That never
   rendered as designed, because the span set border-radius twice in the same
   block — "999px 0 0 999px" and then, seven lines later, a plain "999px" that
   won. So the label closed into a complete pill and the arrow's cap hung off
   its right edge on the photo, while border-right:0 left that edge open.
   Putting the background on the container removes the seam, the negative
   margin and the whole class of bug: the arrow is inside the pill because it
   is inside the element that IS the pill. */
.trip-card__cta {
  position: absolute !important;
  left: 22px;
  bottom: 20px;
  z-index: 4;
  display: inline-flex !important;
  align-items: center;
  gap: 6px;
  padding: 7px 14px;
  border-radius: var(--r4);
  background: rgba(255, 255, 255, .12);
  border: 1.5px solid rgba(255, 255, 255, .28);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  opacity: 1;
  transform: none;
  pointer-events: auto;
  color: var(--tc-fg) !important;
  transition: background var(--t-fast) ease, border-color var(--t-fast) ease, color var(--t-fast) ease;
}
/* The label is now just text inside the pill — the pill itself is the parent.
   The explicit colour stays (rather than inherit) so the colour cascade around
   this element is left exactly as it was: only the background moved. */
.trip-card__cta > span:not(.trip-card__cta-price) {
  display: inline-flex;
  align-items: center;
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--tc-fg);
  white-space: nowrap;
}

/* Just the glyph now: no cap, no backing, no negative margin. The earlier
   version carried its own padding/border and needed box-sizing:content-box to
   survive the sitewide border-box reset, because width:14px minus 14px of
   padding minus the border computed to a content box of -1px and the chevron
   had no room to draw (1f4de63). With the padding gone that arithmetic cannot
   recur, but content-box is kept so width/height mean the glyph itself. */
.trip-card__cta > svg {
  display: inline-block !important;
  width: 14px;
  height: 14px;
  flex-shrink: 0;
  box-sizing: content-box;
  color: var(--tc-fg);
  transition: transform var(--t-fast) ease, color var(--t-fast) ease;
}

/* Hover paints the pill once, on the container. The two children keep their
   own colour declarations, exactly as before — nothing about the colour
   cascade here changed, only which element carries the background. */
.trip-card:hover .trip-card__cta {
  background: var(--tc-accent);
  border-color: transparent;
}
.trip-card:hover .trip-card__cta > span:not(.trip-card__cta-price),
.trip-card:hover .trip-card__cta > svg {
  color: var(--tc-ink);
}
.trip-card:hover .trip-card__cta > svg {
  transform: translateX(3px);
}

/* The duplicate price strip injected by _v19_inject_monuments.py is
   no longer needed — price lives in the top-right chip now. */
.trip-card__cta-price { display: none !important; }

/* ── Region accent strip — bottom border line on hover ────── */
.trip-card::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 3px;
  background: var(--tc-accent);
  z-index: 5;
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform var(--t-slow) var(--ease-spring);
}
.trip-card:hover::after {
  transform: scaleX(1);
}

/* ── Mobile tuning ────────────────────────────────────────── */
@media (max-width: 640px) {
  .trips-grid {
    grid-template-columns: 1fr;
    gap: 16px;
  }
  .trip-card {
    aspect-ratio: 5 / 6;
  }
  .trip-card__body { padding: 18px 18px 64px !important; }
  .trip-card__from { top: 12px; right: 12px; padding: 6px 10px !important; }
  .trip-card__monument { top: 12px; left: 12px; width: 38px; height: 38px; }
  [dir="rtl"] .trip-card__monument { left: auto; right: 12px; }
  /* Touch devices have no hover — give them the "active" look at rest.
     The background is on the pill now; the children keep carrying their own
     colour, same as the hover rule above. */
  .trip-card__cta {
    left: 18px;
    bottom: 16px;
    background: var(--tc-accent);
    border-color: transparent;
  }
  [dir="rtl"] .trip-card__cta { left: auto; right: 18px; }
  .trip-card__cta > span:not(.trip-card__cta-price),
  .trip-card__cta > svg {
    color: var(--tc-ink);
  }
}

/* ── Reduced motion ──────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .trip-card,
  .trip-card__img,
  .trip-card__cta,
  .trip-card__cta > span,
  .trip-card__cta > svg,
  .trip-card__monument,
  .trip-card__from,
  .trip-card::after {
    transition: none !important;
  }
  .trip-card:hover { transform: none; }
  .trip-card:hover .trip-card__img { transform: none; }
  .trip-card:hover .trip-card__monument { transform: none; }
  .trip-card::after { transform: scaleX(1); }
}

/* End v20 trip-cards ──────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   v19 — Color hierarchy: TOKEN definitions consolidated into the
   canonical :root at the top of this file. Component-level rules
   (cards, hover surfaces, borders, scrollbars, etc.) remain below.
   ══════════════════════════════════════════════════════════════ */

/* ── Apply: nudge the existing component baselines toward the new ladder ── */

/* Body itself sits on --bg (not --bg-2) so the depth ladder reads correctly */
body { background: var(--bg); color: var(--txt-1); }

/* v21 phase D.2: canonical content-card surface baseline.
   All cards listed here share bg-card + border-color. Each card's
   individual block keeps its own padding, gap, radius (some use r1
   instead of r3), and transition — those vary by component shape. */
.testi-card,
.stat-card,
.info-card,
.faq-item,
.contact-form,
.bform-block,
.breakdown,
.upload-zone,
.branch-card,
.hl-card {
  background: var(--bg-card);
  border-color: var(--border);
}

/* Hover surfaces tip up to bg-elev */
.testi-card:hover,
.faq-item.open,
.faq-item[open] {
  background: var(--bg-elev);
}

/* Text colour propagation — anything that previously hardcoded grays gets
   rerouted via cascade to the new --txt-* tokens. */
.section-head__sub,
.bform-hint,
.bform-note,
.contact-form__hint,
.bf-trip-empty,
.hero-fineprint {
  color: var(--txt-3);
}

/* Mint usage discipline — small dim variant for non-CTA mint moments */
.amenity-pill,
.phase-marker {
  background: var(--mint-dim);
  color: var(--accent);
  border-color: var(--border-mint);
}

/* Section backgrounds — some sections used --bg-2 hard-coded inline. Map
   them to the new bg-2 implicitly through the cascade — also support
   `data-elev` attribute for explicit elevation on a wrapper. */

/* Focus rings — single unified token */
*:focus-visible {
  outline: 2px solid var(--ring);
  outline-offset: 3px;
}
.btn:focus-visible,
.hotel-card:focus-visible,
.trip-card:focus-visible,
.tier-tab:focus-visible {
  outline-offset: 4px;
}

/* Borders globally subtle — except hot states */
.bform-field input,
.bform-field select,
.bform-field textarea {
  border-color: var(--border-hi);
}
.bform-field input:focus,
.bform-field select:focus,
.bform-field textarea:focus {
  border-color: var(--mint);
  box-shadow: 0 0 0 3px var(--mint-glow);
}

/* Selection highlight — picks up the brand mint */
::selection {
  background: var(--mint-glow);
  color: var(--txt-1);
}

/* Scrollbar (Webkit) — match the new ladder */
::-webkit-scrollbar { width: 12px; height: 12px; }
::-webkit-scrollbar-track { background: var(--bg-low); }
::-webkit-scrollbar-thumb {
  background: var(--bg-elev);
  border-radius: var(--r4);
  border: 3px solid var(--bg-low);
}
::-webkit-scrollbar-thumb:hover { background: var(--border-hi); }

/* End v19 palette ──────────────────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   Phone cards — now used ONLY by /rendez-vous-visa/.
   The homepage contact section used to render the same six numbers as a
   3×2 grid of these cards, directly below the branches block that already
   listed all six. It now shows two in the contact rail behind a disclosure
   (see .advisor-list), so the .staff-phones wrapper rules that framed the
   grid were deleted with it. The .phone-card rules below stay — the visa
   page still renders them.
   ══════════════════════════════════════════════════════════════ */

.phone-card {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 4px;
  padding: 14px 14px 12px;
  background: var(--bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r2, 8px);
  transition: border-color var(--t-fast) ease, transform var(--t-fast) ease, background var(--t-fast) ease;
}
.phone-card:hover {
  border-color: var(--border-mint);
  transform: translateY(-2px);
  background: var(--bg-low);
}
.phone-card__label {
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.phone-card__num {
  font-family: var(--font-display, "DM Sans", system-ui, sans-serif);
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body);
  font-weight: 600;
  letter-spacing: .03em;
  color: var(--txt-1);
  margin-bottom: 6px;
}
.phone-card__actions {
  display: flex;
  gap: 6px;
  margin-top: auto;
}
.phone-card__btn {
  flex: 1;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  /* v22 follow-up #1: bump from 7/8 to 11/14 to hit WCAG 2.5.5 (44x44).
     Combined with the SVG (13px) + .8125rem text + .01em letter-spacing,
     the button now renders at ~44-46px tall on every viewport. */
  padding: 11px 14px;
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .01em;
  min-height: var(--touch-min, 44px);
  border-radius: var(--r4);
  text-decoration: none;
  border: 1px solid transparent;
  white-space: nowrap;
  transition: background var(--t-fast) ease, color var(--t-fast) ease, border-color var(--t-fast) ease;
}
.phone-card__btn svg {
  flex-shrink: 0;
}
.phone-card__btn--wa {
  background: var(--wa-green);
  color: var(--wa-ink);
}
.phone-card__btn--wa:hover {
  background: var(--wa-green-hov);
  color: var(--wa-ink);
}
.phone-card__btn--call {
  background: var(--bg-elev);
  color: var(--txt-1);
  border-color: var(--border-hi);
}
.phone-card__btn--call:hover {
  border-color: var(--accent);
  color: var(--accent);
}

@media (max-width: 480px) {
  .phone-card {
    padding: 12px 14px 12px;
  }
}

/* End phone-card (visa page) ──────────────────────────────── */

/* ══════════════════════════════════════════════════════════════
   v19.2 — Real agency network
   The agence section now lists 3 OWNED locations instead of 1 HQ +
   4 fictional partner cities. Tighter grid, Google Maps deep-link
   chip on every card, popup gets a matching itinéraire affordance.
   ══════════════════════════════════════════════════════════════ */

/* Three real agencies → three roughly-equal columns at desktop, no
   stretching, no awkward 4th-slot ghost. Falls back to 1 col on mobile
   via the existing breakpoint above. */
.branch-list {
  grid-template-columns: repeat(3, minmax(240px, 1fr));
  max-width: 1080px;
  margin-inline: auto;
}
@media (max-width: 980px) {
  .branch-list {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 640px) {
  .branch-list {
    grid-template-columns: 1fr;
  }
}

/* dead-css sweep 2026-08: .branch-maps (Google-Maps "Itinéraire" chip at the
   foot of each branch card) deleted — its host .branch-card markup was replaced
   by the .branches-bento layout in 921b4f4, so the chip has no element left.
   The equivalent deep-link survives as .amap-popup__maps below. */

/* Map popup — Itinéraire deep-link sits one row below the phone */
.amap-popup__maps {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: 6px;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--txt-2, #c9cdd4) !important;
  text-decoration: none;
  padding: 2px 0;
  letter-spacing: .01em;
}
.amap-popup__maps:hover { text-decoration: underline; }
:root[data-theme="light"] .amap-popup__maps { color: var(--txt-2, #4a5b6f) !important; }

/* End v19.2 agency-network ──────────────────────────────────── */

/* ══════════════════════════════════════════════════════════
   AOS integration layer — REMOVED v22 (2026-05-22)
   ══════════════════════════════════════════════════════════
   AOS library dropped (~14 KB JS + ~28 KB CSS). The replacement
   lives at line ~2824 ("AOS-compat reveal") and the JS side
   in enhance.js#initRevealObserver. Reduced-motion is now
   handled by the foundation-level prefers-reduced-motion rule.
   This tombstone exists so future spelunkers don't recreate it.
══════════════════════════════════════════════════════════ */

/* Silence CSS keyframe animation on data-aos elements that also
   carry the legacy .fade-up* classes — keep, still relevant. */
[data-aos].fade-up,
[data-aos].fade-up--d1,
[data-aos].fade-up--d2,
[data-aos].fade-up--d3 {
  animation: none;
}

/* ════════════════════════════════════════════════════════════════
   I18N — LANGUAGE SWITCHER + ARABIC TYPOGRAPHY + RTL  (restored 2026-05-25)
   ════════════════════════════════════════════════════════════════
   Recovered from stash@{1} (2026-05-22). Paired with site/assets/js/i18n.js
   which injects a 3-button switcher into .site-nav. The site reverted
   from FR-only (strategy c) to FR+EN+AR; docs/I18N-SEO.md updated.
   ════════════════════════════════════════════════════════════════ */

/* ── LANGUAGE SWITCHER  (FR · EN · AR — pill in the navbar) ── */
.lang-switcher {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r4);
  height: 38px;
}
.lang-btn {
  appearance: none;
  background: transparent;
  border: 0;
  color: var(--txt-2);
  /* var() inside the shorthand: the size still has to sit on the ladder,
     and a `font:` shorthand is invisible to a `font-size:` search. */
  font: 500 var(--fs-caption)/1 var(--font-display);
  letter-spacing: 0.04em;
  padding: 0 10px;
  height: 30px;
  min-width: 32px;
  border-radius: var(--r4);
  cursor: pointer;
  transition: background-color var(--t), color var(--t);
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.lang-btn:hover {
  color: var(--txt-1);
  background: rgba(255,255,255,.05);
}
.lang-btn--active {
  background: var(--mint);
  color: var(--navy);
  font-weight: 600;
}
.lang-btn--active:hover {
  background: var(--mint);
  color: var(--navy);
}
.lang-btn--ar {
  font-family: 'Cairo', 'DM Sans', system-ui, sans-serif;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  letter-spacing: 0;
}

/* Light-mode tweaks */
[data-theme="light"] .lang-switcher {
  background: rgba(0,44,81,0.04);
  border-color: rgba(0,44,81,0.18);
}
[data-theme="light"] .lang-btn { color: var(--txt-2); }
[data-theme="light"] .lang-btn:hover {
  color: var(--navy);
  background: rgba(0,44,81,0.05);
}
[data-theme="light"] .lang-btn--active {
  background: var(--navy);
  color: #fff;
}

/* 900px, not 768: the drawer that holds these buttons opens at <=900, so a
   768 breakpoint left them 30x32 for the whole 769-900 band. 44px minimum —
   they are the primary controls of a trilingual site. */
@media (max-width: 900px) {
  .lang-switcher { height: auto; padding: 2px; }
  .lang-btn { min-height: var(--touch-min); min-width: var(--touch-min); padding: 0 10px; font-size: var(--fs-caption); }
  .lang-btn--ar { font-size: var(--fs-caption); }
}

/* Note (corrected 2026-09-05): the drawer is live again — initNavDrawer() in
   enhance.js moves the switcher, theme toggle and CTA into it below 900px.
   The block above sizes the pills for that drawer; the stale note claiming
   the drawer was reverted described neither the markup nor the CSS. */

/* ── ARABIC TYPOGRAPHY  (Cairo — single Arabic face, display + body) ── */
:root[lang="ar"] {
  /* Arabic type pair (2026-08): Cairo carries the display voice — geometric,
     high-contrast, right at home next to Sora — while Noto Sans Arabic runs the
     body text, where Cairo's tight counters get dense at paragraph sizes. */
  --font-display: 'Cairo', 'Noto Sans Arabic', 'DM Sans', system-ui, sans-serif;
  --font-body:    'Noto Sans Arabic', 'Cairo', 'DM Sans', system-ui, sans-serif;
  --font-hero-display: 'Cairo', 'Noto Sans Arabic', 'DM Sans', system-ui, sans-serif; /* Sora is Latin-only — Arabic heroes stay on Cairo */
}
:root[lang="ar"] body {
  font-family: var(--font-body);
  line-height: 1.7;
}
:root[lang="ar"] h1,
:root[lang="ar"] h2,
:root[lang="ar"] h3,
:root[lang="ar"] .hero__title,
:root[lang="ar"] .home-hero__content h1,
:root[lang="ar"] .section-head__title {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.25;
  font-style: normal !important;
}
:root[lang="ar"] em {
  font-style: normal;
  font-weight: 700;
}
/* Arabic numerals stay LTR even in RTL flow — numbers must NEVER flip/reorder
   in Arabic. Covers stat counters, prices (incl. the <strong> inside hero/hotel
   price blocks) and phone numbers. `unicode-bidi: isolate` fully isolates each
   numeric run from the surrounding RTL text so digit+separator+symbol sequences
   keep their natural left-to-right order. */
:root[lang="ar"] .value-card__num,
:root[lang="ar"] [data-counter],
:root[lang="ar"] .price,
:root[lang="ar"] .phone-card__num,
:root[lang="ar"] .stat-card__num,
:root[lang="ar"] .hero__price strong,
:root[lang="ar"] .hotel-card__price strong,
:root[lang="ar"] .trip-card__cta-price,
/* Extended coverage 2026-06-03: every numeric surface across calc, booking,
   sticky bars, trip cards, date chips, agency stats, related cards, etc. */
:root[lang="ar"] .date-chip,
:root[lang="ar"] .breakdown__line span:last-child,
:root[lang="ar"] .breakdown__total-amount,
:root[lang="ar"] .breakdown__usd,
:root[lang="ar"] .sticky-total__amount,
:root[lang="ar"] .trip-sticky-bar__price-num,
:root[lang="ar"] .trip-card__from strong,
:root[lang="ar"] .bf-trip-chip strong,
:root[lang="ar"] .related-card__price strong,
:root[lang="ar"] .conseiller-num,
:root[lang="ar"] .phone-group a,
:root[lang="ar"] time,
:root[lang="ar"] [data-num],
/* Extended coverage 2026-07-20: phone numbers rendered as link/button labels
   (final-CTA ghost buttons on trip pages, .contact-phone-link) were still
   reordering in Arabic — "0561 616 266" became "266 616 0561" because the
   spaces between digit groups are bidi-neutral. Number links never carry
   data-i18n (they aren't translated), so :not([data-i18n]) isolates them
   without forcing LTR onto genuinely translated button text. */
:root[lang="ar"] .contact-phone-link,
:root[lang="ar"] a[href^="tel:"]:not([data-i18n]),
:root[lang="ar"] a.btn--ghost[href*="wa.me"]:not([data-i18n]),
/* 2026-09-05: `.trust-strip__item strong` was removed from this list. It existed
   for the "4,9 / 5" rating, which is gone; the <strong> now holds Arabic words
   ("3 وكالات") and forcing LTR on it put the digit on the wrong side. Same for
   the .bf-trip-chip and .related-card__price CONTAINERS above: only their numeric
   <strong> leaves are isolated now, so the Arabic label keeps its natural side. */
:root[lang="ar"] .num-ltr {
  direction: ltr;
  unicode-bidi: isolate;
  /* 'Noto Sans Arabic' second: these selectors also catch elements that hold
     Arabic words ("600 م", "أسبوعياً"), which fell to the OS fallback. */
  font-family: 'DM Sans', 'Noto Sans Arabic', system-ui, sans-serif;
}

/* ── RTL LAYOUT ADJUSTMENTS  (Arabic only) ── */
/* Flip directional arrows */
[dir="rtl"] .trip-card__cta svg,
[dir="rtl"] .related-card__cta svg,
[dir="rtl"] .voyage-arrow,
[dir="rtl"] .arrow-right {
  transform: scaleX(-1);
}
/* Compose the RTL flip with the hover nudge: without this the higher-specificity
   hover rule replaced the flip, so the arrow pointed the wrong way and slid
   toward the text on hover in Arabic. */
[dir="rtl"] .trip-card:hover .trip-card__cta > svg { transform: translateX(-3px) scaleX(-1); }
/* Trip card price ribbons originate from left edge — flip to right */
[dir="rtl"] .trip-card__flag,
[dir="rtl"] .hotel-card__ribbon { left: auto; right: var(--s3); }
[dir="rtl"] .trip-card__from,
[dir="rtl"] .trip-card__share { right: auto; left: var(--s3); }
/* Mirror trip-card edge alignment for RTL */
[dir="rtl"] .trip-card__from { align-items: flex-start; }
[dir="rtl"] .trip-card__cta { left: auto; right: 22px; }
/* The monument badge has to mirror with them. It sits at top/left 14px, and
   the price chip lands on top/left 16px once the rule above moves it — same
   corner, same 14px top, so on every /ar/ card the chip covered the badge.
   This is the RTL twin of the share/price collision fixed in f19e0c0: the
   left edge is the crowded one under RTL, and the right edge is now free. */
[dir="rtl"] .trip-card__monument { left: auto; right: 14px; }
/* Logo letter-spacing tweak for Arabic */
[dir="rtl"] .nav-logo,
[lang="ar"] .nav-logo { letter-spacing: 0; }
/* v26 mobile-ux: blanket letter-spacing reset for Arabic — Latin-tuned tracking
   (.04em–.18em on display/eyebrow/.btn/badges) breaks joined cursive script. */
:root[lang="ar"] *,
[dir="rtl"] * { letter-spacing: 0 !important; }
[dir="rtl"] .nav-links { padding-inline-start: 0; }
/* WhatsApp FAB anchors right by default — flip to left for RTL */
[dir="rtl"] .fab-whatsapp { left: var(--s5); right: auto; }

/* ── RTL gaps found against the generated /ar/<trip>/ pages (2026-08) ──────
   Arabic had never shipped as a real URL, so the physical↔[dir="rtl"] pairing
   above was hand-maintained against pages nobody had ever rendered in Arabic.
   Every rule below mirrors a physical-direction declaration that (a) actually
   fires on a rendered /ar/ trip page and (b) had no RTL counterpart. Each was
   checked against the full cascade first: rules whose physical declaration is
   already dead (.seg-opt's border-right, killed by a later `border:none`;
   .site-nav > .theme-toggle's margin-left:auto, killed by the v3 nav override
   that spaces the bar with the logical `margin-inline:auto`) are deliberately
   NOT mirrored — adding those overrides would have invented layout that LTR
   does not have. Overrides rather than logical properties on the originals:
   the LTR rules live in other sections of this file and are shared with the
   FR/EN pages, whose bytes must not move. */

/* Bulleted body lists (« Compris dans le prix », conditions, annulation): the
   dot is absolutely positioned at left:0 against a matching padding-left, so
   in Arabic every bullet detached from its text and sat at the line's end. */
[dir="rtl"] .info-list li { padding-left: 0; padding-right: 18px; }
[dir="rtl"] .info-list li::before { left: auto; right: 0; }
[dir="rtl"] .info-list--tiered li { padding: 10px 32px 10px 14px; }
[dir="rtl"] .info-list--tiered li::before { left: auto; right: 14px; }
/* Callout note: accent bar + the rounded pair both on the inline-start edge. */
[dir="rtl"] .info-card__note {
  border-left: 0;
  border-right: 3px solid var(--accent, var(--mint));
  border-radius: 8px 0 0 8px;
}
/* Section eyebrows carry a 12px accent dash before the text — 9 per page. */
[dir="rtl"] [data-region] .section-head__eyebrow { padding-left: 0; padding-right: 18px; }
[dir="rtl"] [data-region] .section-head__eyebrow::before { left: auto; right: 0; }
/* Hotel cards: the cut-corner triangle and the ★ inside it. */
[dir="rtl"] .hotel-card::before { right: auto; left: -28px; }
[dir="rtl"] .hotel-card::after  { right: auto; left: 10px; }
/* Step marker pill: the numbered badge hugs the inline-start edge (4px) and
   the label the inline-end edge (10px). */
[dir="rtl"] .phase-marker { padding: 4px 4px 4px 10px; }
[dir="rtl"] .phase-marker__label { padding-right: 0; padding-left: 4px; }
/* Required-field asterisk trails its label; the booking form's upload
   thumbnails carry their remove badge in the top inline-end corner. */
[dir="rtl"] .bform-field .req { margin-left: 0; margin-right: 2px; }
[dir="rtl"] .upload-thumb__remove { right: auto; left: 3px; }
/* Skip link — off-screen until focused, then it must land on the start edge. */
[dir="rtl"] .skip-link { left: auto; right: 8px; }
/* Trip-switcher dropdown hangs off the trigger's inline-end edge; anchored
   right in RTL it opened leftwards off the viewport. */
[dir="rtl"] .trip-switcher__menu { right: auto; left: 0; transform-origin: top left; }
@media (max-width: 768px) {
  [dir="rtl"] .trip-switcher__menu { right: auto; left: 16px; }
}
/* The FAB's tooltip hangs off the button's inline-start side; with the FAB
   itself flipped to the left (rule above) it pointed off-screen. */
[dir="rtl"] .fab-whatsapp__tooltip {
  right: auto;
  left: calc(100% + 12px);
  transform: translateY(-50%) translateX(-8px);
}
[dir="rtl"] .fab-whatsapp.tooltip-shown .fab-whatsapp__tooltip {
  transform: translateY(-50%) translateX(0);
}
[dir="rtl"] .fab-whatsapp__tooltip::after {
  right: auto;
  left: -5px;
  border-right: 0;
  border-top: 0;
  border-left: 1px solid rgba(255, 255, 255, 0.08);
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}
/* Photo lightbox (enhance.js builds it from the hotel images on every trip
   page): swap the rails, and flip the chevrons so "previous" still points
   back. The flip goes on the <svg>, not the button, which carries its own
   translateY(-50%) centring transform. */
[dir="rtl"] .lightbox__close { right: auto; left: 20px; }
[dir="rtl"] .lightbox__nav--prev { left: auto; right: 20px; }
[dir="rtl"] .lightbox__nav--next { right: auto; left: 20px; }
[dir="rtl"] .lightbox__nav svg { transform: scaleX(-1); }
@media (max-width: 640px) {
  [dir="rtl"] .lightbox__nav--prev { left: auto; right: 10px; }
  [dir="rtl"] .lightbox__nav--next { right: auto; left: 10px; }
  [dir="rtl"] .lightbox__close { right: auto; left: 12px; }
}
/* Map "recentrer" control. */
[dir="rtl"] .tmap-recenter,
[dir="rtl"] .amap-recenter { left: auto; right: 14px; }

/* Numeric runs the isolation list above missed on the real /ar/ pages.
   `.aurora-hero__amount` (the big trip price) already carries its own
   direction:ltr in the aurora-hero block, so it is not repeated here.
   `.ltr` is the class the house style tells authors to wrap prices, phone
   numbers and dates in; it had no rule at all, so every `class="ltr"` was a
   silent no-op. Nothing on the public site uses it yet — defining it changes
   no current pixel and makes the convention work for the next author. */
:root[lang="ar"] .u-noscript-card a,
:root[lang="ar"] .ltr {
  direction: ltr;
  unicode-bidi: isolate;
  /* 'Noto Sans Arabic' second: these selectors also catch elements that hold
     Arabic words ("600 م", "أسبوعياً"), which fell to the OS fallback. */
  font-family: 'DM Sans', 'Noto Sans Arabic', system-ui, sans-serif;
}

/* ═══════════════════════════════════════════════════════════════════════════
   HORIZON AURORA HERO (v27) — full-bleed parallax destination hero
   Replaces the v14 scroll-hero scrub on trip pages. Per-destination tint via
   --hero-a/b/c. Aurora rides ON the photo (mix-blend-mode:screen) so it stays
   visible; solid→transparent gradients avoid color-mix (broad Android support).
   No-JS safe (real HTML). All motion gated by prefers-reduced-motion. Mobile
   holds no will-change (matches the v26 ≤640px GPU gate).
   ═══════════════════════════════════════════════════════════════════════════ */
.aurora-hero{
  --hero-a:#33C5C9; --hero-b:#1E6F8E; --hero-c:#FF6B5A;   /* fallback */
  position:relative; min-height:100svh; min-height:100dvh;
  display:grid; grid-template-rows:1fr auto;
  isolation:isolate; overflow:clip;
  color:var(--txt-1); background:#05101c;
}
.aurora-hero[data-region="egypt"]      { --hero-a:#E8B04B; --hero-b:#C8612C; --hero-c:#0E5C63; }
.aurora-hero[data-region="azerbaijan"] { --hero-a:#E85D2F; --hero-b:#B8412E; --hero-c:#3AAFAF; }
.aurora-hero[data-region="istanbul"]   { --hero-a:#70B8E0; --hero-b:#1E6F8E; --hero-c:#E07040; }
.aurora-hero[data-region="malaysia"]   { --hero-a:#33C5C9; --hero-b:#1E8E6F; --hero-c:#F2994A; }
.aurora-hero[data-region="sharm"]      { --hero-a:#28B4D4; --hero-b:#1E6F8E; --hero-c:#E85070; }
.aurora-hero[data-region="tunisie"]    { --hero-a:#3AA9D4; --hero-b:#1E6F8E; --hero-c:#E8B04B; }
.aurora-hero[data-region="bali"]       { --hero-a:#2BB39A; --hero-b:#1E8E6F; --hero-c:#F2994A; }
.aurora-hero[data-region="vietnam"]    { --hero-a:#2BA37A; --hero-b:#1E6F5E; --hero-c:#E8B04B; }

/* full-bleed photo + slow Ken Burns */
.aurora-hero__photo{ position:absolute; inset:0; z-index:1; display:block; overflow:hidden; }
.aurora-hero__img{
  width:100%; height:100%; object-fit:cover; display:block;
  transform-origin:58% 42%;
  animation:auroraKen 30s ease-in-out infinite alternate;
}
@keyframes auroraKen{ 0%{transform:scale(1.05)} 100%{transform:scale(1.14) translate3d(-1.4%,-1.6%,0)} }

/* aurora light — rides ON the photo */
.aurora-hero__sky{
  position:absolute; inset:-15%; z-index:2; pointer-events:none;
  background:
    radial-gradient(40% 48% at 20% 24%, var(--hero-a), transparent 66%),
    radial-gradient(44% 54% at 82% 16%, var(--hero-b), transparent 70%),
    radial-gradient(52% 60% at 72% 92%, var(--hero-c), transparent 72%),
    radial-gradient(64% 72% at 26% 96%, var(--hero-b), transparent 78%);
  filter:blur(40px) saturate(1.3);
  mix-blend-mode:screen; opacity:.56;
  animation:auroraDrift 22s ease-in-out infinite alternate;
}
@keyframes auroraDrift{ 0%{transform:translate3d(-2%,-1%,0) scale(1.04)} 100%{transform:translate3d(2%,2%,0) scale(1.12)} }

/* contrast scrim */
.aurora-hero__scrim{
  position:absolute; inset:0; z-index:3; pointer-events:none;
  background:
    linear-gradient(180deg, rgba(5,16,28,.40) 0%, rgba(5,16,28,.06) 22%, rgba(5,16,28,.28) 54%, rgba(5,16,28,.66) 78%, rgba(5,16,28,.93) 100%),
    radial-gradient(130% 86% at 50% 0%, transparent 44%, rgba(5,16,28,.34) 100%);
}

/* content */
.aurora-hero__inner{
  position:relative; z-index:5; grid-row:1; align-self:end; justify-self:center;
  display:flex; flex-direction:column; align-items:center; gap:var(--space-3);
  width:min(1080px,92vw); margin-inline:auto;
  padding:calc(var(--nav-h) + var(--space-6)) 0 var(--space-2); text-align:center;
  animation:auroraRise 900ms var(--ease-out, ease-out) both;
}
.aurora-hero__eyebrow{
  display:inline-flex; align-items:flex-start; gap:var(--space-2); margin:0;
  font-size:var(--fs-caption); font-weight:600; text-transform:uppercase; letter-spacing:.16em;
  color:var(--txt-1); background:var(--bg-glass); border:1px solid var(--border-hi);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  padding:.5em 1.05em; border-radius:var(--r4);
}
.aurora-hero__pin{ color:var(--hero-a); flex:none; }
.aurora-hero__title{
  margin:0; color:#fff; font-family:var(--font-display);
  font-weight:600; font-size:clamp(2.7rem,8.4vw,6.6rem); line-height:.96; letter-spacing:-.025em;
  text-shadow:0 1px 2px rgba(0,0,0,.45), 0 8px 44px rgba(0,0,0,.5);
}
.aurora-hero__title em{
  display:block; margin-top:var(--space-3); font-family:var(--font-display);
  font-style:normal; font-weight:400; font-size:clamp(.95rem,2.4vw,1.5rem);
  letter-spacing:.005em; line-height:1.3; color:#fff; text-shadow:0 1px 12px rgba(0,0,0,.6);
}
/* --txt-2 at 13px on the bright band of a hero photo, with no shadow, measured
   as the least legible text on the page (visual audit B13). */
.aurora-hero__date{ margin:0; font-size:var(--fs-body-sm); text-transform:uppercase; letter-spacing:.14em; color:#fff; text-shadow:0 1px 8px rgba(0,0,0,.65), 0 1px 2px rgba(0,0,0,.5); }

/* glass offer bar */
.aurora-hero__offer{
  position:relative; z-index:6; grid-row:2; justify-self:center;
  display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:var(--space-3) var(--space-6);
  width:min(1080px,92vw); margin:var(--space-2) auto calc(var(--sticky-bar-h, 68px) + var(--space-5) + env(safe-area-inset-bottom));
  padding:var(--space-3) var(--space-5);
  background:var(--bg-glass); border:1px solid var(--border-hi);
  -webkit-backdrop-filter:blur(18px); backdrop-filter:blur(18px);
  border-radius:var(--r3); box-shadow:0 16px 48px rgba(0,0,0,.4);
  animation:auroraRise 900ms var(--ease-out, ease-out) 120ms both;
}
.aurora-hero__price{ margin:0; display:flex; align-items:baseline; flex-wrap:wrap; justify-content:center; gap:.15em .5ch; }
.aurora-hero__from{ font-size:var(--fs-caption); text-transform:uppercase; letter-spacing:.12em; color:var(--txt-2); }
.aurora-hero__amount{ font-family:var(--font-display); font-weight:600; font-size:clamp(1.55rem,4.4vw,2.2rem); color:#fff; direction:ltr; unicode-bidi:isolate; }
/* The offer bar glass is cream in light mode, so #fff price was invisible. */
:root[data-theme="light"] .aurora-hero__amount{ color:var(--txt-1); }
.aurora-hero__unit{ font-size:var(--fs-caption); color:var(--txt-2); }
.aurora-hero__actions{ display:flex; flex-wrap:wrap; gap:var(--space-3); justify-content:center; }
.aurora-hero__wa{ display:inline-flex; align-items:center; gap:.5ch; }
@keyframes auroraRise{ from{opacity:0; transform:translate3d(0,18px,0)} to{opacity:1; transform:none} }

/* slim intro strip (lede + fineprint) */
.hero-intro{ position:relative; padding:var(--space-7) 0 var(--space-4); background:transparent; }
.hero-intro__inner{ max-width:760px; text-align:center; }
.hero-intro__lede{ margin:0 auto; font-size:var(--fs-body-lg); line-height:1.6; color:var(--txt-1); }
.hero-intro__fineprint{ margin:var(--space-3) auto 0; font-size:var(--fs-caption); color:var(--txt-3); }

/* desktop will-change only (≤640px released by the v26 GPU gate) */
@media (min-width: 641px){ .aurora-hero__sky{will-change:transform} .aurora-hero__img{will-change:transform} }

/* mobile tuning — compact offer (more photo visible) + a touch more aurora */
@media (max-width: 768px){
  .aurora-hero{ min-height:92svh; min-height:92dvh; }
  .aurora-hero__sky{ filter:blur(24px) saturate(1.3); opacity:.5; }
  /* Cap the offer/eyebrow glass blur on phones (they're always on-screen) —
     matches the ≤640px GPU cap applied to the rest of the site's glass. */
  .aurora-hero__offer, .aurora-hero__eyebrow{ -webkit-backdrop-filter:blur(8px); backdrop-filter:blur(8px); }
  .aurora-hero__inner{ padding-top:calc(var(--nav-h) + var(--space-4)); gap:var(--space-2); }
  .aurora-hero__offer{ gap:var(--space-2) var(--space-3); padding:var(--space-3) var(--space-4); }
  .aurora-hero__price{ width:100%; }
  .aurora-hero__actions{ width:100%; flex-wrap:nowrap; gap:var(--space-2); }
  .aurora-hero__actions .btn{ flex:1 1 0; min-width:0; justify-content:center; padding-inline:var(--space-3); font-size:var(--fs-body-sm); }
}

/* reduced motion: freeze to final state */
@media (prefers-reduced-motion: reduce){
  .aurora-hero__sky, .aurora-hero__img, .aurora-hero__inner, .aurora-hero__offer{ animation:none !important; }
  .aurora-hero__img{ transform:scale(1.04); }
}

/* ══════════════════════════════════════════════════════════
   FOOTER — premium brand band + WhatsApp CTA (additive)
   Extends the 6 scattered in-place footer rules above; does not rewrite
   them. The .footer-cta band only renders once the HTML adds it.
   All inside the global reduced-motion umbrella — no new infinite keyframes.
   ══════════════════════════════════════════════════════════ */
.site-footer {
  position: relative;
  background: linear-gradient(180deg, var(--bg) 0%, var(--bg-2) 40%);
}
/* Accent hairline along the top edge */
.site-footer::before {
  content: '';
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 1px;
  background: linear-gradient(90deg, transparent, var(--accent-glow), transparent);
}

/* CTA band — sits above the existing .footer-grid */
.footer-cta {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--space-5);
  flex-wrap: wrap;
  padding-bottom: var(--space-7);
  margin-bottom: var(--space-7);
  border-bottom: 1px solid var(--border);
}
.footer-cta__text h3 {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  color: var(--txt-1);
  margin: 0;
}
.footer-cta__text p {
  color: var(--txt-2);
  font-size: var(--fs-body-sm);
  margin: .25rem 0 0;
}
/* dup sweep 2026-08: `.footer-cta__btn` deleted here — the v28 footer block
   re-declares the same min-height (and adds flex-shrink). */

/* Rebalance the brand-heavier grid + bump the logo */

/* Animated underline on footer column links */
.footer-col a {
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  color: var(--txt-2);
  transition:
    background-size var(--t-fast) var(--ease-out),
    color var(--t-fast) var(--ease-out);
}
.footer-col a:hover {
  background-size: 100% 1px;
  color: var(--txt-1);
}

/* RTL: mirror the CTA band */
:root[lang="ar"] .footer-cta {
  flex-direction: row-reverse;
}

/* ── Aurora orb (homepage hero visual — replaces the cobe WebGL globe) ──────
   CSS-only floating photo-stack over the same aurora atmosphere as the trip
   heroes. No JS, no CDN, works on mobile; RTL + reduced-motion safe. */
.aurora-orb{position:relative;width:100%;max-width:480px;margin-inline:auto;aspect-ratio:1/1;isolation:isolate;}
.aurora-orb__sky{position:absolute;inset:-12%;z-index:0;border-radius:50%;background:radial-gradient(40% 48% at 22% 24%,var(--accent),transparent 64%),radial-gradient(46% 54% at 80% 20%,#C8612C,transparent 70%),radial-gradient(54% 60% at 70% 88%,#1E6F8E,transparent 72%);filter:blur(46px) saturate(1.25);opacity:.55;animation:auroraDrift 22s ease-in-out infinite alternate;}
.aurora-orb__card{position:absolute;margin:0;border-radius:var(--r3);overflow:hidden;background:#0c0e12;box-shadow:0 24px 60px -18px rgba(0,0,0,.65),0 0 0 1px rgba(255,255,255,.06);will-change:transform;}
.aurora-orb__card img{display:block;width:100%;height:100%;object-fit:cover;aspect-ratio:4/5;}
.aurora-orb__card figcaption{position:absolute;left:0;right:0;bottom:0;padding:28px 14px 12px;font-size: var(--fs-caption);font-weight:600;letter-spacing:.04em;color:#fff;text-shadow:0 1px 8px rgba(0,0,0,.7);background:linear-gradient(transparent,rgba(5,16,28,.85));}
.aurora-orb__card--1{z-index:3;top:6%;left:21%;width:58%;--rot:-5deg;animation:orbFloat 9s ease-in-out infinite;}
.aurora-orb__card--2{z-index:2;top:24%;left:2%;width:46%;opacity:.92;--rot:5deg;animation:orbFloat 9s ease-in-out -3s infinite;}
.aurora-orb__card--3{z-index:1;top:30%;right:0;width:46%;opacity:.88;--rot:-3deg;animation:orbFloat 9s ease-in-out -6s infinite;}
@keyframes orbFloat{0%,100%{transform:translate3d(0,0,0) rotate(var(--rot,-5deg))}50%{transform:translate3d(0,-10px,0) rotate(var(--rot,-5deg))}}
:root[lang="ar"] .aurora-orb__card--1{left:auto;right:21%}
:root[lang="ar"] .aurora-orb__card--2{left:auto;right:2%}
:root[lang="ar"] .aurora-orb__card--3{right:auto;left:0}
@media (prefers-reduced-motion: reduce){.aurora-orb__sky,.aurora-orb__card{animation:none!important}}
/* Mobile GPU gate for the homepage orb — match the aurora-hero: lighter blur,
   release the persistent compositor layers on phones. */
@media (max-width: 768px){.aurora-orb__sky{filter:blur(24px) saturate(1.25)}.aurora-orb__card{will-change:auto}}

/* ── v27 responsive / delivery polish (from the responsive audit) ──────────── */
/* iOS focus-zoom guard: keep form controls >=16px even when a utility font class
   (e.g. .fs-body-sm on #hotel-select) outranks the pointer:coarse safety rule. */
.calc-form select,
.bform-field input, .bform-field select, .bform-field textarea{ font-size:max(16px, 1rem); }
/* Stepper +/- buttons: full 44px hit area on touch (the coarse rule set only min-height). */
@media (pointer: coarse){ .stepper__btn{ min-width:var(--touch-min); min-height:var(--touch-min); } }
/* Same trap, two more buttons. The coarse rule raises min-height on every
   button but not min-width, so a round button narrower than 44px is served as
   an ellipse on every phone. These two stay round at 28px — above the WCAG
   2.5.8 AA floor of 24x24, and small enough not to swallow the 80px upload
   thumbnail they sit on. */
@media (pointer: coarse){
  .upload-thumb__remove,
  .bf-passport-entry__remove{ width:28px; height:28px; min-width:28px; min-height:28px; }
}
/* Aurora hero title: never clip/overflow on narrow phones; add a side gutter to the inner. */
.aurora-hero__title{ overflow-wrap:break-word; hyphens:auto; }
.aurora-hero__inner{ padding-inline:var(--container-x); }
/* Aurora hero CTAs: stack full-width on the smallest phones instead of a cramped 2-up. */
/* Stack the two hero CTAs well before 380px: they are flex:1 1 0 with no
   ellipsis on .btn, and the FR/AR labels already crowd at ~440px. */
@media (max-width: 440px){
  .aurora-hero__actions{ flex-wrap:wrap; }
  .aurora-hero__actions .btn{ flex:1 1 100%; }
}

/* ══════════════════════════════════════════════════════════════
   Homepage contact section — form-first layout
   The form is the point of the section, so it takes the wider column and
   the reference material (advisors, branches, payment) moves into a rail
   of cards beside it. Previously the form sat in a half-width column with
   six near-identical phone cards stacked underneath, repeating the six
   numbers the branches block had already listed a screen earlier.
   ══════════════════════════════════════════════════════════════ */

/* Holds the <symbol> defs. display:none would stop <use> resolving in some
   engines, so the element is collapsed out of layout instead. */
.contact-sprite {
  position: absolute;
  width: 0;
  height: 0;
  overflow: hidden;
}

/* Icons are sized by their width/height attributes; this only stops flex
   containers from squashing them and keeps them optically centred on text. */
.ico {
  flex-shrink: 0;
  vertical-align: middle;
}

.contact-main__title {
  font-size: clamp(28px, 4vw, 48px);
  line-height: 1.1;
  margin: 0 0 var(--s4, 24px);
}
/* --accent, not --bronze. The old markup said color:var(--bronze) inline, but
   Phase J deleted that token family, so the emphasis colour had silently
   resolved to nothing and the accented half of the heading rendered in plain
   body colour. 12.4:1 on --bg-2 dark, 4.7:1 light — both clear of the 3:1 that
   large text needs. */
.contact-main__title em {
  color: var(--accent);
  font-style: normal;
}
/* Same story as the contact title: the agency heading's <em> carried an inline
   color:var(--bronze), and Phase J deleted that token, so the accented half
   ("depuis Bordj Bou Arreridj") had rendered in plain heading colour. Moved off
   the inline style onto this class, using --accent like its sibling. */
.agency-title em {
  color: var(--accent);
  font-style: normal;
}
.contact-main__lede {
  margin-bottom: var(--s6, 32px);
  max-width: 34rem; /* was running ~78 chars — tightened to a comfortable measure */
}

/* Two fields per row while there is room. 220px is the point at which the
   longest label ("Voyage qui vous intéresse") still fits on one line. */
.contact-form__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--s4, 16px);
}

/* Submit feedback. Empty by default and removed from layout so it does not
   reserve a blank line — the old form gave no feedback at all, so a blocked
   popup looked like a dead button. */
.contact-form__status {
  margin: 0;
  font-size: var(--fs-caption);
  line-height: 1.5;
}
.contact-form__status:empty {
  display: none;
}
.contact-form__status.is-ok {
  color: var(--txt-2);
}
.contact-form__status.is-warn a {
  color: var(--accent);
  font-weight: 600;
  text-decoration: underline;
}

/* ── trust rail ── */
.contact-rail {
  display: flex;
  flex-direction: column;
  gap: var(--s4, 16px);
}
.contact-card {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3, 12px);
  padding: var(--s5, 24px);
}
.contact-card__title {
  display: flex;
  align-items: center;
  gap: 8px;
  margin: 0 0 var(--s4, 16px);
  font-size: var(--fs-2xs);
  font-weight: 700;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--txt-3);
}
.contact-card__title .ico {
  color: var(--accent);
}
.contact-card__note {
  display: flex;
  align-items: flex-start;
  gap: 8px;
  margin: var(--s4, 16px) 0 0;
  font-size: var(--fs-caption);
  line-height: 1.55;
  color: var(--txt-3);
}
.contact-card__note .ico {
  margin-top: .15em;
}

/* ── advisors ── */
.advisor-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 6px;
}
/* [hidden] must win over this. The attribute's display:none comes from the UA
   stylesheet, and ANY author rule that sets display beats the whole UA sheet
   regardless of specificity — so `display: flex` here silently un-hid the four
   collapsed advisors while their `hidden` attribute still said otherwise. The
   attribute selector below restores the intent. */
.advisor {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3, 12px);
  padding: 8px 10px;
  border: 1px solid var(--border);
  border-radius: var(--r2, 8px);
  background: var(--bg);
}
.advisor[hidden] {
  display: none;
}
/* Same trap, same fix. .bf-field-err and .bf-validation-banner are display:flex
   and booking-form.js ships them with `hidden` — so every field error and the red
   "complete the fields" banner painted on first load, before any input. */
.bf-field-err[hidden],
.bf-validation-banner[hidden] {
  display: none;
}
/* Third one, same trap: .bform-field is display:flex and #bf-office-field
   ships `hidden`, revealed by booking-form.js only when the trip actually has
   more than one office to choose between. Without this it painted an office
   picker on every load, including the trips that have a single office. */
.bform-field[hidden] {
  display: none;
}
.advisor__num {
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--txt-1);
}
.advisor__actions {
  display: flex;
  gap: 6px;
}
/* 44px keeps these above the WCAG 2.5.8 target-size minimum; the icon inside
   stays 15px so the button reads as compact while remaining tappable. */
.advisor__btn {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  border-radius: var(--r2, 8px);
  border: 1px solid var(--border-hi);
  background: var(--bg-elev);
  color: var(--txt-1);
  transition: border-color .15s ease, color .15s ease, background .15s ease;
}
.advisor__btn:hover {
  border-color: var(--accent);
  color: var(--accent);
}
.advisor__btn--wa {
  background: var(--wa-green);
  border-color: var(--wa-green);
  color: var(--wa-ink);
}
.advisor__btn--wa:hover {
  background: var(--wa-green-hov);
  border-color: var(--wa-green-hov);
  color: var(--wa-ink);
}

.advisor-toggle {
  margin-top: 10px;
  padding: 8px 4px;
  min-height: var(--touch-min);
  width: 100%;
  background: none;
  border: 0;
  color: var(--accent);
  font: inherit;
  font-size: var(--fs-caption);
  font-weight: 600;
  text-align: start;
  cursor: pointer;
}
.advisor-toggle:hover {
  text-decoration: underline;
}

/* ── branches / payment ── */
.branch-list,
.pay-list {
  list-style: none;
  margin: 0;
  padding: 0;
}
.branch-list li {
  display: flex;
  flex-direction: column;
  gap: 1px;
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--txt-2);
}
.branch-list li + li {
  margin-top: var(--space-3, 12px);
}
.branch-list strong {
  color: var(--txt-1);
  font-weight: 600;
}
.pay-list {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
}
.pay-list li {
  padding: var(--space-2, 8px) var(--space-3, 12px);
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r1, 2px);
  font-size: var(--fs-caption);
  color: var(--txt-2);
}

/* Below the 1024px breakpoint the section is already one column, so the rail
   spreads its cards across the full width instead of running as a tall stack. */
@media (max-width: 1024px) and (min-width: 721px) {
  .contact-rail {
    flex-direction: row;
    flex-wrap: wrap;
  }
  .contact-rail > .contact-card {
    flex: 1 1 260px;
  }
}

/* ══════════════════════════════════════════════════════════════
   FOOTER — bold editorial redesign (2026-07-24)
   One design, rendered on all 8 pages: index.html and the 7 trip pages
   (via tools/templates/sections/footer.tpl). Reuses the existing leaf
   classes (.footer-cta, .footer-col, .phone-group, .footer-social,
   .footer-bottom) and, being appended last, wins the cascade over the
   scattered "phase" rules above. New structural classes: .footer-main,
   .footer-nav, .footer-legal, .footer-top.
   ══════════════════════════════════════════════════════════════ */
.site-footer {
  padding-block: clamp(48px, 8vw, 96px) clamp(28px, 4vw, 40px);
}

/* CTA band — statement + WhatsApp, bolder and calmer than before. */
.footer-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s7);
  flex-wrap: wrap;
  padding-bottom: clamp(32px, 5vw, 56px);
  margin-bottom: clamp(40px, 6vw, 64px);
  border-bottom: 1px solid var(--border);
}
.footer-cta__text h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  line-height: 1.1;
  letter-spacing: -.01em;
  color: var(--txt-1);
  margin: 0;
}
.footer-cta__text p {
  margin: .5rem 0 0;
  font-size: var(--fs-body-sm, .9375rem);
  color: var(--txt-2);
}
.footer-cta__btn {
  min-height: var(--touch-min);
  flex-shrink: 0;
}

/* Main block: brand (with oversized wordmark) beside the link directory. */
.footer-main {
  display: grid;
  /* The brand block is short (logo, one line of copy, socials) while the nav
     carries seven trips and three offices — an near-even split left the left
     column mostly empty and the right one cramped and tall. */
  grid-template-columns: minmax(0, .85fr) minmax(0, 2fr);
  gap: clamp(40px, 6vw, 88px);
  align-items: start;
}
.footer-brand {
  display: flex;
  flex-direction: column;
  gap: var(--s4);
  min-width: 0;
}

/* The editorial anchor is now the full Alliance Travel logo (SVG) rather than a
   text wordmark — see .footer-brand-logo / .footer-logo-svg near end of file.
   The old .footer-wordmark type rules were removed with the element. */
.footer-tagline {
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--txt-2);
  max-width: 42ch;
  margin: 0;
}

/* Social tiles — dotted rounded squares that lift on hover (the reference's
   signature cue), mapped to the site palette. */
.footer-social {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  list-style: none;
  margin: var(--s2) 0 0;
  padding: 0;
}
.footer-social a {
  width: 46px;
  height: 46px;
  border-radius: var(--r3);
  border: 1px dotted var(--border-hi);
  background: transparent;
  display: grid;
  place-items: center;
  color: var(--txt-2);
  transition: transform var(--t-fast) var(--ease-out),
              color var(--t-fast), border-color var(--t-fast), background var(--t-fast);
}
.footer-social a:hover {
  transform: translateY(-3px);
  border-color: var(--accent);
  border-style: solid;
  color: var(--accent);
  background: var(--accent-dim);
}
.footer-social a svg { width: 18px; height: 18px; }

/* Link directory */
.footer-nav {
  display: grid;
  /* auto-fit gave the trips list and the contact block an equal share, which
     made contact ~4x taller than everything beside it. Contact now gets the
     room to lay its offices out side by side instead of stacking. */
  grid-template-columns: minmax(0, .62fr) minmax(0, 2fr);
  gap: clamp(24px, 4vw, 48px);
}

@media (max-width: 860px) {
  .footer-nav { grid-template-columns: 1fr; }
}

/* ── Footer offices ───────────────────────────────────────────────────────
   One entry per branch (name · address · its own lines) instead of a
   WhatsApp-vs-Phone split that left five numbers unattributed — a visitor
   could not tell which office they were calling. Laid out across the row so
   the column reads wide-and-short rather than a tall stack. */
.office-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--s5);
}

.office__name {
  margin: 0 0 3px;
  font-size: var(--fs-caption);
  font-weight: 600;
  color: var(--txt-1);
  line-height: 1.4;
}

.office__addr {
  margin: 0 0 10px;
  font-size: var(--fs-caption);
  line-height: 1.5;
  color: var(--txt-3);
}

.office__lines {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 5px;
}

/* Numerals stay LTR and tabular so the columns line up in Arabic too. */
.office__lines a {
  font-size: var(--fs-body-sm);
  font-variant-numeric: tabular-nums;
  direction: ltr;
  unicode-bidi: isolate;
  color: var(--txt-2);
  transition: color var(--t-fast) var(--ease-out);
}

.office__lines a:hover,
.office__lines a:focus-visible { color: var(--accent); }
.footer-col h4 {
  font-size: var(--fs-2xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .14em;
  color: var(--txt-3);
  margin: 0 0 var(--s4);
}
.footer-col--trips ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
/* Animated underline, scoped to the trip links so the phone numbers in the
   contact column keep their own treatment. */
.footer-col--trips a {
  display: inline-block;
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  background-image: linear-gradient(var(--accent), var(--accent));
  background-size: 0% 1px;
  background-repeat: no-repeat;
  background-position: 0 100%;
  transition: background-size var(--t-fast) var(--ease-out), color var(--t-fast);
}
:root[lang="ar"] .footer-col--trips a { background-position: 100% 100%; }
.footer-col--trips a:hover {
  color: var(--txt-1);
  background-size: 100% 1px;
}

/* Contact column keeps the phone-group layout; re-asserted here so the
   trip-link rule above cannot bleed into the numbers. */
.footer-col--contact .phone-group { margin-bottom: var(--s4); }
/* dup sweep 2026-08: `.phone-group:last-child { margin-bottom: 0 }` deleted —
   re-declared identically in the v28 contact-column block below. */
.footer-col--contact .phone-group a {
  background: none;
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  color: var(--txt-1);
  padding: 2px 0;
  transition: color var(--t-fast);
}
.footer-col--contact .phone-group a:hover { color: var(--accent); }
.footer-address {
  margin: 0;
  font-size: var(--fs-body-sm);
  line-height: 1.6;
  color: var(--txt-2);
}

/* Bottom bar: legal on one side, back-to-top on the other. Dotted rule as a
   final editorial nod. */
.footer-bottom {
  margin-top: clamp(40px, 6vw, 64px);
  padding-top: clamp(24px, 3vw, 32px);
  border-top: 1px dotted var(--border-hi);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--s4);
}
.footer-legal p {
  margin: 0;
  font-size: var(--fs-caption);
  color: var(--txt-3);
  line-height: 1.5;
}
.footer-legal .footer-notice { margin-top: 2px; opacity: .85; }

/* Back-to-top pill — the one utility control. It is a real link to #top, so it
   works with no JS; enhance.js upgrades the jump to a smooth scroll. */
.footer-top {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: var(--touch-min);
  padding: 10px 18px;
  border: 1px solid var(--border-hi);
  border-radius: var(--r4);
  color: var(--txt-2);
  font-size: var(--fs-caption);
  font-weight: 600;
  letter-spacing: .02em;
  white-space: nowrap;
  transition: transform var(--t-fast) var(--ease-out),
              color var(--t-fast), border-color var(--t-fast);
}
.footer-top svg { width: 16px; height: 16px; }
.footer-top:hover {
  transform: translateY(-2px);
  color: var(--accent);
  border-color: var(--accent);
}

/* ── responsive ── */
@media (max-width: 900px) {
  .footer-main { grid-template-columns: 1fr; gap: clamp(32px, 6vw, 48px); }
}
@media (max-width: 560px) {
  .footer-cta { gap: var(--s4); }
  .footer-cta__btn { width: 100%; justify-content: center; }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
}

/* ── reduced motion: no lifts ── */
@media (prefers-reduced-motion: reduce) {
  .footer-social a:hover,
  .footer-top:hover { transform: none; }
}

/* ── Footer brand logo — the full Alliance Travel logo (replaces the text
   wordmark). The source SVG hardcodes cream (#efe8df) + green (#9ce8b2) fills
   for a dark background; the footer bg follows the theme (dark→light), so the
   fills are re-themed here by the same attribute-selector trick the nav logo
   uses. CSS `fill` overrides the presentation attribute while the attribute
   value — and therefore the selector match — stays intact. ── */
.footer-brand-logo { display: block; line-height: 0; }
.footer-logo-svg {
  width: clamp(190px, 22vw, 250px);
  height: auto;
  display: block;
}
.footer-logo-svg path[fill="#efe8df"] { fill: var(--txt-1); }
.footer-logo-svg path[fill="#9ce8b2"] { fill: var(--accent); }

/* ═══════════════════════════════════════════════════════════════════════════
   HOMEPAGE FLOW — readability + alignment pass.
   Scoped so the trip pages (already consistent) are untouched. Fixes: the
   value-props strip was inset ~40px more than every other section (max-width
   1200 vs the container's 1280) and floated with no presence; the agency
   section carried a second copy of the hero stats; several body ledes ran
   ~78ch, past the comfortable 45–75ch measure.
   ═══════════════════════════════════════════════════════════════════════════ */

/* Value-props: align to the container grid + give each item card presence. */
.value-props-3 {
  max-width: 1280px;
  padding-inline: var(--container-x, clamp(16px, 5vw, 80px));
  padding-block: clamp(48px, 8vw, 96px);
  gap: clamp(16px, 2vw, 24px);
}
.value-prop {
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3, 12px);
  padding: clamp(24px, 3vw, 36px) clamp(20px, 2.5vw, 28px);
  gap: 14px;
  transition: border-color var(--t-fast, .18s) ease, transform var(--t-fast, .18s) ease;
}
.value-prop:hover {
  border-color: var(--accent);
  transform: translateY(-2px);
}
.value-prop__text {
  font-size: var(--fs-body-sm); /* was .875rem (14px) — matched to the site body size */
  max-width: 30ch;
}

/* Agency: single, left-aligned editorial column (its right half was the
   duplicate stats). Capped for readability and sharing the hero/contact left
   edge, so the left margin stays put as you scroll. */
/* rem, not ch: DM Sans's '0' glyph is ~0.69em, so a `ch` cap renders ~40%
   more characters than its number implies — 64ch was ~88 characters. 38rem
   lands around 74 for this story column without leaving it lopsidedly thin. */
.about-copy {
  max-width: 38rem;
}
.about-copy .fs-body {
  line-height: 1.7;
}

/* Section rhythm: the content sections now alternate bg-2 / bg cleanly
   (A-B-A-B-A), and a hairline between them delineates each one so the page
   reads as distinct bands rather than one continuous cream wash. Homepage
   only — the trip pages already have their own section treatment. */
body[data-page="home"] #voyages,
body[data-page="home"] .value-props-3,
body[data-page="home"] #agence,
body[data-page="home"] #agences,
body[data-page="home"] #contact {
  border-top: 1px solid var(--border);
}
/* End HOMEPAGE FLOW ──────────────────────────────────────────────────────── */

/* ── WhatsApp lead-capture prompt (lead-whatsapp.js) ─────────────────────────
   A small, dismissible "want a callback?" invite shown a beat after a WhatsApp
   CTA tap. Anchored bottom-inline-start so it never overlaps the bottom-right
   FAB, and rises above the FAB on narrow screens. Sits at toast level: above
   content and the sticky bar, below the FAB and nav drawer. RTL-native. */
.wa-lead-prompt {
  position: fixed;
  /* Logical start: the FAB mirrors to the inline-end corner in both directions
     (right in LTR, left in RTL — see the [dir="rtl"] .fab-whatsapp rule), so
     anchoring the prompt to inline-start keeps it in the opposite corner from
     the FAB in every language. */
  inset-inline-start: 24px;
  inset-block-end: 24px;
  z-index: var(--z-toast);
  width: min(340px, calc(100vw - 48px));
  padding: 16px 18px 18px;
  background: var(--bg-card);
  border: 1px solid var(--border-hi);
  border-radius: var(--r-card);
  box-shadow: 0 14px 34px -10px rgba(0, 0, 0, .5), 0 4px 12px rgba(0, 0, 0, .28);
  color: var(--txt-1);
  text-align: start;
  opacity: 0;
  visibility: hidden;
  transform: translate3d(0, 16px, 0);
  transition: opacity var(--t-base) var(--ease-out),
              transform var(--t-base) var(--ease-out),
              visibility 0s linear var(--t-base);
}
.wa-lead-prompt.is-visible {
  opacity: 1;
  visibility: visible;
  transform: none;
  transition: opacity var(--t-base) var(--ease-out),
              transform var(--t-base) var(--ease-out);
}
.wa-lead-prompt__close {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-end: 10px;
  width: 28px;
  height: 28px;
  padding: 0;
  border: 0;
  background: transparent;
  color: var(--txt-3);
  font-size: var(--fs-body-sm);
  line-height: 1;
  cursor: pointer;
  border-radius: var(--r2);
  transition: color var(--t-fast), background var(--t-fast);
}
.wa-lead-prompt__close:hover { color: var(--txt-1); background: var(--border); }
.wa-lead-prompt__q {
  margin: 0 0 2px;
  margin-inline-end: 26px;
  font-family: var(--font-display, inherit);
  font-size: var(--fs-body);
  font-weight: 600;
  color: var(--txt-1);
}
.wa-lead-prompt__sub {
  margin: 0 0 12px;
  font-size: var(--fs-caption);
  line-height: 1.4;
  color: var(--txt-2);
}
.wa-lead-prompt__form { display: flex; flex-direction: column; gap: 8px; }
.wa-lead-prompt__input {
  width: 100%;
  padding: 10px 12px;
  background: var(--bg);
  border: 1px solid var(--border-hi);
  border-radius: var(--r3);
  color: var(--txt-1);
  font: inherit;
  font-size: var(--fs-body-sm);
  transition: border-color var(--t-fast);
}
.wa-lead-prompt__input::placeholder { color: var(--txt-3); }
.wa-lead-prompt__input:focus-visible { outline: none; border-color: var(--border-mint); }
.wa-lead-prompt__send { margin-top: 2px; justify-content: center; }
.wa-lead-prompt__done {
  margin: 0;
  padding: 6px 0;
  font-size: var(--fs-body-sm);
  font-weight: 600;
  color: var(--accent);
  text-align: center;
}
@media (max-width: 560px) {
  .wa-lead-prompt {
    inset-inline: 12px;
    inset-block-end: 92px;   /* clear the 56px FAB + its 24px breathing room */
    width: auto;
  }
}
@media (prefers-reduced-motion: reduce) {
  .wa-lead-prompt { transition: none !important; } /* appear/leave instantly */
}

/* ── Footer contact — tappable WhatsApp / phone rows (2026-08) ────────────────
   The contact column read as a flat stack of plain text links. Every entry is a
   wa.me / tel action on a WhatsApp-first site, so make them look tappable:
   comfortable rows with a hover fill, clearer group rhythm, and a labelled
   address block. CSS-only, so it applies to every page's footer at once.
   Direction-agnostic (no left/right transforms) so it is RTL-safe. */
.footer-col--contact .phone-group { margin-bottom: var(--s5); }
.footer-col--contact .phone-group:last-child { margin-bottom: 0; }
.footer-col--contact .phone-group__head { margin: 0 0 var(--s2); }

.footer-col--contact .phone-group a {
  display: flex;
  align-items: center;
  /* 44px, not 40: the <=900px rule meant to raise these is .footer-col a
     (0,2,1) and loses to this (0,3,1) selector, so the mobile touch-target
     fix never actually applied here. */
  min-height: var(--touch-min);
  padding: 6px 12px;
  margin-inline: -12px;              /* hover fill bleeds to the edge; text stays flush */
  border-radius: var(--r2, 8px);
  background: none;
  font-variant-numeric: tabular-nums;
  font-size: var(--fs-body-sm);
  font-weight: 500;
  letter-spacing: .01em;
  color: var(--txt-1);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.footer-col--contact .phone-group a:hover,
.footer-col--contact .phone-group a:focus-visible {
  background: var(--accent-dim);
  color: var(--accent);
  outline: none;
}
/* Trailing "tap to chat" chevron, revealed on hover. */
.footer-col--contact .phone-group a::after {
  content: "";
  inline-size: 6px;
  block-size: 6px;
  margin-inline-start: auto;
  border-top: 1.6px solid currentColor;
  border-inline-end: 1.6px solid currentColor;
  transform: rotate(45deg);
  opacity: 0;
  transition: opacity var(--t-fast) var(--ease-out);
}
[dir="rtl"] .footer-col--contact .phone-group a::after { transform: rotate(-135deg); }
.footer-col--contact .phone-group a:hover::after,
.footer-col--contact .phone-group a:focus-visible::after { opacity: .65; }

.footer-col--contact .footer-address { margin-block-start: 2px; }

/* ══════════════════════════════════════════════════════════
   MOTION LAYER (ported from the motion branch) — icon + reveal
   hooks choreographed by assets/js/anim.js; CSS is the no-JS /
   reduced-motion / blocked-CDN baseline.
   ══════════════════════════════════════════════════════════ */

/* ── Trust stat icons ────────────────────────────────────────────────
   Small accent chip above each stat (icons are index-keyed in
   trust.tpl). The card's own data-aos="zoom-in" reveals the chip on
   scroll (baseline, works standalone); the anime.js pass re-animates
   the `.stat-card__icon` targets for a secondary staggered pop.
   Hover micro-motion mirrors .hl-card__icon. The chip sits at the
   inline start (v28 .stat-card is text-align:start, not centered). */
.stat-card__icon {
  width: 40px;
  height: 40px;
  margin-block-end: var(--s3);
  border-radius: var(--r2);
  background: var(--accent-dim);
  color: var(--accent);
  display: grid;
  place-items: center;
  transition: transform var(--t-base) var(--ease-spring),
    background var(--t-base) ease, color var(--t-base) ease;
}
.stat-card__icon svg { width: 20px; height: 20px; }
.stat-card:hover .stat-card__icon {
  transform: translateY(-2px) scale(1.06);
}
:root[data-theme="light"] .stat-card__icon {
  background: var(--mint-dim);
  color: var(--mint);
}
@media (prefers-reduced-motion: reduce) {
  .stat-card:hover .stat-card__icon { transform: none !important; }
}

/* ── Itinerary day-node reveal ───────────────────────────────────────
   Each J1/J2… node carries data-aos="zoom-in" (staggered) in
   itinerary.tpl, so the marker scale/pops as it enters view via the
   existing observer — no per-day icon added (would crowd the spine).
   `.tl-node` is the anime.js hook. Reduced-motion guard keeps it still. */
@media (prefers-reduced-motion: reduce) {
  html.js .tl-node[data-aos] { opacity: 1 !important; transform: none !important; }
}

/* ── Inclus/exclus "tick-in" reveal ──────────────────────────────────
   Each check/cross (.inclus-check) scales + fades in, staggered, when
   its column scrolls into view. Baseline rides the existing
   .reveal → .visible observer (enhance.js) already on .inclus-col, so
   it works before the anime.js pass; anim.js re-targets the same
   `.inclus-check` elements. --tick-i (set per item in inclus.tpl)
   drives the stagger. Scoped to html.js so no-JS shows every tick;
   RTL-safe (scale/opacity only, no directional transform). */
html.js .inclus-col.reveal .inclus-check {
  opacity: 0;
  transform: scale(.4);
  transform-origin: center;
  transition: opacity var(--t-base) var(--ease-out),
    transform var(--t-base) var(--ease-spring);
  transition-delay: calc(var(--tick-i, 0) * 55ms);
}
html.js .inclus-col.reveal.visible .inclus-check {
  opacity: 1;
  transform: none;
}
@media (prefers-reduced-motion: reduce) {
  html.js .inclus-col.reveal .inclus-check {
    opacity: 1 !important;
    transform: none !important;
    transition: none !important;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   DUOTONE ICON SYSTEM (.dico) + FOOTER "editorial duotone" (2026-08)
   A crisp glyph on a soft tinted disc, with a small reduced-motion-safe motion
   library. Foundation for animated, relevant icons across the site.
   ══════════════════════════════════════════════════════════════════════════ */
.dico {
  --dico-size: 34px;
  inline-size: var(--dico-size);
  block-size: var(--dico-size);
  flex: none;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--accent-dim);
  color: var(--accent);
  transition: transform var(--t-base) var(--ease-spring),
              background var(--t-fast) var(--ease-out),
              color var(--t-fast) var(--ease-out);
}
.dico > svg { inline-size: 54%; block-size: 54%; display: block; }
.dico--sm { --dico-size: 28px; }
.dico--lg { --dico-size: 44px; }
.dico--amber { background: var(--accent-2-dim, var(--accent-dim)); color: var(--accent-2, var(--accent)); }

/* Relevant micro-motions — calm and slow; disabled under reduced-motion below. */
@keyframes dico-pulse { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.12); } }
@keyframes dico-ring  { 0%, 70%, 100% { transform: rotate(0); } 78% { transform: rotate(-13deg); } 87% { transform: rotate(11deg); } 95% { transform: rotate(-4deg); } }
@keyframes dico-drop  { 0%, 58%, 100% { transform: translateY(0); } 30% { transform: translateY(-4px); } 45% { transform: translateY(0); } }
@keyframes dico-bob   { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes dico-fly   { 0%, 100% { transform: translate(0, 0) rotate(-8deg); } 50% { transform: translate(2px, -3px) rotate(6deg); } }
.dico--pulse > svg { animation: dico-pulse 2.8s ease-in-out infinite; transform-origin: center; }
.dico--ring  > svg { animation: dico-ring 3.4s ease-in-out infinite; transform-origin: center; }
.dico--drop  > svg { animation: dico-drop 3s ease-in-out infinite; transform-origin: center bottom; }
.dico--fly   > svg { animation: dico-fly 3.6s ease-in-out infinite; }

@media (prefers-reduced-motion: reduce) {
  .dico > svg { animation: none !important; }
  .dico { transition: none; }
}

/* ── Footer destinations → icon-led rows with monument chips ──────────────── */
.footer-col--trips ul { gap: 4px; }
.footer-col--trips a {
  display: flex;
  align-items: center;
  gap: 11px;
  padding: 7px 10px;
  margin-inline: -10px;
  border-radius: var(--r2, 8px);
  background-image: none;            /* supersede the animated-underline treatment */
  color: var(--txt-2);
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.footer-col--trips a .dico { --dico-size: 30px; }
.footer-col--trips a:hover { background: rgba(255, 255, 255, .05); color: var(--txt-1); }
:root[data-theme="light"] .footer-col--trips a:hover { background: rgba(0, 44, 81, .05); }
.footer-col--trips a:hover .dico { transform: translateY(-2px); background: var(--accent); color: var(--bg-card); }
.footer-col--trips a:hover .dico > svg { animation: dico-bob .7s ease-in-out infinite; }
@media (prefers-reduced-motion: reduce) { .footer-col--trips a:hover .dico > svg { animation: none !important; } }

/* ── Footer contact → duotone chip heads with gentle idle motion ─────────── */
.footer-col--contact .phone-group__head { gap: 11px; color: var(--txt-2); }
.footer-col--contact .phone-group__head svg {
  width: 30px;
  height: 30px;
  padding: 7px;
  box-sizing: border-box;
  border-radius: 50%;
  background: var(--accent-dim);
  color: var(--accent);
  flex: none;
}
.footer-col--contact .phone-group:nth-of-type(1) .phone-group__head svg { animation: dico-pulse 2.8s ease-in-out infinite; transform-origin: center; }
.footer-col--contact .phone-group:nth-of-type(2) .phone-group__head svg { animation: dico-ring 3.6s ease-in-out infinite; transform-origin: center; }
.footer-col--contact .phone-group:nth-of-type(3) .phone-group__head svg { animation: dico-drop 3.2s ease-in-out infinite; transform-origin: center bottom; }
@media (prefers-reduced-motion: reduce) { .footer-col--contact .phone-group__head svg { animation: none !important; } }

/* ── Footer duotone — calmer + slightly smaller chips (feedback) ──────────── */
.footer-col--trips a .dico { --dico-size: 28px; }
.footer-col--contact .phone-group__head svg { width: 28px; height: 28px; }
.footer-col--contact .phone-group:nth-of-type(1) .phone-group__head svg { animation-duration: 5s; }
.footer-col--contact .phone-group:nth-of-type(2) .phone-group__head svg { animation-duration: 6s; }
.footer-col--contact .phone-group:nth-of-type(3) .phone-group__head svg { animation-duration: 5.5s; }

/* ── Feature icon chips — calm, staggered idle float (reduced-motion safe) ── */
.value-prop__icon > svg, .hl-card__icon > svg, .info-card__icon > svg { animation: dico-bob 5s ease-in-out infinite; }
.hl-card:nth-of-type(2n) .hl-card__icon > svg { animation-delay: .8s; }
.hl-card:nth-of-type(3n) .hl-card__icon > svg { animation-delay: 1.6s; }
.value-prop:nth-of-type(2) .value-prop__icon > svg { animation-delay: .7s; }
.value-prop:nth-of-type(3) .value-prop__icon > svg { animation-delay: 1.4s; }
@media (prefers-reduced-motion: reduce) {
  .value-prop__icon > svg, .hl-card__icon > svg, .info-card__icon > svg { animation: none !important; }
}

/* ══════════════════════════════════════════════════════════════════════════
   AGENCES — bento (map tile + location-switcher panel) (2026-08)
   ══════════════════════════════════════════════════════════════════════════ */
.branches-bento {
  margin-top: var(--s9, 48px);
  display: grid;
  grid-template-columns: minmax(0, 1.55fr) minmax(0, 1fr);
  gap: var(--space-4, 24px);
  align-items: stretch;
}
@media (max-width: 860px) { .branches-bento { grid-template-columns: 1fr; } }

.bento-tile {
  min-width: 0;                 /* let grid tracks shrink; prevents overflow */
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: var(--r3, 12px);
  overflow: hidden;
}
.bento-tile--map { padding: 0; }
/* The tile frames the map now, so strip the map's own frame + fix its height. */
.branches-bento .bento-tile--map #algeria-map {
  height: 100%;
  min-height: clamp(420px, 44vw, 560px);
  border: 0;
  border-radius: 0;
  box-shadow: none;
}
.bento-tile--panel {
  padding: var(--space-4, 24px);
  display: flex;
  flex-direction: column;
  gap: var(--space-3, 20px);
}

/* location switcher (segmented control) */
.loc-switch {
  display: flex;
  gap: 4px;
  padding: 4px;
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: var(--r4);
}
.loc-switch__tab {
  flex: 1 1 0;
  min-width: 0;                 /* allow labels to shrink instead of overflowing */
  overflow: hidden;
  text-overflow: ellipsis;
  min-height: 40px;
  padding: 8px 10px;
  border: 0;
  border-radius: var(--r4);
  background: transparent;
  color: var(--txt-2);
  font: inherit;
  font-size: var(--fs-caption);
  font-weight: 600;
  white-space: nowrap;
  cursor: pointer;
  transition: background var(--t-fast) var(--ease-out), color var(--t-fast) var(--ease-out);
}
.loc-switch__tab:hover { color: var(--txt-1); }
.loc-switch__tab.is-active { background: var(--accent); color: var(--bg-card); }

/* active branch detail */
.loc-detail { display: none; }
.loc-detail.is-active { display: flex; flex-direction: column; gap: var(--space-3, 18px); animation: locFade .28s var(--ease-out) both; }
html:not(.js) .loc-detail { display: flex; flex-direction: column; gap: var(--space-3, 18px); } /* no-JS: show all */
@keyframes locFade { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@media (prefers-reduced-motion: reduce) { .loc-detail.is-active { animation: none; } }

.loc-detail__head { display: flex; gap: 12px; align-items: flex-start; }
.loc-detail__head .dico { --dico-size: 40px; margin-top: 2px; }
.loc-detail__name { margin: 6px 0 3px; font-size: 1.15rem; font-weight: 700; line-height: 1.2; color: var(--txt-1); }
.loc-detail__addr { margin: 0; font-size: var(--fs-body-sm); line-height: 1.5; color: var(--txt-2); }

/* merged phone chips */
.loc-phones { display: flex; flex-wrap: wrap; gap: 8px; }
.loc-phone {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 8px 14px 8px 10px;
  border-radius: var(--r4);
  border: 1px solid var(--border-hi);
  background: var(--bg);
  color: var(--txt-1);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
  font-size: var(--fs-body-sm);
  transition: border-color var(--t-fast) var(--ease-out), background var(--t-fast) var(--ease-out), transform var(--t-fast) var(--ease-out);
}
.loc-phone svg { width: 18px; height: 18px; color: var(--wa-green); flex: none; }
.loc-phone:hover { border-color: var(--wa-green); background: var(--accent-dim); transform: translateY(-1px); }

.loc-dir { align-self: flex-start; gap: 8px; margin-top: 2px; }
.loc-dir svg { width: 16px; height: 16px; }

/* The contact card carries a duplicate branch mini-list; force it to a single
   column so its 3×240px grid can't push the page into horizontal scroll. */
.contact-card .branch-list { grid-template-columns: 1fr; }


/* ── Hero type — Sora display face restored (owner call 2026-08-13) ──────────
   The v28 "one family per role" pass put heroes on Fraunces, whose italic em
   ("fully sorted") the owner rejected as unreadable. Heroes go back to the
   approved Sora treatment (daf58e5): modern geometric sans, weight 600, accent
   line in brand green, no italic. Section headings stay on Fraunces — this is
   hero-scoped. RTL remaps --font-hero-display to Cairo (Sora has no Arabic). */
.home-hero .hero__title { font-family: var(--font-hero-display); font-weight: 600; font-size: clamp(2.3rem, 1.7rem + 3vw, 4rem); line-height: 1.08; letter-spacing: -.02em; }
.home-hero .hero__title em { font-family: var(--font-hero-display); font-style: normal; font-weight: 600; font-size: .56em; color: var(--accent); }

.aurora-hero__title { font-family: var(--font-hero-display, var(--font-display)); font-weight: 600; font-size: clamp(2.5rem, 7.4vw, 5.4rem); line-height: 1; letter-spacing: -.02em; }
.aurora-hero__title em { font-family: var(--font-hero-display, var(--font-display)); font-style: normal; }

/* Promoted from the two pages' inline <style> (visual audit A16): the base
   .hero is min-height:100svh + display:grid, so a short service hero left
   242px of dead space under it. Content-sized here instead. */
.hero--service {
  min-height: auto;
  align-content: center;
  padding-block: clamp(80px, 12vh, 140px) clamp(48px, 6vh, 80px);
}
.hero--service .hero__title { font-family: var(--font-hero-display); font-weight: 600; font-size: clamp(2.3rem, 1.7rem + 3vw, 4rem); line-height: 1.08; letter-spacing: -.02em; }
.hero--service .hero__title em { font-family: var(--font-hero-display); font-style: normal; font-weight: 600; font-size: .82em; color: var(--accent); }


/* ── Maker's mark — site credit, the very last line of every page ──────────
   Signature in the body face's true italic; NUMIDIEA LABS as a letterspaced
   Sora wordmark in the brand green, joined by a hairline accent stroke.
   Logical properties + baseline flex keep it correct in RTL and both themes. */
.madeby {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: center;
  gap: 6px 10px;
  margin-block-start: var(--s6, 24px);
  padding-block-start: var(--s5, 18px);
  border-block-start: 1px solid rgba(255, 255, 255, .06);
  font-size: var(--fs-caption); color: var(--txt-3);
}
.madeby__made { letter-spacing: .02em; }
.madeby__sig  { font-style: italic; color: var(--txt-2); }
.madeby__sep  { inline-size: 22px; block-size: 1px; align-self: center;
                background: linear-gradient(90deg, transparent, var(--accent), transparent); }
.madeby__brand {
  font-family: var(--font-display);
  font-weight: 700; font-size: var(--fs-2xs);
  letter-spacing: .22em; text-transform: uppercase;
  color: var(--accent); white-space: nowrap;
}
.madeby__tm { font-size: .6em; letter-spacing: 0; vertical-align: super; margin-inline-start: 2px; opacity: .8; }
:root[data-theme="light"] .madeby { border-color: rgba(0, 44, 81, .08); }
/* Arabic: the Latin wordmark keeps its own tracking, the signature stays upright
   (Noto Sans Arabic has no italic — a synthesized slant would look broken). */
:root[lang="ar"] .madeby__sig { font-style: normal; }

/* ── Typographic finish: balanced headings, no orphans ─────────────────────
   Measured before writing this (1081px and 1680px, live): measure already caps
   at 59-77 characters, body line-height is 1.6-1.65 and paragraph rhythm is
   16-24px — the fundamentals were sound, so nothing here changes size, weight
   or spacing. What was missing was line-BREAKING quality: `text-wrap` appeared
   zero times in this file, so every heading could drop a single orphan word
   onto its own last line ("Votre / réservation") and paragraphs could end on a
   one-word runt. Both are pure progressive enhancement — a browser without
   support ignores the declaration and renders exactly as it does today, so
   there is no fallback to maintain and no layout risk.

   balance -> short blocks (headings, eyebrows, leads): the browser evens the
   line lengths, which is what stops the orphan word.
   pretty  -> long blocks (body copy): keeps normal line-breaking speed but
   refuses to leave a runt on the final line. */
h1, h2, h3, h4, h5, h6,
.hero__title, .aurora-hero__title, .section-head__title,
.hl-card__title, .hotel-card__name, .bform-block__title,
.final-cta__title, .inclus-col__title, .trip-card__title {
  text-wrap: balance;
}

/* Leads and subtitles are 2-3 lines — balancing reads as deliberate there. */
.section-head__sub, .hero__lede, .hero__fineprint, .bform-hint {
  text-wrap: balance;
}

/* Running copy: prevent the one-word last line without touching the rhythm. */
p, li, dd, blockquote, figcaption, .testi-text {
  text-wrap: pretty;
}

/* Arabic is cursive and joins: `balance` may re-break mid-phrase in ways that
   read oddly, and RTL support is less mature. Keep AR on normal wrapping. */
:root[lang="ar"] h1, :root[lang="ar"] h2, :root[lang="ar"] h3,
:root[lang="ar"] h4, :root[lang="ar"] h5, :root[lang="ar"] h6,
:root[lang="ar"] .hero__title, :root[lang="ar"] .aurora-hero__title,
:root[lang="ar"] .section-head__title, :root[lang="ar"] .section-head__sub,
:root[lang="ar"] p, :root[lang="ar"] li {
  text-wrap: wrap;
}

/* Legal links in the footer bottom bar (mentions légales / confidentialité / CGV).
   Added 2026-08-31: the site collects passport data and had no legal pages at all. */
.footer-links { margin: var(--s2) 0 0; font-size: var(--fs-caption); color: var(--txt-3); }
.footer-links a { color: var(--txt-3); text-decoration: none; border-bottom: 1px solid transparent; transition: color var(--t-fast), border-color var(--t-fast); }
.footer-links a:hover, .footer-links a:focus-visible { color: var(--accent); border-bottom-color: var(--accent); }

/* Consent opt-in gating the optional passport fields in the booking form.
   Added 2026-08-31: the form collected passport numbers and dates of birth with
   no notice and no opt-in. The fields stay hidden until this is ticked. */
.bf-consent { display: flex; gap: var(--s3); align-items: flex-start; margin: var(--s3) 0 var(--s4);
  padding: var(--s4); border: 1px solid var(--border); border-radius: var(--r2);
  background: var(--bg-2); cursor: pointer; font-size: var(--fs-body-sm); color: var(--txt-2);
  line-height: var(--lh-normal); }
.bf-consent:hover { border-color: var(--border-hi); }
.bf-consent input { flex: 0 0 auto; width: 18px; height: 18px; margin-top: 1px; accent-color: var(--accent); cursor: pointer; }
.bf-consent:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-dim); }

/* ── 2026-09-05 mobile nav fixes (visual audit, Lens B) ─────────────────── */
@media (max-width: 900px) {
  /* #nav-drawer is a child of nav.site-nav, so `.site-nav .nav-links{margin-inline:auto}`
     leaked into the drawer and indented the menu 73px while the switcher, toggle and
     WhatsApp button hugged the left edge. */
  .nav-drawer .nav-links { margin-inline: 0; align-items: stretch; width: 100%; }
  .nav-drawer .theme-toggle { min-width: var(--touch-min); min-height: var(--touch-min); }
  /* `.site-nav > .trip-switcher{order:3}` sat to the RIGHT of the burger on every
     non-home page. The hamburger is always last. */
  .site-nav > .nav-hamburger { order: 5; }
}

/* A22 — .container is capped at 1280 while --container-x keeps growing to 80px,
   so the readable column NARROWS to 1120px on the widest screens. Give the cap
   a little back above 1600 (visual audit, desktop lens). */
@media (min-width: 1600px) {
  .container { max-width: 1296px; }
}

/* D12 — .agency-title and .contact-main__title carried an inline
   clamp(28px,4vw,48px), so they rendered 48px next to a 40px .section-head__title
   on the same page. Same scale as the shared title now; h2 has no size of its own,
   so this rule is what sizes them. */
.agency-title,
.contact-main__title {
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.1;
}

/* ── 2026-09-05 · visual audit, wave 2 (mobile + tablet) ────────────────── */

/* M7 — a native select stripped of its arrow with nothing put back reads as a
   flat box. One inline chevron, both themes, no extra request. */
/* The seven trip JSONs each carried this as an inline style attribute on the
   <select>, which also meant an inline `background` shorthand that wiped the
   caret image below. One rule, no copies. */
#hotel-select {
  border: 1px solid var(--border);
  border-radius: var(--r2);
  padding: var(--space-3) var(--space-4);
  width: 100%;
  cursor: pointer;
  color: var(--txt-1);
}

#hotel-select,
.contact-form select,
#bf-office {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%238e857a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
  background-color: var(--bg);
  background-repeat: no-repeat;
  background-position: right var(--s3) center;
  background-size: 16px 16px;
  padding-inline-end: calc(var(--s3) * 2 + 16px);
}
:root[lang="ar"] #hotel-select,
:root[lang="ar"] .contact-form select,
:root[lang="ar"] #bf-office {
  background-position: left var(--s3) center;
}

/* M10 — the one-departure fallback that replaces a single-option radiogroup. */
.date-chips__next {
  margin: 0;
  font-size: var(--fs-body-sm);
  color: var(--txt-2);
  line-height: 1.6;
}
.date-chips__next strong { color: var(--txt-1); }
.date-chips__next a {
  color: var(--accent);
  text-decoration: underline;
  text-underline-offset: 3px;
}

@media (max-width: 900px) {
  /* M12 — these are 44px at 375 but shrank at tablet, because every touch rule
     lived in a ≤640 block: footer links 24px, filter pills 35, share 36. */
  .dest-filter__pill,
  .trip-switcher__trigger {
    min-height: var(--touch-min);
    display: inline-flex;
    align-items: center;
  }
  .trip-card__share {
    width: 44px;
    height: 44px;
    opacity: 1;   /* no hover on touch — the affordance has to be there at rest */
  }
  .footer-col a {
    min-height: var(--touch-min);
    display: flex;
    align-items: center;
  }
  /* M13 — 11px eyebrows and 12px table cells are below the readable floor. */
  .section-head__eyebrow { font-size: var(--fs-caption); }
}

/* M12 — 900ms entrances mean a fast scroller reads content at 10–20% opacity.
   Touch scrolling is faster than wheel scrolling, so shorten it there. */
@media (pointer: coarse) {
  [data-fx] {
    transition-duration: 400ms;
  }
}
