/* =====================================================================
   Mauritius Aura — the site's one stylesheet.

   Order matters and later tasks append to the end, under their own commented
   header. Never re-declare a token below :root; if a value needs to change,
   change the token.

   FOUNDATION (this file's first half): fonts, tokens, base elements, buttons,
   focus, header, menu panel, footer, phone bottom nav, reveal, reduced motion.
   ===================================================================== */

/* -------------------------------------------------------------- fonts ---
   Self-hosted Latin + Latin-1 subsets, so French accents including capitals
   (É, Î, Ç) are covered without a second request. All swap, each with a
   metric-matched local fallback so the swap costs no layout shift.

   NOTE: Google serves Inter's latin subset as ONE variable file covering the
   whole weight axis — the CSS it hands out points both the 400 and the 600
   face at the same URL. So there is no separate inter-600.woff2 to download:
   both faces below load inter-400.woff2 and the browser instantiates the
   weight. Two files here would be the same bytes twice.                    */

@font-face {
  font-family: 'Anton';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/anton-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Barlow Semi Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/barlow-semi-condensed-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/inter-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/inter-400.woff2') format('woff2'); /* same variable file — see note above */
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* The display serif (every headline on every page). An inscriptional roman:
   wide, low contrast, even colour, and it holds its shape at any size — which
   is what the face it replaced did not. Instrument Serif was here until
   2026-09-28 and shipped two files, because it had an italic for one emphasis
   rule. Marcellus has no italic at all; nothing in src/ uses <em> inside a
   heading, so that rule was styling nothing, and one 14 KB file now does the
   work of 43 KB. The same Latin-1 subset as the others, so French capitals
   with accents are covered. */
@font-face {
  font-family: 'Marcellus';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/marcellus-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* Metric-matched fallbacks. These are what the page paints with during the
   swap; the overrides make the fallback occupy the same box as the real face,
   which is what keeps CLS at 0 rather than merely small. Re-tune against the
   Task 23 measurement, not by eye. */
@font-face {
  font-family: 'Anton Fallback';
  src: local('Impact'), local('Haettenschweiler'), local('Arial Narrow Bold');
  size-adjust: 92%;
  ascent-override: 105.4%;
  descent-override: 23.7%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Barlow Fallback';
  src: local('Arial Narrow'), local('Arial');
  size-adjust: 86%;
  ascent-override: 116%;
  descent-override: 29%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Inter Fallback';
  src: local('Arial');
  size-adjust: 107%;
  ascent-override: 90.5%;
  descent-override: 22.6%;
  line-gap-override: 0%;
}
/* Measured, not eyeballed — the value this replaced said so itself.
   ascent/descent are Marcellus's own metrics straight out of the woff2
   (hhea 1994/2048 and 574/2048). size-adjust is the ratio of the two faces'
   advance widths over four real headlines at the same size, taken in Chrome
   with canvas measureText: Marcellus sets 92.2% as wide as Georgia. Redo it
   the same way if the face ever changes; do not adjust it by eye. */
@font-face {
  font-family: 'Marcellus Fallback';
  src: local('Georgia'), local('Times New Roman');
  size-adjust: 92.2%;
  ascent-override: 97.4%;
  descent-override: 28%;
  line-gap-override: 0%;
}

/* ------------------------------------------------------------- tokens --- */
:root {
  /* This site has ONE palette and it is light. Without this declaration a
     browser assumes the page can go either way, and Chrome's Auto Dark Theme
     (Android: Settings > Accessibility, or the auto-dark flag) re-colours the
     whole page on the fly — the client saw the site served on a near-black
     background with inverted text on 2026-09-21. Declaring `light` opts every
     engine out of that automatic inversion; it is not a preference, it is the
     only scheme these tokens are contrast-checked against. There is a matching
     <meta name="color-scheme" content="light"> in src/layout.js, which is what
     covers the first paint before this stylesheet has loaded. Change both or
     neither. Adding a real dark theme means new tokens with their own contrast
     ratios, not flipping this value. */
  color-scheme: light;

  /* Colour — carried over unchanged from the 2026-09-12 design system.
     --gold on white is 3.45:1: fine for 24px+ display type, fails for 12px
     labels, and fails just as hard as a button fill behind a white one.
     --gold-ink is the logo's darkest gold, 5.62:1: small text, and the only
     gold a button may put a 14px white label on.
     --gold-lt is its highlight gold, 6.95:1 on --deep. */
  --deep: #043D4C;
  --deep-2: #075A6C;
  --deep-ink: #022B36;
  --gold: #B3812A;
  --gold-lt: #E9C174;
  --gold-ink: #8A5F1C;
  --cream: #F2EAD8;
  /* The logo's sea blue. --sea is decorative (waves, rules); --sea-ink is the
     6.16:1 text-safe version; --aqua-lt is 6.99:1 on --deep. */
  --sea: #019BB5;
  --sea-ink: #036B7E;
  --aqua-lt: #7FD4E2;
  --paper: #ffffff;
  --paper-2: #FAF8F4;
  --paper-3: #F3EFE8;
  --line: #E3DCD0;
  --line-2: #D3C9B7;
  /* --line-2 is 1.64:1 on white: right for a decorative rule, not enough for
     the edge of an input, which 1.4.11 treats as a UI component boundary. */
  --line-ctrl: #9A8E77;
  /* The header is sticky and the phone nav is fixed, so anything scrolled to by
     the browser -- a skip link, sequential focus -- must clear both. */
  scroll-padding-block-start: calc(var(--hdr-h) + 12px);
  --text: #10333D;
  --muted: #4F6A74;

  --r: 14px;
  --r-sm: 10px;
  --r-lg: 24px;
  --r-pill: 999px;
  --wrap: 1200px;
  --shadow: 0 1px 2px rgba(4, 61, 76, .05), 0 8px 28px -12px rgba(4, 61, 76, .18);
  --shadow-lg: 0 2px 6px rgba(4, 61, 76, .06), 0 26px 60px -26px rgba(4, 61, 76, .34);
  /* Resting card shadow: long, soft and mostly clipped, so a card reads as
     sitting on the page rather than floating above it. */
  --shadow-card: 0 18px 50px -38px rgba(2, 43, 54, .5);

  /* Motion. The built-in CSS easings are too weak to read as deliberate, so
     these are the standard strong curves — do not hand-roll new ones.
     --ease-out for anything entering or leaving, --ease-in-out for something
     moving across the screen, plain `ease` for hover and colour. */
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --t-press: 160ms;  /* button press feedback */
  --t-hover: 300ms;  /* hover / colour */
  --t-move: 250ms;   /* something sliding to a new position */
  --t-enter: 560ms;  /* marketing entrance — allowed over 300ms, UI is not */

  /* Type */
  /* Display is the editorial serif on every page (it started on the home page
     and the inner pages followed, so the site reads as one voice). Anton stays
     for the big numerals only — stop numbers, step numbers, booking references. */
  --font-display: 'Marcellus', 'Marcellus Fallback', Georgia, 'Times New Roman', serif;
  --font-num: 'Anton', 'Anton Fallback', Impact, 'Arial Narrow Bold', sans-serif;
  --font-sub: 'Barlow Semi Condensed', 'Barlow Fallback', 'Arial Narrow', sans-serif;
  --font-body: 'Inter', 'Inter Fallback', system-ui, Arial, sans-serif;
  --fs-display: clamp(2.9rem, 1.4rem + 5.8vw, 6.25rem);
  --fs-h2: clamp(2.3rem, 1.3rem + 3.6vw, 4.1rem);
  --fs-h3: clamp(1.25rem, 1rem + .8vw, 1.6rem);
  --fs-body: 1rem;
  --fs-small: .875rem;
  /* Display leading. Headlines are sentence case now, so accented capitals only
     ever open a line and never sit under another line's descenders; the serif
     can run tight. Checked on the two-line FR titles ("De belles journées. /
     De beaux endroits.") at 390 and 1440 px. */
  --lh-display: 1.02;

  /* Spacing */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 72px;

  --hdr-h: 72px;
  --gutter: clamp(16px, 4vw, 40px);
  --mnav-h: 62px; /* app.js overwrites this with the bar's measured height */
}

/* -------------------------------------------------------------- base --- */
*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; }
/* scroll-behavior:smooth is NOT set here. Combined with any snapping or
   overflow container it can suppress the page's LCP entry entirely (HANDOVER,
   "The scroll-snap strip is gone"). Smooth scrolling is opted into per
   interaction in JS instead. */

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font: 400 var(--fs-body)/1.65 var(--font-body);
  -webkit-font-smoothing: antialiased;
  overflow-x: clip;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; cursor: pointer; }
h1, h2, h3, h4, p, figure, ul, ol { margin: 0; }
/* No one-word last lines. Balanced headlines (.display) keep their own rule. */
p { text-wrap: pretty; }
ul, ol { padding: 0; list-style: none; }
strong, b { font-weight: 600; }
:where(h1, h2, h3) { font-weight: 600; line-height: 1.15; }

.wrap {
  width: 100%;
  max-width: calc(var(--wrap) + var(--gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.section { padding-block: clamp(64px, 8vw, 120px); }
.section--tint { background: var(--paper-2); }
.section--deep { background: var(--deep); color: var(--cream); }

/* Demo-price notice. Rendered only while a mock scenario is active (the client
   preview Worker), never on the real site. A plain in-flow strip under the
   sticky header, raised one step so nothing can paint over it. */
.demo-note {
  position: relative;
  z-index: 99;
  margin: 0;
  padding: 10px var(--space-4);
  background: var(--deep-ink);
  color: var(--cream);
  text-align: center;
  font-size: 13px;
  line-height: 1.5;
}

/* Skip link. Visible the moment it is focused, and nowhere else. */
.skip {
  position: fixed;
  z-index: 200;
  inset-block-start: var(--space-3);
  inset-inline-start: var(--space-3);
  padding: 12px 18px;
  border-radius: var(--r-sm);
  background: var(--deep);
  color: #fff;
  font-weight: 600;
  translate: 0 -200%;
  transition: translate var(--t-move) var(--ease-out);
}
.skip:focus-visible { translate: 0 0; }
#main:focus { outline: none; }

/* The header's scroll sentinel: 80 px of nothing at the top of the document.
   app.js watches it instead of listening to scroll. */
.hdr-sentinel {
  position: absolute;
  inset-block-start: 0;
  inset-inline-start: 0;
  width: 1px;
  height: 80px;
  pointer-events: none;
}

.eyebrow {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.section--deep .eyebrow, .ftr .eyebrow { color: var(--gold-lt); }

.lede {
  color: var(--muted);
  font-size: clamp(1rem, .96rem + .2vw, 1.125rem);
  max-width: 58ch;
}
.section--deep .lede { color: color-mix(in srgb, var(--cream) 82%, transparent); }

/* Display headings. A single-weight serif, sentence case, tracked slightly
   tight: the letterforms carry the emphasis, so it never needs a bolder weight
   or capitals. An <em> inside one is the italic, for one word at most. */
.display, h1.display, h2.display {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--lh-display);
  letter-spacing: -.005em;
  text-wrap: balance;
  color: var(--deep);
  font-variant-numeric: lining-nums;
}
.display em { font-style: normal; color: var(--gold-ink); }
.section--deep .display em, .ftr .display em { color: var(--gold-lt); }
h1.display { font-size: var(--fs-display); }
h2.display { font-size: var(--fs-h2); }
.section--deep .display, .ftr .display { color: var(--cream); }

.sub {
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.2;
  letter-spacing: .01em;
}

.sec-mark { display: flex; align-items: center; gap: 14px; margin-bottom: 14px; }
.mark {
  --mark-sun: var(--gold);
  --mark-sea: var(--sea);
  width: 54px;
  height: 19px;
  flex: 0 0 auto;
  overflow: visible;
}
.section--deep .mark, .ftr .mark { --mark-sun: var(--gold-lt); --mark-sea: var(--aqua-lt); }

.placeholder-note {
  display: inline-block;
  margin-block: var(--space-5) var(--space-6);
  padding: 10px 16px;
  border: 1px dashed var(--gold);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--gold-lt) 18%, var(--paper));
  color: var(--gold-ink);
  font-size: var(--fs-small);
  font-weight: 600;
}

/* ------------------------------------------------------------ buttons --- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  min-height: 44px;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: .01em;
  text-align: center;
  background: none;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease,
              border-color var(--t-hover) ease, box-shadow var(--t-hover) ease,
              scale var(--t-press) var(--ease-out);
}
.btn .arw, .btn svg { width: 18px; height: 18px; flex: 0 0 auto; }
.btn .arw { display: inline-flex; transition: translate var(--t-hover) var(--ease-out); }
.btn:active { scale: .97; }

.btn--deep { background: var(--deep); color: #fff; }
/* The primary CTA. --gold behind a 14px white label is 3.45:1, which the token
   block above calls out as display-type-only, so the fill is --gold-ink
   (5.62:1 with white) and hover goes darker still rather than lighter. */
.btn--gold { background: var(--gold-ink); color: #fff; }
.btn--light { background: var(--paper); color: var(--deep); border-color: var(--line); }
.btn--ghost-lt { color: var(--gold-lt); border-color: color-mix(in srgb, var(--gold-lt) 45%, transparent); }

@media (hover: hover) and (pointer: fine) {
  .btn:hover .arw { translate: 3px 0; }
  .btn--deep:hover { background: var(--deep-2); }
  .btn--gold:hover { background: color-mix(in srgb, var(--gold-ink) 84%, var(--deep-ink)); }
  .btn--light:hover { border-color: var(--line-2); box-shadow: var(--shadow); }
  .btn--ghost-lt:hover { background: color-mix(in srgb, var(--gold-lt) 14%, transparent); border-color: var(--gold-lt); }
}

/* -------------------------------------------------------------- focus --- */
/* --gold-lt is 1.70:1 on --paper and 1.00:1 on the finder's own gold band, so
   as a ring on a light surface it failed 1.4.11 outright -- and the dark-section
   rule below sets the very same colour, which is what gave it away as a copy
   rather than a decision. --deep is 11.8:1 on paper and reads on every light
   surface the site has; gold stays where it belongs, on the dark ones. */
:focus-visible {
  outline: 3px solid var(--deep);
  outline-offset: 2px;
  border-radius: 4px;
}
.section--deep :focus-visible, .ftr :focus-visible, .hdr:not(.hdr--solid) :focus-visible {
  outline-color: var(--gold-lt);
}

/* ------------------------------------------------------------- header --- */
.hdr {
  position: sticky;
  inset-block-start: 0;
  z-index: 100;
  color: #fff;
  transition: background-color var(--t-hover) ease, box-shadow var(--t-hover) ease,
              border-color var(--t-hover) ease;
  border-block-end: 1px solid transparent;
}
.hdr-in {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: var(--hdr-h);
}
.hdr--solid {
  background: var(--deep);
  border-block-end-color: color-mix(in srgb, var(--gold-lt) 22%, transparent);
  box-shadow: 0 10px 30px -22px rgba(2, 43, 54, .9);
}
/* Over a photo hero the bar is transparent and the logo sits on the image;
   app.js adds .hdr--solid the moment the 80 px sentinel leaves the viewport. */
.hdr[data-hdr="over"]:not(.hdr--solid) { background: linear-gradient(rgba(2, 43, 54, .42), transparent); }

.hdr-logo { flex: 0 0 auto; display: block; }
.hdr-logo img { width: auto; height: 36px; }

/* `display:contents` would flatten the box but has a history of dropping the
   landmark from the accessibility tree, so the nav stays a real flex box. */
.nav {
  display: flex;
  align-items: center;
  gap: clamp(16px, 2vw, 32px);
  margin-inline-start: auto;
}
.nav-list {
  display: flex;
  align-items: center;
  gap: clamp(14px, 1.8vw, 28px);
  font-size: var(--fs-small);
  font-weight: 600;
}
.nav-list a {
  display: inline-block;
  padding-block: 10px;
  position: relative;
  /* French labels are the long ones ("Transport entreprise"). A wrapped nav item
     breaks the bar's baseline, so items never wrap — the row scales down and
     then collapses into the menu instead. */
  white-space: nowrap;
  color: color-mix(in srgb, #fff 88%, transparent);
  transition: color var(--t-hover) ease;
}
.nav-list a::after {
  content: "";
  position: absolute;
  inset-block-end: 4px;
  inset-inline: 0;
  height: 2px;
  background: var(--gold-lt);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) var(--ease-out);
}
.nav-list a[aria-current="page"] { color: #fff; }
.nav-list a[aria-current="page"]::after { transform: scaleX(1); }
@media (hover: hover) and (pointer: fine) {
  .nav-list a:hover { color: #fff; }
  .nav-list a:hover::after { transform: scaleX(1); }
}

.nav-act { display: flex; align-items: center; gap: var(--space-3); }

/* Language: a three-up segment rather than a globe. A globe says a language
   choice exists somewhere; it does not say which language you are reading or
   what you would get. All three codes fit, so the control answers both at a
   glance, and it never has to collapse into an icon that answers neither. Codes
   and not flags: Mauritius speaks these languages, and a flag is a country. */
.lang {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid color-mix(in srgb, #fff 22%, transparent);
  border-radius: 999px;
}
.lang-o {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 35px;
  min-height: 34px;
  padding-inline: 8px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: .07em;
  color: color-mix(in srgb, #fff 78%, transparent);
  transition: color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.hdr--solid .lang { border-color: color-mix(in srgb, var(--cream) 20%, transparent); }
.hdr--solid .lang-o { color: color-mix(in srgb, var(--cream) 80%, transparent); }
/* Listed after the .hdr--solid rule and matching it for specificity, or the
   solid header's cream wins over the active pill and paints cream on gold at
   about 1.3:1 — which is what it did until this line existed. --deep on
   --gold-lt measures 6.9:1. */
.lang-o--on, .hdr--solid .lang-o--on { background: var(--gold-lt); color: var(--deep); }
@media (hover: hover) and (pointer: fine) {
  a.lang-o:hover { color: #fff; background: color-mix(in srgb, #fff 14%, transparent); }
}

/* Currency (spec 5.4): the language control's pill with three options, and three
   links to ?cur=, never a script. On the page it sits on paper and takes ink
   colours; .cur--hdr is the copy in the menu panel and takes the header's. The
   desktop bar never shows it: at >= 1280 px the French bar has 7-22 px to spare
   (spec D4), so the panel is the only place in the header it fits. */
.cur {
  display: inline-flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2);
  font-size: var(--fs-small);
  color: var(--muted);
}
.cur-opts {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border: 1px solid var(--line-2);
  border-radius: 999px;
}
.cur-o {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 40px;
  min-height: 36px;
  padding-inline: 10px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 700;
  color: var(--deep);
  transition: color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.cur-o--on { background: var(--deep); color: var(--cream); }
.cur--hdr { display: none; color: color-mix(in srgb, var(--cream) 80%, transparent); }
.cur--hdr .cur-opts { border-color: color-mix(in srgb, var(--cream) 20%, transparent); }
.cur--hdr .cur-o { min-width: 52px; min-height: 44px; color: color-mix(in srgb, var(--cream) 80%, transparent); }
/* After the rule above and matching it for specificity, for the reason the
   .lang-o--on note gives: otherwise cream lands on gold. */
.cur--hdr .cur-o--on { background: var(--gold-lt); color: var(--deep); }
@media (max-width: 1279px) {
  .cur--hdr { display: inline-flex; }
}
@media (hover: hover) and (pointer: fine) {
  a.cur-o:hover { background: var(--paper-3); }
  .cur--hdr a.cur-o:hover { color: #fff; background: color-mix(in srgb, #fff 14%, transparent); }
}

.hdr-tel {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  min-height: 44px;
  font-size: var(--fs-small);
  font-weight: 600;
  color: color-mix(in srgb, #fff 88%, transparent);
  transition: color var(--t-hover) ease;
}
.hdr-tel svg { width: 17px; height: 17px; flex: 0 0 auto; }
.hdr-tel span { white-space: nowrap; }
.hdr--solid .hdr-tel { color: color-mix(in srgb, var(--cream) 88%, transparent); }
@media (hover: hover) and (pointer: fine) {
  .hdr-tel:hover { color: var(--gold-lt); }
}

.burger {
  display: none;
  align-items: center;
  gap: 9px;
  margin-inline-start: auto;
  min-height: 44px;
  padding: 0 4px;
  border: 0;
  background: none;
  color: inherit;
  font-size: var(--fs-small);
  font-weight: 600;
}
/* The label follows the glyph: an X captioned "Menu" says two things at once. */
.burger[aria-expanded="false"] .burger-txt[data-when="open"],
.burger[aria-expanded="true"] .burger-txt[data-when="closed"] { display: none; }

.burger-bars { display: grid; gap: 4px; width: 20px; }
.burger-bars i {
  display: block;
  height: 2px;
  background: currentColor;
  border-radius: 2px;
  transition: translate var(--t-move) var(--ease-out), rotate var(--t-move) var(--ease-out), opacity var(--t-move) ease;
}
/* Open = an X, not three bars sliding into one dash: translate first, then
   rotate, so the two strokes cross on the middle bar's line. */
.burger[aria-expanded="true"] .burger-bars i:nth-child(1) { translate: 0 6px; rotate: 45deg; }
.burger[aria-expanded="true"] .burger-bars i:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] .burger-bars i:nth-child(3) { translate: 0 -6px; rotate: -45deg; }

/* ---- the menu panel, below 1280 px ----
   Was 960, and in French that was wishful. Measured on /fr/location-voiture:
   the logo, five nav labels and three actions want 1178 px of content width,
   and 960 px of viewport offers 945. "Organiser mon séjour" was cut off by the
   viewport edge on every French page from 960 up to about 1270. English fits
   in roughly 970, which is why nobody saw it.
   1178 needs viewport - scrollbar - 2 gutters >= 1178, so 1280 is the first
   round width that clears it; above 1300 the wrap caps at 1200 and the margin
   settles at 22 px. Both languages now get the bar only where the bar works. */
@media (max-width: 1279px) {
  .burger { display: inline-flex; }
  .nav {
    display: block;
    margin-inline-start: 0;
    position: fixed;
    inset: var(--hdr-h) 0 0 0;
    padding: var(--space-6) var(--gutter) calc(var(--space-8) + env(safe-area-inset-bottom));
    background: var(--deep);
    overflow-y: auto;
    overscroll-behavior: contain;
    opacity: 0;
    visibility: hidden;
    translate: 0 -12px;
    transition: opacity var(--t-move) ease, translate var(--t-move) var(--ease-out), visibility 0s linear var(--t-move);
  }
  .nav[data-open] {
    opacity: 1;
    visibility: visible;
    translate: 0 0;
    transition-delay: 0s;
  }
  .nav-list {
    display: grid;
    gap: 2px;
    margin: 0;
    font-size: 1.25rem;
    font-family: var(--font-sub);
    font-weight: 600;
  }
  /* The rule belongs to the row, not to the words: on the anchor it would stop
     at the end of the text and read as an underline. */
  .nav-list li { border-block-end: 1px solid color-mix(in srgb, var(--gold-lt) 18%, transparent); }
  .nav-list a { display: block; padding-block: 14px; }
  .nav-list a::after { display: none; }
  .nav-list a[aria-current="page"] { color: var(--gold-lt); }
  .nav-act {
    display: grid;
    gap: var(--space-3);
    justify-items: start;
    margin-block-start: var(--space-6);
  }
  /* In the bar the pills are pointer targets and 34 px is plenty; in the panel
     they are thumb targets, and the panel has the room the bar does not. */
  .lang-o { min-width: 52px; min-height: 44px; font-size: 13px; }
  .hdr-cta { width: 100%; }
  /* The header itself must stay above the panel it opens, and must stop being
     a containing block while it does. A backdrop-filter other than none makes
     its element the containing block for fixed descendants, and the menu panel
     is a fixed descendant of the header -- so the frosted header added in the
     home polish pass silently re-anchored "inset: var(--hdr-h) 0 0 0" to the
     header box. The panel rendered 104 px tall instead of 772 and spilled its
     own contents over the page behind it, on every phone, on every page whose
     header is solid. The blur has nothing to do while the menu is open anyway:
     the line below paints the header opaque. */
  .hdr[data-menu-open] {
    background: var(--deep);
    -webkit-backdrop-filter: none;
    backdrop-filter: none;
  }
  body[data-menu-open] { overflow: hidden; }
}

@media (min-width: 1280px) {
  .hdr-cta { margin-inline-start: var(--space-1); }
}
.hdr-cta { white-space: nowrap; }
/* The phone number is the one header item that goes first when space runs out —
   it is repeated in the footer and in the bottom nav. The bar carries five FR
   nav labels plus three actions, so the text goes well before 1140px. */
/* The number itself never rides in the bar now, at any width. It used to appear
   above 1365, and that is 90 px French does not have: with the label showing,
   the French row wants 1268 px inside a wrap that caps at 1200. The icon still
   dials, and the number is written out in the footer and in the phone bottom
   nav, which is where people look for it. */
@media (min-width: 1280px) {
  .hdr-tel span { display: none; }
}

/* ------------------------------------------------------------- footer --- */
.ftr {
  position: relative;
  background: var(--deep-ink);
  color: color-mix(in srgb, var(--cream) 82%, transparent);
  padding-block: var(--space-8) var(--space-6);
  font-size: var(--fs-small);
}
.ftr-horizon {
  display: flex;
  justify-content: center;
  margin-block-end: var(--space-7);
}
.ftr-horizon .mark { width: 92px; height: 32px; opacity: .85; }
.ftr-in {
  display: grid;
  gap: var(--space-7) var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
}
.ftr-brand { grid-column: 1 / -1; max-width: 32ch; }
.ftr-logo { width: auto; height: 40px; }
.ftr-tag {
  margin-block-start: var(--space-4);
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: 1.25rem;
  color: var(--cream);
}
.ftr-col h2 {
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold-lt);
  margin-block-end: var(--space-4);
}
.ftr-col ul { display: grid; gap: 10px; }
.ftr-col a { transition: color var(--t-hover) ease; }
@media (hover: hover) and (pointer: fine) {
  .ftr-col a:hover { color: var(--gold-lt); }
}
.ftr-contact li { display: grid; grid-template-columns: 18px 1fr; gap: 10px; align-items: start; }
.ftr-contact svg { width: 16px; height: 16px; margin-block-start: 3px; color: var(--gold-lt); }
.ftr-legal {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid color-mix(in srgb, var(--cream) 14%, transparent);
  color: color-mix(in srgb, var(--cream) 62%, transparent);
}

@media (min-width: 900px) {
  .ftr-in { grid-template-columns: 1.4fr repeat(4, 1fr); }
  .ftr-brand { grid-column: auto; }
}

/* -------------------------------------------------- phone bottom nav --- */
.mnav {
  position: fixed;
  z-index: 90;
  inset: auto 0 0 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  background: color-mix(in srgb, var(--deep) 96%, transparent);
  backdrop-filter: blur(10px);
  border-block-start: 1px solid color-mix(in srgb, var(--gold-lt) 20%, transparent);
  padding-block-end: env(safe-area-inset-bottom);
}
.mnav-i {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 4px;
  min-height: 56px;
  padding: 8px 2px;
  border: 0;
  background: none;
  color: color-mix(in srgb, var(--cream) 82%, transparent);
  font-size: 11px;
  font-weight: 600;
  line-height: 1.1;
  text-align: center;
}
.mnav-i svg { width: 21px; height: 21px; }
.mnav-i--wa { color: var(--gold-lt); }
/* The spacer keeps the last line of the footer clear of the bar. app.js sets
   its height from the bar's real offsetHeight, safe-area included. */
.mnav-sp { height: var(--mnav-h); }

@media (min-width: 720px) {
  .mnav, .mnav-sp { display: none; }
}

/* ------------------------------------------------------- scroll reveal ---
   One mechanism, deliberately: fade + rise, fired once, stagger index handed
   in as --i so a grid arrives as a cascade instead of one slab.

   The hidden state is scoped to `.js-reveal`, set by a one-line inline script
   first in <head>. Without that guard a JS error or a no-JS visitor gets a
   page that is permanently opacity:0. Do not move that script later in the
   document — the reveals would paint once and then blink out.

   The movement is the `translate` longhand, not `transform`. A revealed card's
   resting rule beats a `:hover` transform on specificity, so hover lifts
   written as `transform` are silently dead; `translate` composes instead. */
.js-reveal [data-reveal] {
  opacity: 0;
  translate: 0 18px;
  transition: opacity var(--t-enter) var(--ease-out), translate var(--t-enter) var(--ease-out);
  transition-delay: calc(var(--i, 0) * 70ms);
}
.js-reveal [data-reveal].is-in { opacity: 1; translate: 0 0; }

/* ------------------------------------------------------ reduced motion ---
   Fewer and gentler, NOT zero. A blanket `transition:none` here would strand
   every reveal target at opacity:0 and hide most of the page, so durations
   collapse instead of being removed and reveal targets are forced into their
   finished state. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  [data-reveal] {
    opacity: 1 !important;
    translate: none !important;
    transform: none !important;
    clip-path: none !important;
  }
  .btn:active { scale: none; }
  .btn .arw { translate: none !important; }
  .nav { translate: none !important; }
}

/* -------------------------------------------------- 404 & legal pages --- */
.nf-in, .legal-in { max-width: 72ch; }
.nf-in .lede, .legal-in p { margin-block-start: var(--space-5); }
.nf-links { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-block-start: var(--space-6); }

.legal-sec { margin-block-start: var(--space-7); }
.legal-sec h2 {
  font-family: var(--font-sub);
  font-size: var(--fs-h3);
  color: var(--deep);
}
.legal-sec p { color: var(--muted); }

/* =====================================================================
   ---- components ----
   The pieces every page is assembled from: section heads, tour cards, car
   cards, price lines, the stops timeline and the lead form.

   Two rules run through all of it and are load-bearing, not taste:

   1. A hover lift NEVER goes on the element that carries [data-reveal].
      `.js-reveal [data-reveal].is-in { translate: 0 0 }` is three selectors
      wide and beats `.tcard:hover`, so the lift would silently do nothing.
      Each card therefore has an inner box (.tcard-link, .tcard-in, .ccard-in) that owns
      the hover state, and the outer <li> owns the reveal. The same goes for
      opacity: .ccard--unavailable dims the inner box, not the <li>.
   2. Hover effects live inside @media (hover: hover) so a touch device never
      gets stuck in a hovered state after a tap.
   ===================================================================== */

/* ------------------------------------------------------------ helpers --- */
.arw { display: inline-flex; flex: 0 0 auto; transition: translate var(--t-hover) var(--ease-out); }
.arw svg { width: 18px; height: 18px; }

/* A card grid. One column on a phone, two from 640, three from 960 — explicit
   tracks rather than auto-fill, because .tcard--lg has to be able to span
   exactly two of them. */
.cards {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
}
@media (min-width: 640px) { .cards { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 960px) {
  .cards { grid-template-columns: repeat(3, 1fr); gap: var(--space-6); }
  .tcard--lg { grid-column: span 2; }
}

/* ---------------------------------------------------------- tour carousel
   Every tour on the home page in one horizontal track. The track is a
   horizontally scrollable strip by itself, so with no JavaScript it is still
   swipeable on touch and scrollable from the keyboard; js/tour-carousel.js adds
   the arrows,
   the dots and the auto-advance and sets `.is-ready` once it has. Anything
   that would be a lie without that script is scoped to `.is-ready`.

   `.cards.tcar-track` is 0,2,0 and beats the 0,1,0 `.cards` grid rules above
   from anywhere in the file, media queries included. */
.tcar { position: relative; }

.cards.tcar-track {
  display: flex;
  grid-template-columns: none;
  overflow-x: auto;
  /* proximity, never mandatory. Mandatory forces a resting point even when the
     reader did not ask for one, which is a real hazard when the page is zoomed
     and a card is wider than the viewport -- it can pull content out of reach.
     Proximity only tidies up a swipe that already ended near a card edge, which
     is all this needs: the arrows drive scrollLeft themselves (js/tour-carousel.js)
     and always finish exactly on a card, so there is nothing for snap to correct. */
  scroll-snap-type: x proximity;
  overscroll-behavior-x: contain;
  /* An overflow container clips: this is the room the focus ring and the
     card's hover lift need in order to be seen at all. */
  padding: 4px 4px 12px;
  margin-inline: -4px;
}
.cards.tcar-track > .tcard {
  flex: 0 0 calc(100% - var(--space-5));
  scroll-snap-align: start;
}
@media (min-width: 640px) {
  .cards.tcar-track > .tcard { flex-basis: calc(50% - var(--space-5)); }
}
@media (min-width: 960px) {
  .cards.tcar-track > .tcard { flex-basis: calc(33.333% - var(--space-6)); }
}

/* Until the arrows exist the scrollbar IS the affordance, so it is only
   hidden once the script has mounted. */
.tcar.is-ready .tcar-track { scrollbar-width: none; }
.tcar.is-ready .tcar-track::-webkit-scrollbar { display: none; }

/* Three 44 px buttons and a dot per stop fit one line on a wide screen only.
   Shrinking them to fit drew the arrows 9 px wide on a 390 px phone and still
   pushed a 320 px page to 352: nothing shrinks, and the dots wrap instead. */
.tcar-bar { display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-4); margin-top: var(--space-5); }
.tcar-btn {
  flex: none;
  display: inline-grid;
  place-items: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--paper);
  color: var(--deep);
  cursor: pointer;
}
.tcar-btn:hover { border-color: var(--line-2); }
.tcar-btn svg { width: 18px; height: 18px; }

.tcar-dots { display: flex; flex-wrap: wrap; gap: 2px; margin-inline-start: auto; }
/* 8px of dot inside a 24px target: WCAG 2.5.8 measures the target, not the ink. */
.tcar-dot {
  flex: none;
  display: grid;
  place-items: center;
  width: 24px;
  height: 24px;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.tcar-dot::before {
  content: '';
  width: 8px;
  height: 8px;
  border-radius: 999px;
  background: var(--line-2);
  transition: width var(--t-enter) var(--ease-out), background var(--t-enter) var(--ease-out);
}
.tcar-dot[aria-current='true']::before { width: 22px; background: var(--deep); }

/* The chip that sits on a photo: category on a tour, anything short elsewhere. */
.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--deep-ink) 82%, transparent);
  backdrop-filter: blur(6px);
  color: var(--cream);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  line-height: 1.2;
}

.badge {
  display: inline-flex;
  align-items: center;
  align-self: start;
  gap: 6px;
  padding: 6px 13px;
  border-radius: var(--r-pill);
  font-size: var(--fs-small);
  font-weight: 600;
  line-height: 1.3;
}
.badge--muted { background: var(--paper-3); border: 1px solid var(--line); color: var(--muted); }
/* A booking nobody has confirmed yet (the car and tour sheets' results, car.js and result.js): the gold of .placeholder-note, solid. */
.badge--gold { background: color-mix(in srgb, var(--gold-lt) 22%, var(--paper)); border: 1px solid var(--gold); color: var(--gold-ink); }

/* The stand-in for a photo we do not have yet: the brand horizon on deep water.
   Never an empty grey box — a missing photo should still look like the site.
   Doubled class on purpose: .tcard-media / .ccard-media set their own background
   further down the file and would otherwise win on source order. */
.tcard-media.tcard-media--none, .ccard-media.ccard-media--none {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  padding: var(--space-5);
  background: radial-gradient(120% 100% at 50% 0%, var(--deep-2), var(--deep));
  text-align: center;
}
.tcard-media--none .mark, .ccard-media--none .mark {
  width: 84px;
  height: 30px;
  --mark-sun: var(--gold-lt);
  --mark-sea: var(--aqua-lt);
}
.media-none-txt {
  color: color-mix(in srgb, var(--cream) 72%, transparent);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
}

/* -------------------------------------------------------- section head --- */
.sec-head {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
  max-width: 46rem;
  margin-block-end: var(--space-7);
}
/* The mark row already carries its own bottom margin for standalone use; inside
   the grid the gap does that job. */
.sec-head .sec-mark { margin-block-end: 0; }
/* Each title line is its own block, so the caller's array is the line break.
   Task 14 splits these into words for the reveal — the span must stay. */
.sec-head .display .line { display: block; }
.sec-head-go { margin-block-start: var(--space-2); }
.sec-head--center { justify-items: center; text-align: center; max-width: 52rem; margin-inline: auto; }
.sec-head--center .sec-mark { justify-content: center; }

/* ----------------------------------------------------------- tour card --- */
.tcard { display: flex; }
/* .tcard-in is the same box for a gallery card (/tours), whose photos sit outside the
   link: see "tour card photo carousel" below. */
.tcard-link, .tcard-in {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--line) 82%, transparent);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: translate var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) ease,
              border-color var(--t-hover) ease;
}
/* The gold hairline. `transform` (not `translate`) is safe on a pseudo-element:
   nothing else writes to it there. */
.tcard-link::after, .tcard-in::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 3px;
  background: linear-gradient(90deg, var(--gold-lt), var(--gold));
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--t-hover) var(--ease-out);
}
/* Keyboard users get the hairline too, and outside the hover query so it still
   fires on a touch device with a keyboard attached. */
.tcard:focus-within .tcard-link::after, .tcard:focus-within .tcard-in::after { transform: scaleX(1); }

.tcard-media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  background: var(--paper-3);
}
.tcard-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: scale var(--t-hover) var(--ease-out);
}
.tcard-media .chip {
  position: absolute;
  inset-block-start: 12px;
  inset-inline-start: 12px;
}
.tcard-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 10px;
  padding: var(--space-5);
}
.tcard-title {
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.15;
  color: var(--deep);
}
.tcard-sub {
  display: block;
  color: var(--muted);
  font-size: var(--fs-small);
  line-height: 1.5;
}
.tcard-facts { display: flex; flex-wrap: wrap; gap: 4px 16px; }
.fact {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--muted);
  font-size: var(--fs-small);
}
.fact svg { width: 16px; height: 16px; flex: 0 0 auto; color: var(--sea-ink); }
/* Pushed to the foot of the card so a row of cards keeps its call to action on
   one line whatever the subtitles do. */
.tcard-go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-block-start: auto;
  padding-block-start: var(--space-3);
  color: var(--gold-ink);
  font-size: var(--fs-small);
  font-weight: 600;
}

/* The lg card is wider, so its photo becomes a landscape crop and its title
   steps up to match. */
@media (min-width: 960px) {
  .tcard--lg .tcard-media { aspect-ratio: 3 / 2; }
  .tcard--lg .tcard-title { font-size: clamp(1.5rem, 1.1rem + 1vw, 2rem); }
  .tcard--lg .tcard-body { padding: var(--space-6); }
}

/* ------------------------------------------------------------ car card --- */
.ccard { display: flex; }
.ccard-in {
  position: relative;
  display: flex;
  flex-direction: column;
  width: 100%;
  background: var(--paper);
  border: 1px solid color-mix(in srgb, var(--line) 82%, transparent);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-card);
  overflow: hidden;
  transition: translate var(--t-hover) var(--ease-out),
              box-shadow var(--t-hover) ease,
              border-color var(--t-hover) ease;
}
/* Vehicles are shot on a light backdrop, so the frame is --paper-3 rather than
   the deep used for tours: it keeps the car, not the box. */
.ccard-media {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--paper-3);
}
.ccard-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transition: scale var(--t-hover) var(--ease-out), filter var(--t-hover) ease;
}
.ccard-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 10px;
  padding: var(--space-5);
}
.ccard-name {
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.15;
  color: var(--deep);
}
.ccard-cat { margin-block-start: -6px; color: var(--muted); font-size: var(--fs-small); }
.specs { display: flex; flex-wrap: wrap; gap: 8px; }
.spec {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 5px 10px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-2);
  color: var(--muted);
  font-size: 12px;
  font-weight: 600;
  line-height: 1.3;
  white-space: nowrap;
}
.spec svg { width: 15px; height: 15px; flex: 0 0 auto; color: var(--sea-ink); }
.ccard-price { display: flex; }
.ccard-act {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-block-start: auto;
  padding-block-start: var(--space-4);
}
.ccard-act .btn { flex: 1 1 auto; min-width: 128px; }

/* Taken for the chosen dates. Dimmed rather than removed: the visitor asked for
   this car, and hiding it only makes them look for it. */
.ccard--unavailable .ccard-in { opacity: .6; }
.ccard--unavailable .ccard-img { filter: grayscale(.4); }
.ccard--unavailable .ccard-book {
  background: var(--paper-3);
  border-color: var(--line);
  color: var(--muted);
  cursor: not-allowed;
}

/* -------------------------------------------------------------- price --- */
.price {
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: 1.125rem;
  line-height: 1.25;
  letter-spacing: .01em;
  color: var(--deep);
}
.price-amt { font-size: 1.375rem; }
.price-note {
  display: block;
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-small);
  color: var(--muted);
}
/* "On request" is not a price, so it does not look like one: a dashed gold
   outline says "we will tell you", where a solid pill would read as a figure. */
.price--req {
  display: inline-flex;
  align-self: start;
  align-items: center;
  padding: 5px 14px;
  border: 1px dashed var(--gold);
  border-radius: var(--r-pill);
  color: var(--gold-ink);
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .1em;
  text-transform: uppercase;
}

/* -------------------------------------------------------------- stops --- */
.stops {
  position: relative;
  display: grid;
  gap: var(--space-6);
  padding-inline-start: 52px;
}
/* The line the day runs down. It stops at the middle of the first and last
   numbers rather than running past them, so it reads as a route, not a border. */
.stops::before {
  content: "";
  position: absolute;
  inset-block: 16px;
  inset-inline-start: 15px;
  width: 2px;
  border-radius: 2px;
  background: linear-gradient(var(--gold), color-mix(in srgb, var(--gold) 22%, transparent));
  transform-origin: top;
}
/* One stop: nothing to connect. */
.stops--single::before { display: none; }
.stop { position: relative; }
/* Anton, in --gold-ink rather than --gold: at 16px the lighter gold drops under
   AA on paper. The disc is opaque, so the line passes behind it, not through. */
.stop-n {
  position: absolute;
  inset-inline-start: -52px;
  inset-block-start: -3px;
  display: grid;
  place-items: center;
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--gold-lt) 30%, var(--paper));
  color: var(--gold-ink);
  font-family: var(--font-num);
  font-size: 1rem;
  line-height: 1;
  letter-spacing: .02em;
}
.stop-t {
  font-family: var(--font-sub);
  font-weight: 600;
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--deep);
}
.stop-note { margin-block-start: 6px; max-width: 60ch; color: var(--muted); }
.stops-groups { display: grid; gap: var(--space-7); }
/* Indented to the same 52px as the stop titles, so the region reads as a label
   for the names below it and not for the numbers beside them. */
.stops-region { margin-block-end: var(--space-5); padding-inline-start: 52px; }
.section--deep .stop-t { color: var(--cream); }
.section--deep .stop-note { color: color-mix(in srgb, var(--cream) 78%, transparent); }
.section--deep .stop-n { background: color-mix(in srgb, var(--gold-lt) 22%, var(--deep)); color: var(--gold-lt); }

/* The line draws itself as the list scrolls through the viewport: scroll-driven,
   so it is tied to the reader's own movement and cannot run forever. Where
   animation-timeline is unsupported — and whenever motion is reduced — the
   declaration is never applied at all and the line is simply drawn full. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    @keyframes stops-draw { from { scale: 1 0; } to { scale: 1 1; } }
    .stops::before {
      scale: 1 0;
      animation: stops-draw linear both;
      animation-timeline: view();
      animation-range: entry 30% cover 55%;
    }
  }
}

/* ----------------------------------------------------------- lead form --- */
.lead { position: relative; display: grid; gap: var(--space-5); }
.lead-grid { display: grid; gap: var(--space-4); }
@media (min-width: 640px) {
  .lead-grid { grid-template-columns: 1fr 1fr; gap: var(--space-4) var(--space-5); }
  .fld--wide { grid-column: 1 / -1; }
}
.fld { display: grid; gap: 6px; align-content: start; }
.fld-lb { font-size: var(--fs-small); font-weight: 600; color: var(--deep); }
.req { margin-inline-start: 3px; color: var(--gold-ink); }
.fld-in {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  /* 16px exactly: iOS Safari zooms the whole page when a focused field is
     smaller than that, and never zooms back out. */
  font: 400 16px/1.4 var(--font-body);
  color: var(--text);
  background: var(--paper);
  border: 1px solid var(--line-ctrl);
  border-radius: var(--r-sm);
  transition: border-color var(--t-hover) ease, box-shadow var(--t-hover) ease;
}
textarea.fld-in { min-height: 122px; resize: vertical; }
.fld-in:focus { border-color: var(--sea-ink); box-shadow: 0 0 0 3px color-mix(in srgb, var(--sea) 16%, transparent); }
.fld-in[aria-invalid="true"] { border-color: #B3261E; }
.field-err { color: #B3261E; font-size: 12px; font-weight: 600; line-height: 1.4; }
.field-err[hidden], .msg[hidden] { display: none; }
.lead-req { color: var(--muted); font-size: 12px; }
.lead-act { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.lead-send { padding-inline: 28px; }
/* Not rendered at all: browsers never autofill a display:none field, whereas a
   1px clipped box is still a focusable input that address autofill can fill —
   which would turn a real enquiry into a silent honeypot drop. */
.lead-hp { display: none; }
.msg {
  padding: 14px 16px;
  border: 1px solid color-mix(in srgb, var(--sea) 34%, transparent);
  border-radius: var(--r-sm);
  background: color-mix(in srgb, var(--sea) 10%, var(--paper));
  font-size: var(--fs-small);
  line-height: 1.55;
}
.msg strong { color: var(--deep); }
.msg--err { border-color: #F0B4AE; background: #FCEDEB; color: #7A1C15; }
.msg--err strong { color: inherit; }
/* js/flows/lead.js hides the fields and the button on success. These blocks set
   their own `display`, which beats the UA's [hidden] rule, so say it again. */
.lead-grid[hidden], .lead-req[hidden], .lead-act[hidden] { display: none; }
.lead-send:disabled { cursor: progress; opacity: .72; }
/* The panels take focus only so it does not fall to <body> when the button they
   replace disappears; they are not controls, so no ring. */
.msg:focus { outline: none; }
.msg > p + p { margin-block-start: var(--space-2); }
/* The failure panel's way out: a real tel: and WhatsApp link, 44 px tall. */
.msg-acts { display: flex; flex-wrap: wrap; gap: 0 var(--space-5); }
.msg-lnk {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  font-weight: 600;
  text-decoration: underline;
  text-underline-offset: 3px;
}
.msg-lnk svg { width: 18px; height: 18px; flex: 0 0 auto; }
.section--deep .fld-lb { color: var(--cream); }
.section--deep .lead-req { color: color-mix(in srgb, var(--cream) 72%, transparent); }

/* ---------------------------------------------- tour card photo carousel ---
   /tours only (js/card-carousel.js). The card's box moves from .tcard-link to .tcard-in
   around the photos and the link, because the photos and the arrow buttons sit outside
   the link. Not to the <li>: it carries [data-reveal] (rule 1 at the top of this
   section). Until the script marks the card .tcard--live only the cover shows. */
.tcard--gallery .tcard-link,
.tcard--gallery .tcard-link:hover { flex: 1; border: 0; border-radius: 0; box-shadow: none; background: none; translate: none; }
.tcard--gallery .tcard-link::after { display: none; }
.tcard-track {
  position: absolute;
  inset: 0;
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
}
.tcard-track::-webkit-scrollbar { display: none; }
/* overflow: hidden keeps a photo's hover zoom inside its own slide. */
.tcard-track > li { flex: 0 0 100%; height: 100%; overflow: hidden; scroll-snap-align: start; scroll-snap-stop: always; }
.tcard-slide { display: block; height: 100%; }
.tcard--gallery .chip { z-index: 2; pointer-events: none; }
.tcard--gallery:not(.tcard--live) .tcard-track > li + li,
.tcard--gallery:not(.tcard--live) .tcard-arr,
.tcard--gallery:not(.tcard--live) .tcard-dots { display: none; }
.tcard-arr {
  position: absolute;
  inset-block-start: 50%;
  z-index: 2;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin-block-start: -20px;
  padding: 0;
  color: var(--ink);
  background: color-mix(in srgb, var(--paper) 92%, transparent);
  border: 0;
  border-radius: 50%;
  box-shadow: var(--shadow-card);
  cursor: pointer;
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--t-hover) ease;
}
.tcard-arr[hidden] { display: none; }
.tcard-arr svg { width: 18px; height: 18px; }
.tcard-arr--prev { inset-inline-start: 10px; }
.tcard-arr--next { inset-inline-end: 10px; }
.tcard-arr--prev svg { scale: -1 1; }
.tcard--gallery:focus-within .tcard-arr { opacity: 1; pointer-events: auto; }
.tcard-dots {
  position: absolute;
  inset-block-end: 10px;
  inset-inline: 0;
  z-index: 2;
  display: flex;
  justify-content: center;
  gap: 6px;
  pointer-events: none;
}
.tcard-dots i { width: 6px; height: 6px; border-radius: 50%; background: rgb(255 255 255 / 0.55); box-shadow: 0 0 0 1px rgb(0 0 0 / 0.18); }
.tcard-dots i.on { background: #fff; }
@media (hover: hover) and (pointer: fine) {
  .tcard-in:hover .tcard-arr { opacity: 1; pointer-events: auto; }
}
@media (prefers-reduced-motion: reduce) {
  .tcard-arr { transition: none; }
}

/* --------------------------------------------------- component hovers ---
   Everything below is hover-gated, and every lift is the `translate`
   longhand — see the note at the top of this section. */
@media (hover: hover) and (pointer: fine) {
  .tcard-link:hover, .tcard-in:hover { translate: 0 -4px; border-color: var(--line-2); box-shadow: var(--shadow-lg); }
  .tcard-link:hover::after, .tcard-in:hover::after { transform: scaleX(1); }
  .tcard-link:hover .tcard-img, .tcard-in:hover .tcard-img { scale: 1.04; }
  .tcard-link:hover .arw, .tcard-in:hover .arw { translate: 3px 0; }
  .ccard-in:hover { translate: 0 -4px; border-color: var(--line-2); box-shadow: var(--shadow-lg); }
  .ccard-in:hover .ccard-img { scale: 1.03; }
  /* A car that cannot be booked does not invite a click. */
  .ccard--unavailable .ccard-in:hover { translate: 0 0; box-shadow: none; border-color: var(--line); }
  .ccard--unavailable .ccard-in:hover .ccard-img { scale: 1; }
}

@media (prefers-reduced-motion: reduce) {
  .tcard-img, .ccard-img { scale: none !important; }
  .tcard-link, .tcard-in, .ccard-in { translate: none !important; }
  .arw { translate: none !important; }
  .stops::before { scale: none !important; }
}

/* =====================================================================
   ---- home ----
   Strapline, the split hero, the finder, the fleet tabs, the two service
   bands and the contact band. Three things here are load-bearing rather
   than taste, and are commented where they are:

   1. The header only floats over a hero because THIS file pulls the page
      up under it (.hdr[data-hdr="over"] below). Nothing in layout.js does.
   2. Tab panels are all visible until JS says otherwise, so the finder
      still works with scripting off.
   3. The hero's word mask is scoped to `.js-reveal`, like every other
      hidden-until-revealed state in this file — a JS failure must leave
      words readable, never clipped to nothing.
   ===================================================================== */

/* The page slides up under the transparent header. The header is sticky and so
   still occupies flow; a negative bottom margin is what lets the strap and the
   hero start at y=0 while the bar paints on top of them (z-index 100). */
.hdr[data-hdr="over"] { margin-block-end: calc(var(--hdr-h) * -1); }

/* ---------------------------------------------------------- strapline --- */
.strap {
  margin: 0;
  padding-block: calc(var(--hdr-h) + 14px) 14px;
  padding-inline: var(--gutter);
  background: var(--deep-ink);
  color: var(--gold-lt);
  /* 11px floor: under it the .34em tracking stops reading as words at 390px. */
  font-size: clamp(11px, 1.4vw, 12px);
  font-weight: 600;
  letter-spacing: .34em;
  text-transform: uppercase;
  text-align: center;
  line-height: 1.5;
}

/* --------------------------------------------------------------- hero --- */
.hero--split { display: grid; background: var(--deep-ink); }
.hero-panel {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 52svh;
  overflow: hidden;
  color: #fff;
  isolation: isolate;
}
.hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: -2;
  /* No opacity transition and no lazy loading: this is the LCP element, and an
     LCP image that fades in is reported at the end of the fade. */
  transition: scale 500ms var(--ease-out), filter 500ms ease;
}
.hero-shade {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(200deg, rgba(2, 43, 54, .10) 0%, rgba(2, 43, 54, .50) 52%, rgba(2, 43, 54, .86) 100%);
}
.hero-body {
  display: grid;
  justify-items: start;
  gap: var(--space-4);
  width: 100%;
  padding: var(--space-7) var(--gutter) var(--space-8);
}
/* The element selector is not decoration: `.display` sets --deep and
   `h1.display` is one step more specific than a bare `.hero-word`, so a plain
   class here loses and the DRIVE headline renders deep-teal on a photo. */
.hero-word { margin: 0; }
h1.hero-word, p.hero-word { color: #fff; font-size: clamp(2.5rem, 1rem + 9vw, 5.5rem); }
.hero-sub {
  max-width: 34ch;
  color: color-mix(in srgb, #fff 88%, transparent);
  font-size: clamp(1rem, .95rem + .3vw, 1.125rem);
  line-height: 1.5;
}
/* The panel is the link; this only looks like a button, so it must not eat the
   pointer or it would swallow the click it is advertising. */
.hero-go { pointer-events: none; }

/* The word mask. One transition per word, delayed by its index, fired by the
   .hero--in class app.js adds on load. */
.js-reveal .hero .w {
  display: inline-block;
  clip-path: inset(0 0 105% 0);
  translate: 0 .35em;
}
.js-reveal .hero--in .w {
  clip-path: inset(0 0 -20% 0);
  translate: 0 0;
  transition: clip-path 700ms var(--ease-out), translate 700ms var(--ease-out);
  transition-delay: calc(var(--wi, 0) * 90ms);
}

@media (min-width: 760px) {
  .hero-panel { min-height: 76svh; }
}

/* Desktop only: the hovered half grows and its photo eases in, the other half's
   photo steps back. Written as "dim both, then un-dim the hovered one" because
   CSS has no previous-sibling selector and :has() is not used in this project.
   The two rules have equal specificity — the un-dim MUST stay second. */
@media (hover: hover) and (min-width: 960px) {
  .hero--split { display: flex; }
  .hero-panel { flex: 1 1 0; transition: flex-grow 500ms var(--ease-out); }
  .hero-panel:hover, .hero-panel:focus-visible { flex-grow: 1.18; }
  .hero--split:hover .hero-img { filter: brightness(.9); }
  .hero-panel:hover .hero-img { filter: none; scale: 1.04; }
  .hero-panel + .hero-panel { border-inline-start: 1px solid color-mix(in srgb, var(--gold-lt) 30%, transparent); }
}

/* ---------------------------------------------------------- tab lists --- */
/* Without JS every panel is on screen and every form in it submits — three
   stacked forms beats two unreachable ones. The inline .js-reveal guard in
   <head> means scripts are running, so the extra panels go immediately; once
   app.js has wired the lists it sets data-tabs="on" on <html> and [hidden]
   takes over. All three selectors weigh the same — do not reorder them. */
.js-reveal .tab-alt { display: none; }
[data-tabs="on"] .tab-alt { display: block; }
[role="tabpanel"][hidden] { display: none; }

.tabs {
  position: relative;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  padding-block-end: 10px;
  margin-block-end: var(--space-6);
  border-block-end: 1px solid var(--line);
}
/* The sliding indicator. app.js writes --tab-x / --tab-w; the CSS owns the
   movement, so the list keeps working if the properties are never written. */
.tabs::after {
  content: "";
  position: absolute;
  inset-block-end: -1px;
  inset-inline-start: 0;
  width: var(--tab-w, 0);
  height: 3px;
  border-radius: 2px;
  background: linear-gradient(90deg, var(--gold-lt), var(--gold));
  translate: var(--tab-x, 0) 0;
  transition: translate var(--t-move) var(--ease-out), width var(--t-move) var(--ease-out);
}
.tab {
  min-height: 44px;
  padding: 10px 16px;
  border: 0;
  border-radius: var(--r-sm) var(--r-sm) 0 0;
  background: none;
  font-family: var(--font-sub);
  font-size: 1.0625rem;
  font-weight: 600;
  letter-spacing: .01em;
  color: var(--muted);
  transition: color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.tab[aria-selected="true"] { color: var(--deep); }
@media (hover: hover) and (pointer: fine) {
  .tab:hover { color: var(--deep); background: color-mix(in srgb, var(--gold-lt) 16%, transparent); }
}
.tab-short { display: none; }
@media (max-width: 759px) {
  .tab-long { display: none; }
  .tab-short { display: inline; }
  .tab { padding-inline: 12px; }
}

/* ------------------------------------------------------------- finder --- */
.finder {
  scroll-margin-block-start: calc(var(--hdr-h) + 12px);
  padding-block: clamp(32px, 5vw, 56px);
  /* Gold, but the light end of it: --gold is only 3.45:1 against the deep text
     these labels use, --gold-lt is 7.2:1. */
  background: linear-gradient(135deg, var(--gold-lt), color-mix(in srgb, var(--gold-lt) 58%, var(--cream)));
}
.finder-in { display: grid; gap: var(--space-5); }
.finder-head { display: grid; gap: 6px; }
.finder .eyebrow { color: var(--deep); }
.finder-intro { max-width: 62ch; color: color-mix(in srgb, var(--deep) 88%, transparent); font-size: var(--fs-small); }
.finder .tabs { border-block-end-color: color-mix(in srgb, var(--deep) 20%, transparent); margin-block-end: 0; }
.finder .tab { color: color-mix(in srgb, var(--deep) 74%, transparent); }
.finder .tab[aria-selected="true"] { color: var(--deep); }
.finder .tabs::after { background: var(--deep); }
@media (hover: hover) and (pointer: fine) {
  .finder .tab:hover { color: var(--deep); background: color-mix(in srgb, #fff 42%, transparent); }
}
.finder-panel { padding-block-start: var(--space-5); }
.finder-panel:focus-visible { outline-offset: 6px; }
.finder-form { display: grid; gap: var(--space-4); }
.finder .fld-lb { color: var(--deep); }
.finder-note { max-width: 52ch; color: var(--deep); font-size: var(--fs-small); font-weight: 600; }
/* The native select keeps its own arrow and its own keyboard behaviour; only
   the box matches the text inputs. */
.fld-sel { cursor: pointer; }
.fld--go { align-content: end; }
.fld--go .btn { width: 100%; }
/* Two up on a tablet, four up only once four fields fit without the pick-up
   select truncating its longest option ("Hotel delivery" / "Aeroport SSR"). */
@media (min-width: 640px) {
  .finder-form { grid-template-columns: repeat(2, 1fr); align-items: end; }
  .finder-form--calm { grid-template-columns: 1fr auto; align-items: center; }
}
@media (min-width: 1024px) {
  .finder-form { grid-template-columns: repeat(4, 1fr); }
  .finder-form .fld--wide { grid-column: span 2; }
  .fld--go .btn { width: auto; }
}

/* ------------------------------------------------------ featured tours --- */
/* Three cards where the first spans two of three columns is four column-units,
   so the third card wraps to a row of its own and the row reads lopsided. Give
   the big card the second row as well and it becomes the mockup's arrangement:
   one tall feature beside a stack of two. */
/* Scoped to the HOME page, not to an id. `#tours` alone would also match any
   other page that names a section "tours", and hand its first card a two-row
   span plus aspect-ratio:auto for no reason. (Task 15 carry-forward.) */
@media (min-width: 960px) {
  body[data-page="home"] #tours .tcard--lg { grid-row: span 2; }
  /* Two rows of height have to go somewhere. Give them to the photo, not to a
     blank gap between the price and the "explore" line. */
  body[data-page="home"] #tours .tcard--lg .tcard-media { flex: 1 1 auto; aspect-ratio: auto; min-height: 320px; }
  body[data-page="home"] #tours .tcard--lg .tcard-body { flex: 0 0 auto; }
}

/* -------------------------------------------------------------- fleet --- */
.fleet-panel:focus-visible { outline-offset: 6px; }
.fleet-all {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--line);
}
.fleet-all h3 {
  font-family: var(--font-body);
  font-size: 12px;
  letter-spacing: .24em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.fleet-all ul { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); margin-block-start: var(--space-3); }
.fleet-all a {
  display: inline-block;
  padding-block: 6px;
  font-family: var(--font-sub);
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--deep);
  border-block-end: 1px solid transparent;
  transition: border-color var(--t-hover) ease;
}
@media (hover: hover) and (pointer: fine) { .fleet-all a:hover { border-block-end-color: var(--gold); } }

/* Only the panel on screen is named, so the pair the browser animates is
   old-visible to new-visible and the rest of the page is left out of it. */
@media (prefers-reduced-motion: no-preference) {
  .fleet-panel:not([hidden]) { view-transition-name: fleet-swap; }
  ::view-transition-old(fleet-swap) { animation: fleet-out 160ms var(--ease-out) both; }
  ::view-transition-new(fleet-swap) { animation: fleet-in 260ms var(--ease-out) both; }
  /* The root snapshot would otherwise cross-fade the whole document, and the
     page gets taller or shorter on a swap, so that cross-fade reads as a jump. */
  ::view-transition-old(root), ::view-transition-new(root) { animation: none; mix-blend-mode: normal; }
}
@keyframes fleet-out { to { opacity: 0; translate: 0 -12px; } }
@keyframes fleet-in { from { opacity: 0; translate: 0 12px; } }

/* -------------------------------------------------------------- bands --- */
.band-in { display: grid; gap: var(--space-7); align-items: center; }
.band-side { display: grid; justify-items: start; }
.band-side .sec-head { margin-block-end: var(--space-2); }
.band-media { margin: 0; position: relative; }
.band-media img {
  width: 100%;
  border-radius: var(--r-lg);
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.band-cap {
  display: grid;
  justify-items: start;
  gap: 10px;
  position: relative;
  max-width: 22rem;
  margin-block-start: calc(var(--space-6) * -1);
  margin-inline-start: var(--space-5);
  padding: var(--space-5);
  border-radius: var(--r);
  background: var(--paper);
  color: var(--deep);
  font-family: var(--font-sub);
  font-size: var(--fs-h3);
  line-height: 1.25;
  box-shadow: var(--shadow-lg);
}
@media (min-width: 960px) {
  .band-in { grid-template-columns: 1.02fr .98fr; gap: var(--space-8); }
  /* The business band mirrors the private one, so the two do not read as the
     same slab twice. Source order is unchanged, so the tab order is too. */
  .band--flip .band-media { order: -1; }
}

.feats { display: grid; gap: var(--space-5); margin-block: var(--space-6); }
.feat { display: grid; grid-template-columns: 46px 1fr; gap: var(--space-4); align-items: start; }
.feat-ic {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--gold-lt) 24%, var(--paper));
  color: var(--gold-ink);
}
.feat-ic svg { width: 22px; height: 22px; }
.section--deep .feat-ic { background: color-mix(in srgb, var(--gold-lt) 16%, transparent); color: var(--gold-lt); }
.feat-tx { display: grid; gap: 4px; }
.feat h3 { font-family: var(--font-sub); font-size: var(--fs-h3); color: var(--deep); }
.feat p { color: var(--muted); font-size: var(--fs-small); line-height: 1.6; }
.section--deep .feat h3 { color: var(--cream); }
.section--deep .feat p { color: color-mix(in srgb, var(--cream) 80%, transparent); }

/* ------------------------------------------------------- contact band --- */
.band--gold-split { background: var(--paper-2); }
/* "Split" is a left-hand panel, not a half-page gradient: a gradient would have
   to guess where the two columns meet on every screen, and be wrong on most. */
.band--gold-split .band-side--gold {
  align-self: stretch;
  align-content: center;
  padding: clamp(24px, 4vw, 48px);
  border-radius: var(--r-lg);
  background: linear-gradient(160deg, var(--gold-lt), color-mix(in srgb, var(--gold-lt) 55%, var(--cream)));
}
.band--gold-split .sec-head { margin-block-end: var(--space-5); }
.contact-wa {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  min-height: 44px;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--deep);
  border-block-end: 1px solid color-mix(in srgb, var(--deep) 30%, transparent);
}
.contact-wa svg { width: 20px; height: 20px; }
@media (hover: hover) and (pointer: fine) { .contact-wa:hover { border-block-end-color: var(--deep); } }
.band-form {
  padding: clamp(20px, 3vw, 32px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow);
}

/* -------------------------------------------------------- calm states --- */
.state-calm {
  display: grid;
  justify-items: start;
  gap: var(--space-3);
  max-width: 54rem;
  padding: clamp(20px, 3vw, 32px);
  border: 1px dashed var(--line-2);
  border-radius: var(--r);
  background: var(--paper-2);
}
.state-calm h3 { font-family: var(--font-sub); font-size: var(--fs-h3); color: var(--deep); }
.state-calm p { color: var(--muted); }
.state-acts { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-block-start: var(--space-2); }
.state-acts svg { width: 18px; height: 18px; }

/* --------------------------------------------- section title word wipe --- */
/* Same observer as [data-reveal], a different look: the block itself fades and
   rises, and its words wipe up behind a mask a beat apart. Scoped to
   .js-reveal so the words are plain text without scripting. */
.js-reveal [data-words] .w {
  display: inline-block;
  clip-path: inset(0 0 105% 0);
  translate: 0 .3em;
}
.js-reveal [data-reveal].is-in [data-words] .w,
.js-reveal [data-words].is-in .w {
  clip-path: inset(0 0 -20% 0);
  translate: 0 0;
  transition: clip-path 620ms var(--ease-out), translate 620ms var(--ease-out);
  transition-delay: calc(var(--wi, 0) * 70ms);
}

/* ------------------------------------------------ home, reduced motion --- */
/* The global block forces [data-reveal] visible, but a `.w` is not a reveal
   target — without these lines every display headline on the page would stay
   clipped to nothing for anyone who asked for less motion. */
@media (prefers-reduced-motion: reduce) {
  .hero .w, [data-words] .w { clip-path: none !important; translate: none !important; }
  .hero-img { scale: none !important; filter: none !important; }
  .hero-panel { transition: none; }
  .tabs::after { transition: none; }
}

/* =====================================================================
   ---- tours ----
   /tours (the filtered list) and /tours/<slug> (one tour).

   Three rules here are load-bearing rather than taste:

   1. `h1.hero-tour-t`, not `.hero-tour-t`. `.display` paints --deep and
      `h1.display` is one specificity step above a bare class, so a
      single-class rule loses and the title renders deep teal on a dark
      photo. Task 14 hit exactly this on the home hero.
   2. The book card is NOT sticky (the photo grid sits under it). Once it has
      scrolled away, from 720 px, .book-float floats Book this tour in
      (js/tour-gallery.js); under 720 px the phone bar is always there.
   3. On a phone this page's own .book-bar REPLACES the layout's bottom nav
      (`body[data-page="tour"] .mnav`), because two fixed bars stacked at the
      bottom of a phone is most of the screen. The nav's spacer stays and is
      given the new bar's height, so the footer's last line still clears it.
   ===================================================================== */

/* ------------------------------------------------------ filter chips --- */
/* Links, not buttons: ?cat= is a real URL that renders server-side, so the
   filter works without JS, survives a reload and can be shared. The current
   one is aria-current="page" for the same reason. */
.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  margin-block: var(--space-6);
}
.chip-lnk {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  padding: 8px 20px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  background: var(--paper);
  color: var(--deep);
  font-family: var(--font-sub);
  font-size: 1.0625rem;
  line-height: 1.2;
  transition: background-color var(--t-hover) ease, border-color var(--t-hover) ease, color var(--t-hover) ease;
}
.chip-lnk[aria-current="page"] {
  background: var(--deep);
  border-color: var(--deep);
  color: var(--cream);
}
@media (hover: hover) and (pointer: fine) {
  .chip-lnk:hover { border-color: var(--gold); }
  .chip-lnk[aria-current="page"]:hover { border-color: var(--deep); background: var(--deep-2); }
}
.tours-empty { margin-block-start: var(--space-3); }

/* ----------------------------------------------------------- tour hero --- */
.hero--tour {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: 60svh;
  overflow: hidden;
  background: var(--deep-ink);
  color: var(--cream);
  isolation: isolate;
}
/* The LCP element. Never lazy, never faded in - an LCP image that animates its
   opacity is reported at the end of the fade. */
.hero-tour-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: -2;
}
/* No photo yet: brand water and the horizon mark, never an empty grey box. */
.hero-tour-none {
  position: absolute;
  inset: 0;
  z-index: -2;
  display: grid;
  place-content: center;
  background: radial-gradient(120% 100% at 50% 0%, var(--deep-2), var(--deep));
}
/* A watermark, not a badge. At badge size the horizon lands exactly where the
   title sits and the two collide; big and faint it reads as brand texture and
   the headline stays legible over it. */
.hero-tour-none .mark {
  width: min(76vw, 460px);
  height: auto;
  aspect-ratio: 54 / 19;
  opacity: .22;
  --mark-sun: var(--gold-lt);
  --mark-sea: var(--aqua-lt);
}
.hero-shade--tour {
  background: linear-gradient(to top, rgba(2, 43, 54, .94) 0%, rgba(2, 43, 54, .64) 44%, rgba(2, 43, 54, .26) 100%);
}
.hero--tour-flat .hero-shade--tour {
  background: linear-gradient(to top, rgba(2, 43, 54, .72) 0%, rgba(2, 43, 54, .12) 60%, transparent 100%);
}
.hero-tour-in {
  display: grid;
  justify-items: start;
  gap: var(--space-3);
  padding-block: calc(var(--hdr-h) + var(--space-7)) var(--space-8);
}
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-small);
  color: color-mix(in srgb, #fff 84%, transparent);
}
.crumbs a { border-block-end: 1px solid transparent; }
.crumbs [aria-current="page"] { color: var(--gold-lt); }
@media (hover: hover) and (pointer: fine) {
  .crumbs a:hover { border-block-end-color: currentColor; }
}
.hero-tour-cat { color: var(--gold-lt); }
/* See note 1 at the top of this section - the element selector is required. */
h1.hero-tour-t {
  color: var(--cream);
  font-size: clamp(2.75rem, 1.2rem + 5.4vw, 4.75rem);
}
.hero-tour-sub {
  max-width: 40ch;
  font-family: var(--font-sub);
  font-size: clamp(1.125rem, 1rem + .9vw, 1.6rem);
  font-weight: 600;
  line-height: 1.25;
  color: color-mix(in srgb, var(--cream) 94%, transparent);
}
.hero-tour-lede {
  max-width: 62ch;
  color: color-mix(in srgb, var(--cream) 82%, transparent);
}

/* -------------------------------------------------- tour page layout --- */
.tour-grid {
  display: grid;
  gap: var(--space-6);
  padding-block: clamp(32px, 5vw, 64px);
}
.tour-main { min-width: 0; }
.tour-sec { margin-block-start: clamp(40px, 6vw, 72px); }
.tour-sec .sec-head { margin-block-end: var(--space-6); }
.tour-down .nf-in { display: grid; gap: var(--space-5); justify-items: start; }

@media (min-width: 960px) {
  /* The aside (the request card, then the photo grid) sits in the SAME row as
     the article, beside it. The card is not sticky: once it scrolls away,
     .book-float (js/tour-gallery.js) offers Book this tour instead. */
  .tour-grid { grid-template-columns: minmax(0, 1fr) 340px; gap: var(--space-8); }
  .tour-main { grid-column: 1; grid-row: 1; }
  .book-aside { grid-column: 2; grid-row: 1; }
}

/* ------------------------------------------------------------ book card --- */
.book-card {
  display: grid;
  gap: var(--space-3);
  padding: clamp(20px, 3vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-lg);
}
.book-for {
  display: grid;
  gap: 2px;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.book-for strong {
  font-family: var(--font-sub);
  font-size: 1.25rem;
  line-height: 1.2;
  letter-spacing: normal;
  text-transform: none;
  color: var(--deep);
}
.book-card .price { justify-self: start; }

/* ------------------------------------------------------- photo grid --- */
/* The other photos of a tour, under the request card. Two columns. Below 960 px
   at most three tiles (first is big unless there are two); from 960 px up to six. */
.tg {
  --tg-row: clamp(110px, 22vw, 190px);
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  grid-auto-rows: var(--tg-row);
  gap: 8px;
}
.tg-i { position: relative; min-width: 0; overflow: hidden; border-radius: var(--r-sm); background: var(--line-2); }
.tg-i:first-child { grid-column: span 2; grid-row: span 2; }
.tg[data-count="2"] .tg-i:first-child { grid-column: auto; grid-row: auto; }
.tg-a, .tg-a img { display: block; width: 100%; height: 100%; }
.tg-a img { object-fit: cover; }
.tg-a:focus-visible { outline: 2px solid var(--gold); outline-offset: -3px; }
.tg-more {
  position: absolute;
  inset: auto 8px 8px auto;
  padding: 4px 10px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--deep-ink) 78%, transparent);
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  pointer-events: none;
}
.tg-more--wide { display: none; }
@media (max-width: 959px) {
  .tg-i:nth-child(n+4) { display: none; }
}
@media (min-width: 960px) {
  .tg { --tg-row: 110px; }
  .tg[data-count="1"] .tg-i:first-child { grid-row: auto; }
  .tg[data-count="4"] .tg-i:nth-child(4),
  .tg[data-count="6"] .tg-i:nth-child(4) { grid-column: span 2; }
  .tg-more--narrow { display: none; }
  .tg-more--wide { display: block; }
}

/* The floating Book button: tablet and desktop only, shown by script once the card is out of view. */
.book-float {
  position: fixed;
  z-index: 90;
  inset: auto var(--gutter) 24px auto;
  display: grid;
  justify-items: center;
  gap: 0;
  box-shadow: var(--shadow-lg);
}
.book-float small { font-size: 11px; font-weight: 500; opacity: .8; }
.book-float[hidden] { display: none; }
@media (max-width: 719px) { .book-float { display: none; } }
/* It slides in (spec 5.4) when the script unhides it: @starting-style is the frame it
   leaves display:none on, so no script is needed. It just goes when hidden again. The
   transition list repeats .btn's, which this replaces. Not under reduced motion. */
@media (prefers-reduced-motion: no-preference) {
  .book-float {
    transition: background-color var(--t-hover) ease, color var(--t-hover) ease,
                border-color var(--t-hover) ease, box-shadow var(--t-hover) ease,
                scale var(--t-press) var(--ease-out),
                translate var(--t-move) var(--ease-out), opacity var(--t-move) var(--ease-out);
  }
  @starting-style {
    .book-float { translate: 0 16px; opacity: 0; }
  }
}

/* The full-screen photo viewer (js/gallery-viewer.js): a native <dialog> over a scroll-snap track. */
.gv {
  position: fixed; inset: 0; z-index: 400;
  width: 100%; height: 100%; max-width: none; max-height: none;
  margin: 0; padding: 0; border: 0;
  background: rgba(2, 22, 28, .96); color: #fff;
}
.gv:focus { outline: none; }
.gv::backdrop { background: transparent; }
/* The scroll lock pads back the scrollbar it removes, like the sheet's: gallery-viewer.js
   sets --sheet-sbw while the viewer is open. */
html:has(.gv[open]) { overflow: hidden; padding-inline-end: var(--sheet-sbw, 0px); }
.gv-track {
  display: flex; height: 100%;
  overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior: contain;
  scrollbar-width: none;
}
.gv-track::-webkit-scrollbar { display: none; }
.gv-slide {
  flex: 0 0 100%; height: 100%; margin: 0; scroll-snap-align: center;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 12px; padding: 56px 16px 64px;
}
.gv-slide img { max-width: 100%; min-height: 0; flex: 0 1 auto; object-fit: contain; }
.gv-cap { max-width: 60ch; font-size: 14px; text-align: center; color: rgba(255, 255, 255, .85); }
.gv-count {
  position: absolute; inset: auto 0 20px; margin: 0; text-align: center;
  font-size: 14px; font-variant-numeric: tabular-nums; color: rgba(255, 255, 255, .85);
  pointer-events: none;
}
.gv-btn {
  position: absolute; display: grid; place-items: center;
  width: 48px; height: 48px; padding: 0; border: 0; border-radius: 50%;
  background: rgba(255, 255, 255, .14); color: #fff; font: inherit; font-size: 28px; line-height: 1;
  cursor: pointer;
}
.gv-btn:hover { background: rgba(255, 255, 255, .26); }
.gv-btn:focus-visible { outline: 2px solid var(--gold-lt); outline-offset: 2px; }
.gv-btn[hidden] { display: none; }
.gv-x { top: 12px; right: 12px; }
.gv-prev, .gv-next { top: 50%; margin-top: -24px; }
.gv-prev { left: 12px; }
.gv-next { right: 12px; }
@media (max-width: 719px) { .gv-prev, .gv-next { display: none; } }
@media (prefers-reduced-motion: no-preference) { .gv-track { scroll-behavior: smooth; } }

/* The phone bar. See note 3 at the top of this section. */
.book-bar { display: none; }
@media (max-width: 719px) {
  .book-bar {
    position: fixed;
    z-index: 90;
    inset: auto 0 0 0;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-3);
    padding: 10px var(--gutter);
    padding-block-end: calc(10px + env(safe-area-inset-bottom));
    background: color-mix(in srgb, var(--paper) 96%, transparent);
    backdrop-filter: blur(10px);
    border-block-start: 1px solid var(--line-2);
  }
  .book-bar .price { min-width: 0; }
  .book-bar .btn { flex: 0 0 auto; }
  body[data-page="tour"] .mnav { display: none; }
  /* app.js measures .mnav, which is gone here, so --mnav-h would be 0 and the
     bar would sit on top of the footer's last line. */
  body[data-page="tour"] .mnav-sp { height: calc(68px + env(safe-area-inset-bottom)); }
}

/* --------------------------------------------------------------- facts --- */
.facts {
  display: grid;
  gap: var(--space-4) var(--space-5);
  padding: clamp(18px, 2.6vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-2);
}
@media (min-width: 560px) { .facts { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.fact-i {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: var(--space-3);
  align-items: start;
}
.fact-ic {
  display: grid;
  place-content: center;
  width: 40px;
  height: 40px;
  border-radius: 12px;
  background: color-mix(in srgb, var(--sea) 13%, transparent);
  color: var(--sea-ink);
}
.fact-ic svg { width: 20px; height: 20px; }
.fact-b { display: grid; justify-items: start; gap: 4px; min-width: 0; }
.fact-k {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.fact-v {
  font-family: var(--font-sub);
  font-size: 1.125rem;
  line-height: 1.3;
  color: var(--deep);
}
/* A value the client has not filled in yet. Dashed and visible on purpose:
   a gap that looks like a gap is a gap that gets closed before launch. */
.badge--dash {
  border: 1px dashed var(--line-2);
  background: transparent;
  color: var(--muted);
}

/* -------------------------------------------------------- good to know --- */
.know { display: grid; gap: var(--space-5); }
@media (min-width: 640px) { .know { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1200px) { .know { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.know-card {
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-card);
}
.know-card h3 {
  margin-block-end: var(--space-3);
  font-family: var(--font-sub);
  font-size: var(--fs-h3);
  color: var(--deep);
}
.know-list { display: grid; gap: 10px; }
.know-list li {
  display: grid;
  grid-template-columns: 18px 1fr;
  gap: 10px;
  align-items: start;
  color: var(--muted);
}
.know-ic { display: block; }
.know-ic svg { width: 16px; height: 16px; margin-block-start: 5px; color: var(--sea-ink); }

/* ============================================================== cars ---
   /cars (the fleet list) and /cars/<slug> (one vehicle).

   Page-scoped rules use body[data-page="cars"] / ["car"] rather than an id,
   because layout.js already writes the route key on <body> and an id-scoped
   rule is how the NEXT page silently inherits a layout it never asked for
   (see the #tours note in the tours section).
   ===================================================================== */

/* ---------------------------------------------------------- dates bar --- */
/* A real GET form to this same page: it works with JavaScript off, and the URL
   it produces is the URL the Worker reads back. */
.datesbar {
  display: grid;
  gap: var(--space-4);
  margin-block: var(--space-6);
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-2);
  box-shadow: var(--shadow);
}
@media (min-width: 640px) {
  .datesbar { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--space-4) var(--space-5); }
}
@media (min-width: 1040px) {
  .datesbar { grid-template-columns: repeat(2, minmax(0, 1fr)) auto; align-items: end; }
  .datesbar .fld--go { grid-column: 3; grid-row: 1 / span 2; align-self: center; }
}
.datesbar .fld--go .btn { width: 100%; }

/* ------------------------------------------------------- availability --- */
/* Everything here ships with its copy already written and only toggles
   [hidden]: an empty aria-live region announces nothing when it is unhidden,
   and a flow that has to invent the wording ships it in one language. */
.avail {
  display: grid;
  gap: var(--space-4);
  margin-block-end: var(--space-6);
}
.avail[hidden] { display: none; }
.avail-sum {
  font-family: var(--font-sub);
  font-size: 1.0625rem;
  font-weight: 600;
  color: var(--deep);
}
.state-error {
  display: grid;
  gap: var(--space-3);
  justify-items: start;
  padding: clamp(16px, 2.2vw, 22px);
  border: 1px solid #F0B4AE;
  border-radius: var(--r);
  background: #FCEDEB;
  color: #7A1C15;
  font-size: var(--fs-small);
  line-height: 1.55;
}
.state-error[hidden] { display: none; }
.state-error-t { font-family: var(--font-sub); font-size: var(--fs-h3); line-height: 1.2; }

/* Skeleton price lines while the browser flow waits for the quote. The FLOW
   sets data-quote="pending" on #fleet when it sends the request, and "done" or
   "error" when it has an answer. The Worker never renders "pending": without
   JavaScript, or with a flow that failed to load, nothing would ever lift it and
   every price on the page would stay a grey bar.

   The shimmer is COUNTED, not infinite (global constraints): 30 passes is far
   longer than any quote can take, after which the bar settles into a static
   placeholder instead of looping forever behind a request that never came back. */
[data-quote="pending"] .ccard-body > :is(.price, .ccard-price) {
  position: relative;
  min-height: 34px;
  border-radius: var(--r-sm);
  background: var(--paper-3);
  overflow: hidden;
  /* `color: transparent` AND hidden children: the on-request line wraps its
     words in a bordered pill (an element), while the "from" line is a bare text
     node on the <p> itself, which no child selector can reach. */
  color: transparent;
}
[data-quote="pending"] .ccard-body > :is(.price, .ccard-price) > * { visibility: hidden; }
[data-quote="pending"] .ccard-body > :is(.price, .ccard-price)::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--paper) 88%, transparent) 50%, transparent 80%);
  translate: -100% 0;
  animation: sk-shimmer 1.2s var(--ease-in-out) 30;
}
@keyframes sk-shimmer {
  from { translate: -100% 0; }
  to { translate: 100% 0; }
}
@media (prefers-reduced-motion: reduce) {
  [data-quote="pending"] .ccard-body > :is(.price, .ccard-price)::after { animation: none; }
}

/* ---------------------------------------------------- fleet categories --- */
.fleet-cat + .fleet-cat { margin-block-start: clamp(40px, 6vw, 72px); }
.cat-head { margin-block-end: var(--space-5); }
.cat-name {
  font-family: var(--font-sub);
  font-size: clamp(1.4rem, 1.1rem + 1.2vw, 2rem);
  line-height: 1.15;
  color: var(--deep);
}
.cat-pitch { margin-block-start: var(--space-2); }
.cars-empty { display: grid; gap: var(--space-3); margin-block-end: var(--space-6); }
.cars-empty h2 { font-family: var(--font-sub); font-size: var(--fs-h3); color: var(--deep); }

/* ------------------------------------------------------------ car page --- */
.car-top { padding-block: clamp(24px, 4vw, 56px); }
.car-grid { display: grid; gap: var(--space-6); }
@media (min-width: 900px) {
  .car-grid { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: var(--space-8); align-items: start; }
}
.car-media {
  aspect-ratio: 4 / 3;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--paper-3);
}
.car-img { width: 100%; height: 100%; object-fit: cover; object-position: center; }
/* Same stand-in as the cards: the brand horizon on deep water, never a grey box.
   Doubled class so it beats .car-media's own background on source order. */
.car-media.car-media--none {
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 12px;
  padding: var(--space-5);
  background: radial-gradient(120% 100% at 50% 0%, var(--deep-2), var(--deep));
  text-align: center;
}
.car-media--none .mark { width: 96px; height: 34px; --mark-sun: var(--gold-lt); --mark-sea: var(--aqua-lt); }

.car-info { display: grid; gap: var(--space-4); align-content: start; min-width: 0; }
/* The tour hero's crumbs sit on a photo; these sit on paper. */
.crumbs--ink { color: var(--muted); }
.crumbs--ink [aria-current="page"] { color: var(--deep); }
/* See note 1 in the components header - the element selector is required. */
h1.car-t { font-size: clamp(2.5rem, 1.4rem + 3.4vw, 3.9rem); }

.specs-list { display: grid; gap: var(--space-2); }
.spec-r {
  display: grid;
  grid-template-columns: 20px 1fr auto;
  gap: var(--space-3);
  align-items: center;
  padding-block: 10px;
  border-block-end: 1px solid var(--line);
}
.spec-ic svg { width: 18px; height: 18px; color: var(--sea-ink); }
.spec-k { color: var(--muted); font-size: var(--fs-small); }
.spec-v { font-family: var(--font-sub); font-weight: 600; font-size: 1.125rem; color: var(--deep); }

.rates {
  display: grid;
  gap: var(--space-3);
  padding: clamp(18px, 2.4vw, 26px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper-2);
}
.rates-h { font-family: var(--font-sub); font-size: var(--fs-h3); color: var(--deep); }
.rates-table { display: grid; gap: 2px; }
.rate-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-3);
  padding-block: 8px;
}
.rate-row + .rate-row { border-block-start: 1px solid var(--line); }
.rate-k { color: var(--muted); }
.rate-v { font-family: var(--font-sub); font-weight: 600; font-size: 1.125rem; color: var(--deep); }
.rates-note { color: var(--muted); font-size: var(--fs-small); }
.rates-seasons { display: grid; gap: 6px; color: var(--gold-ink); font-size: var(--fs-small); font-weight: 600; }
.rates--none { border-style: dashed; border-color: var(--line-2); }

.car-act { display: flex; flex-wrap: wrap; gap: var(--space-3); }
.car-act .btn { flex: 1 1 auto; min-width: 180px; }
.car-down .nf-in { display: grid; gap: var(--space-5); justify-items: start; }

/* =====================================================================
   ---- services ----
   /private-travel and /business-transport, both built from
   src/components/service.js: a dark hero band, a card grid, and the request
   band holding the lead form.

   Every selector is a page-local .svc-* class, never an id, so nothing here
   can leak onto another page (the `#tours .tcard--lg` lesson).

   One rule is load-bearing rather than taste: `.svc-hero h1.display`, not
   `.svc-hero .display`. `h1.display` sets the display size one specificity
   step above a bare class, so the single-class version silently loses.
   ===================================================================== */

/* ----------------------------------------------------------- hero band --- */
.svc-hero { padding-block: clamp(40px, 7vw, 96px); }
/* Smaller than the home hero's --fs-display: this title shares its row with a
   photo from 960 px, and VOTRE CHAUFFEUR. has to fit half the width. */
.svc-hero h1.display { font-size: clamp(2.75rem, 1.4rem + 4.6vw, 5rem); }
.svc-sub {
  max-width: 36ch;
  margin-block-start: var(--space-2);
  font-family: var(--font-sub);
  font-size: clamp(1.125rem, 1rem + .9vw, 1.6rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--gold-lt);
}
.svc-hero .lede { margin-block-start: var(--space-4); }
.svc-cta { margin-block-start: var(--space-6); }
.svc-media img { box-shadow: var(--shadow-lg); }

/* ----------------------------------------------------------- card grid --- */
/* Four cards: one column on a phone, two from 640, all four in a row from
   1040 (at 960 a quarter of the wrap is too narrow for a French title). */
.svc-grid {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: minmax(0, 1fr);
}
@media (min-width: 640px) { .svc-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .svc-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.svc-card {
  display: grid;
  grid-template-rows: auto auto 1fr auto;
  justify-items: start;
  gap: var(--space-3);
  padding: clamp(20px, 2.4vw, 28px);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--paper);
  box-shadow: var(--shadow-card);
}
.svc-ic {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--gold-lt) 24%, var(--paper));
  color: var(--gold-ink);
}
.svc-ic svg { width: 22px; height: 22px; }
.svc-t {
  font-family: var(--font-sub);
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--deep);
}
.svc-b { color: var(--muted); font-size: var(--fs-small); line-height: 1.6; }
.svc-go {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  min-height: 44px;
  align-self: end;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--sea-ink);
  border-block-end: 1px solid transparent;
}
.svc-go .arw svg { width: 16px; height: 16px; }
@media (hover: hover) and (pointer: fine) {
  .svc-go:hover { border-block-end-color: currentColor; }
  .svc-go:hover .arw { translate: 3px 0; }
}

/* -------------------------------------------------------- how it works --- */
.svc-steps { display: grid; gap: var(--space-6); }
@media (min-width: 860px) {
  .svc-steps { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-7); }
}
.svc-step {
  display: grid;
  align-content: start;
  gap: var(--space-3);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--line-2);
}
/* Decoration: the <ol> already numbers the steps for a screen reader. Large
   display type, so --gold clears the 3:1 large-text bar on paper. */
.svc-step-n {
  font-family: var(--font-num);
  font-size: clamp(3rem, 2.2rem + 2.4vw, 4.25rem);
  line-height: 1;
  color: var(--gold);
}

/* -------------------------------------------------------- request band --- */
/* The form is much taller than the words beside it: pin both to the top
   rather than floating the heading halfway down the form. */
.svc-request .band-in { align-items: start; }
.svc-direct { display: grid; gap: var(--space-2); margin-block-start: var(--space-4); }

/* ---- sheet ---- */
/* js/sheet.js. A bottom sheet on phones, a 480 px right-hand panel from 960 px.
   It moves with the `translate` property only (never `transform`), enters in
   320 ms and leaves in 240 ms. Everything is scoped under #sheet-root / .sheet.
   Reduced motion: no slide at all, opacity only, 1 ms.

   Scroll lock: overflow:hidden on <html>. Where scrollbars take space (not
   phones), that removes the scrollbar, so sheet.js measures it first and
   --sheet-sbw pads its width back: no sideways shift, and the fixed scrim and
   panel still reach the right edge. (Not scrollbar-gutter:stable — that keeps
   an undimmed strip beside the scrim that nothing fixed can cover.) */
html[data-sheet-open] { overflow: hidden; padding-inline-end: var(--sheet-sbw, 0px); }

#sheet-root .sheet-scrim {
  position: fixed;
  z-index: 300;
  inset: 0;
  background: color-mix(in srgb, var(--deep-ink) 58%, transparent);
  opacity: 0;
  pointer-events: none;
  transition: opacity 240ms ease;
}
#sheet-root .sheet-scrim[data-state="open"] { opacity: 1; pointer-events: auto; transition-duration: 320ms; }

#sheet-root .sheet {
  position: fixed;
  z-index: 301;
  inset: auto 0 0 0;
  display: flex;
  flex-direction: column;
  max-height: 92vh;
  max-height: 92svh;
  background: var(--paper);
  border-radius: var(--r-lg) var(--r-lg) 0 0;
  box-shadow: var(--shadow-lg);
  translate: 0 100%;
  transition: translate 240ms var(--ease-out);
}
#sheet-root .sheet[data-state="open"] { translate: 0 0; transition-duration: 320ms; }
#sheet-root .sheet[data-drag] { transition: none; }

/* Drag zones. touch-action:none so a finger drags the sheet instead of
   scrolling the page behind it; the scrollable body is not a drag zone. */
.sheet-handle, .sheet-head { touch-action: none; user-select: none; }
.sheet-handle {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  height: 26px;
  cursor: grab;
}
.sheet-handle::before {
  content: '';
  width: 44px;
  height: 5px;
  border-radius: var(--r-pill);
  background: var(--line-2);
}
.sheet[data-drag] .sheet-handle { cursor: grabbing; }

.sheet-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 2px 20px 14px;
}
.sheet-h { display: grid; gap: 2px; min-width: 0; }
.sheet-h:focus { outline: none; } /* focus is moved here by script, not by the visitor */
.sheet-t {
  font-family: var(--font-sub);
  font-size: 1.4rem;
  line-height: 1.2;
  color: var(--deep);
}
.sheet-n {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--gold-ink);
}

/* The close ×, drawn: two bars turned with the `rotate` property. */
.sheet-x {
  position: relative;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--paper);
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.sheet-x::before, .sheet-x::after {
  content: '';
  position: absolute;
  inset: 50% auto auto 50%;
  width: 16px;
  height: 2px;
  margin: -1px 0 0 -8px;
  border-radius: 2px;
  background: var(--deep);
  rotate: 45deg;
}
.sheet-x::after { rotate: -45deg; }
@media (hover: hover) and (pointer: fine) {
  .sheet-x:hover { border-color: var(--line-2); background: var(--paper-2); }
}

.sheet-bar { flex: 0 0 auto; height: 3px; background: var(--paper-3); }
.sheet-bar > i {
  display: block;
  height: 100%;
  background: var(--gold);
  transform-origin: 0 50%;
  scale: 0 1;
  transition: scale 240ms var(--ease-out);
}

.sheet-scroll {
  flex: 1 1 auto;
  min-height: 0;
  /* hidden on x: the 24 px step slide must not flash a horizontal scrollbar */
  overflow: hidden auto;
  overscroll-behavior: contain;
  padding: 20px;
}
/* sheet.js makes the scroll area a Tab stop only when it overflows with nothing
   focusable inside; the ring is drawn inside so the overflow clip keeps it. */
.sheet-scroll:focus-visible { outline-offset: -3px; border-radius: 0; }
.sheet-slot:empty { display: none; }
.sheet-banner { margin-block-end: var(--space-4); }
.sheet-banner-count { margin-block-start: 6px; font-weight: 600; font-variant-numeric: tabular-nums; }

.sheet-body[data-dir="forward"] { animation: sheet-step-fwd 240ms var(--ease-out); }
.sheet-body[data-dir="back"] { animation: sheet-step-back 240ms var(--ease-out); }
.sheet-body[aria-busy="true"] { cursor: progress; }
@keyframes sheet-step-fwd { from { opacity: 0; translate: 24px 0; } }
@keyframes sheet-step-back { from { opacity: 0; translate: -24px 0; } }
@keyframes sheet-fade { from { opacity: 0; } }

.sheet-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: flex-end;
  gap: var(--space-3);
  flex: 0 0 auto;
  padding: 12px 20px;
  padding-block-end: calc(12px + env(safe-area-inset-bottom));
  border-block-start: 1px solid var(--line);
  background: var(--paper);
}
.sheet-foot:empty { display: none; }
.sheet-foot button:disabled { opacity: .6; cursor: progress; }

.sheet-vh,
.tcard-say {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

@media (min-width: 960px) {
  #sheet-root .sheet {
    inset: 0 0 0 auto;
    width: 480px;
    max-height: none;
    border-radius: var(--r-lg) 0 0 var(--r-lg);
    translate: 100% 0;
  }
  .sheet-handle { display: none; }
  .sheet-head { padding: 24px 24px 16px; }
  .sheet-scroll { padding: 24px; }
  .sheet-foot { padding-inline: 24px; }
}

@media (prefers-reduced-motion: reduce) {
  #sheet-root .sheet, #sheet-root .sheet[data-state="open"] {
    translate: none;
    opacity: 0;
    transition: opacity 1ms linear;
  }
  #sheet-root .sheet[data-state="open"] { opacity: 1; }
  .sheet-body[data-dir] { animation: sheet-fade 1ms linear; }
  .sheet-bar > i { transition: none; }
}

/* ---- car flow ---- */
/* js/flows/car.js, rendered inside the sheet. Everything is scoped to `.cf-*`
   and reuses the page's own field, button, badge and message classes, so the
   sheet reads as part of the site rather than a second design.
   Motion here is one 300 ms count-up tween (in JS) and one COUNTED shimmer: no
   infinite animation, and `translate` rather than `transform` (constraints). */

.cf-h {
  font-family: var(--font-sub);
  font-size: var(--fs-h3);
  line-height: 1.2;
  color: var(--deep);
  margin-block-end: var(--space-4);
}
.cf-lede { color: var(--muted); font-size: var(--fs-small); margin-block-end: var(--space-4); }
.cf-form { display: grid; gap: var(--space-5); }
.cf-grid { display: grid; gap: var(--space-4); }
@media (min-width: 420px) {
  .cf-grid { grid-template-columns: 1fr 1fr; }
  .cf-grid .fld--wide { grid-column: 1 / -1; }
}
.cf-hint { color: var(--muted); font-size: 12px; line-height: 1.4; }
.cf-opt { font-weight: 400; color: var(--muted); }

/* Pick-up place: three cards, one radio each. The radio stays a real radio — it
   is the Tab stop and the thing a screen reader announces; the card is only its
   label. */
.cf-places { display: grid; gap: var(--space-3); border: 0; padding: 0; }
.cf-places legend { padding: 0; margin-block-end: 2px; }
.cf-place {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 10px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--paper);
  cursor: pointer;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.cf-place-r { flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--deep); }
.cf-place-t { font-weight: 600; font-size: var(--fs-small); color: var(--deep); }
.cf-place:has(.cf-place-r:checked) { border-color: var(--deep); background: var(--paper-2); }
.cf-place-x:empty { display: none; }
@media (min-width: 420px) {
  .cf-places { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .cf-places legend { grid-column: 1 / -1; }
}

/* ---- choose ---- */
.cf-recap {
  display: flex;
  flex-wrap: wrap;
  gap: 2px var(--space-3);
  margin-block-end: var(--space-4);
  font-size: var(--fs-small);
  color: var(--muted);
}
.cf-recap-w { font-weight: 600; color: var(--deep); }
.cf-cars { display: grid; gap: var(--space-3); }
.cf-car {
  display: flex;
  align-items: flex-start;
  gap: 10px;
  padding: 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--paper);
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
label.cf-car { cursor: pointer; }
.cf-car-r { flex: 0 0 auto; width: 18px; height: 18px; margin-block-start: 3px; accent-color: var(--deep); }
.cf-car-b { display: grid; gap: 3px; min-width: 0; flex: 1 1 auto; }
.cf-car-n { font-family: var(--font-sub); font-size: 1.125rem; font-weight: 600; color: var(--deep); }
.cf-car-p { font-family: var(--font-sub); font-size: 1.5rem; font-weight: 600; color: var(--deep); }
.cf-car-s { font-size: var(--fs-small); color: var(--muted); }
.cf-car-d { font-size: 12px; color: var(--muted); }
.cf-car:has(.cf-car-r:checked) { border-color: var(--deep); background: var(--paper-2); }
/* Taken for these dates: still listed and still readable, plainly not on offer. */
.cf-car--off { background: var(--paper-3); border-style: dashed; color: var(--muted); }
.cf-car--off .cf-car-n { color: var(--muted); }
.cf-car--req .cf-req { justify-self: start; margin-block-start: 6px; }
.cf-none { color: var(--muted); font-size: var(--fs-small); }

/* Skeleton rows while the quote is in flight. The shimmer is COUNTED (30
   passes), never infinite: after that it settles into a plain grey bar rather
   than looping for ever behind a request that never came back. */
.qskel {
  position: relative;
  height: 86px;
  border-radius: var(--r-sm);
  background: var(--paper-3);
  overflow: hidden;
}
.qskel::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--paper) 88%, transparent) 50%, transparent 80%);
  translate: -100% 0;
  animation: sk-shimmer 1.2s var(--ease-in-out) 30;
}

/* ---- extras ---- */
.cf-extras { display: grid; gap: var(--space-3); }
.cf-extra {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding: 12px 14px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-2);
}
.cf-extra-b { display: grid; gap: 2px; min-width: 0; }
.cf-extra-n { font-weight: 600; color: var(--deep); }
.cf-extra-p { font-size: var(--fs-small); color: var(--muted); }
.cf-steps { display: flex; align-items: center; gap: 4px; flex: 0 0 auto; }
.cf-step {
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--paper);
  font-size: 1.125rem;
  font-weight: 600;
  color: var(--deep);
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.cf-step:disabled { opacity: .4; }
.cf-qty { min-width: 2.5ch; text-align: center; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--deep); }
.cf-total {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-4);
  margin-block-start: var(--space-5);
  padding-block-start: var(--space-4);
  border-block-start: 1px solid var(--line);
}
.cf-total-k { font-weight: 600; color: var(--deep); }
.cf-total-v {
  font-family: var(--font-sub);
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--deep);
  font-variant-numeric: tabular-nums;
}

/* ---- details summary ---- */
.cf-sum {
  display: grid;
  gap: 6px;
  margin-block-end: var(--space-5);
  padding: 14px 16px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--paper-2);
}
.cf-sum-r { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-4); }
.cf-sum-k { flex: 0 0 auto; font-size: var(--fs-small); color: var(--muted); }
.cf-sum-v { text-align: end; font-weight: 600; color: var(--deep); }
.cf-sum-r--total { margin-block-start: 4px; padding-block-start: 8px; border-block-start: 1px solid var(--line); }
.cf-sum-r--total .cf-total-v { font-size: 1.25rem; }
/* The Turnstile mount under the details form (js/flows/send.js): a challenge sits clear of the
   notes field, and send.js scrolls it into view. Empty between sends, so no space then. */
.cf-ts { margin-block-start: var(--space-5); }
.cf-ts:empty { margin-block-start: 0; }

/* ---- result ---- */
.cf-res { display: grid; gap: var(--space-3); justify-items: start; }
.cf-res-h { margin-block-end: 0; }
.cf-res-k { font-size: 12px; font-weight: 600; letter-spacing: .16em; text-transform: uppercase; color: var(--gold-ink); }
.cf-ref {
  font-family: var(--font-num);
  font-size: clamp(2.25rem, 1.4rem + 3.4vw, 3.25rem);
  line-height: 1;
  letter-spacing: .01em;
  color: var(--deep);
}
.cf-res-next { color: var(--muted); font-size: var(--fs-small); line-height: 1.55; }

@media (hover: hover) and (pointer: fine) {
  .cf-place:hover, label.cf-car:hover { border-color: var(--deep-2); }
  .cf-step:not(:disabled):hover { border-color: var(--deep); background: var(--paper-2); }
}
@media (prefers-reduced-motion: reduce) {
  .qskel::after { animation: none; }
}

/* ---- tour flow ---- */
/* js/flows/tour.js and js/calendar.js, inside the sheet. The steppers, totals,
   summary, fields and result are the car flow's `.cf-*`; only the calendar, the
   departure radio cards and the tour's own wrappers are new here, built from the
   same tokens. Motion: colour transitions and one COUNTED skeleton shimmer
   (`translate`, a counted 30 passes). */
.tf-cal { margin-block-end: var(--space-5); }
.tf-paxes { align-items: start; }
.tf-price .cf-total { margin-block-start: 0; }
.tf-price .cf-hint { margin-block-start: 4px; }
/* The Shared / Private switch on top of step 1: two cards built like .cf-car,
   the pressed one in the deep border and the second paper. */
.tf-opts { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-3); }
.tf-opt {
  display: grid;
  gap: 2px;
  align-content: start;
  min-height: 44px;
  padding: 12px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--paper);
  text-align: start;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.tf-opt[aria-pressed="true"] { border-color: var(--deep); background: var(--paper-2); box-shadow: inset 0 0 0 1px var(--deep); }
/* An option withdrawn while the page was open (S-R2): it reads "No longer offered" and takes no press. */
.tf-opt:disabled { opacity: .45; cursor: not-allowed; }
.tf-opt-n { font-family: var(--font-sub); font-size: 1.125rem; font-weight: 600; color: var(--deep); }
.tf-opt-p { font-size: var(--fs-small); color: var(--muted); font-variant-numeric: tabular-nums; }
.tf-opt-l { margin-block: var(--space-2) var(--space-5); font-size: var(--fs-small); }
.tf-opt-l:empty { display: none; }
.tf-opts:has(+ .tf-opt-l:empty) { margin-block-end: var(--space-5); }
@media (hover: hover) and (pointer: fine) {
  .tf-opt:not(:disabled):hover { border-color: var(--deep-2); }
}
.cf-res-note { max-width: 46ch; }
.tf-pickup { display: grid; gap: var(--space-3); }
.tf-pickup-x:empty { display: none; }
/* request sheet (Task 21b): the "Sending…" live line under the details form */
.rf-live { margin-block-start: var(--space-3); }
.rf-live:empty { margin-block-start: 0; }
.sheet-banner .msg-acts { margin-block-start: var(--space-3); }

/* ---- calendar ---- */
.cal { display: grid; gap: var(--space-3); min-width: 0; }
.cal-nav {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  min-height: 44px;
}
.cal-m {
  font-family: var(--font-sub);
  font-size: 1.25rem;
  font-weight: 600;
  line-height: 1.2;
  color: var(--deep);
}
.cal-m::first-letter { text-transform: uppercase; }
.cal-arw {
  display: grid;
  place-items: center;
  flex: 0 0 auto;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--line-2);
  border-radius: 50%;
  background: var(--paper);
  color: var(--deep);
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.cal-arw:disabled { opacity: .4; }
/* a chevron from two borders: the corner points back, or (next) forward */
.cal-arw-i {
  width: 9px;
  height: 9px;
  border-block-start: 2px solid currentColor;
  border-inline-start: 2px solid currentColor;
  rotate: -45deg;
  translate: 2px 0;
}
.cal-arw--next .cal-arw-i { rotate: 135deg; translate: -2px 0; }

/* 7 equal columns that shrink with the sheet: no horizontal scroll at 390 px,
   and every day stays a 44 px tall target. */
.cal-grid { display: grid; gap: 2px; }
.cal-row { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 2px; }
.cal-wd {
  padding-block: 4px;
  overflow: hidden;
  text-align: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--muted);
}
.cal-d {
  position: relative;
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 44px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background: transparent;
  overflow: hidden;
  color: var(--text);
  font-variant-numeric: tabular-nums;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease, color var(--t-hover) ease;
}
.cal-dn { font-size: var(--fs-small); font-weight: 600; }
/* Nothing on it: disabled in look only. It keeps its tab stop and arrow keys
   (spec §6.2), so it keeps its focus ring too. */
.cal-d[aria-disabled="true"] { color: color-mix(in srgb, var(--muted) 72%, var(--paper)); cursor: default; }
.cal-d--out .cal-dn { opacity: .45; }
.cal-d--has, .cal-d--full { border-color: var(--line-2); background: var(--paper-2); color: var(--deep); cursor: pointer; }
.cal-d--has::after {
  content: "";
  position: absolute;
  inset-block-end: 6px;
  inset-inline-start: calc(50% - 2px);
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--sea);
}
/* every departure that day is sold out: still opens (the list says so) */
.cal-d--full { border-style: dashed; background: var(--paper-3); color: var(--muted); }
.cal-d--full .cal-dn { text-decoration: line-through; text-decoration-color: var(--line-2); }
.cal-d--today { border-color: var(--gold); }
.cal-d.cal-d--on { border-color: var(--deep); background: var(--deep); color: #fff; }
.cal-d--on::after { background: var(--gold-lt); }
.cal-d:focus-visible { outline: 3px solid var(--sea-ink); outline-offset: -3px; }
.cal-d--on:focus-visible { outline-color: var(--gold-lt); }
/* skeleton day while its month loads (and before calendar.js itself arrives) */
.cal-d--sk { background: var(--paper-3); color: var(--muted); }
.cal-d--sk::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 20%, color-mix(in srgb, var(--paper) 88%, transparent) 50%, transparent 80%);
  translate: -100% 0;
  animation: sk-shimmer 1.2s var(--ease-in-out) 30;
}

/* ---- calendar states ---- */
.state-error-say { display: grid; gap: var(--space-2); }
.cal-count { font-weight: 600; font-variant-numeric: tabular-nums; }
.cal-empty {
  display: grid;
  gap: var(--space-2);
  justify-items: start;
  padding: clamp(16px, 2.2vw, 22px);
  border: 1px dashed var(--line-2);
  border-radius: var(--r);
  background: var(--paper-2);
  color: var(--muted);
  font-size: var(--fs-small);
  line-height: 1.55;
}
.cal-empty .state-error-t { color: var(--deep); }
.cal-state:empty, .cal-list:empty { display: none; }

/* ---- the picked day's departures: radio cards like the car flow's ---- */
.cal-deps { display: grid; gap: var(--space-3); min-width: 0; margin: 0; padding: 0; border: 0; }
.cal-deps-lg { padding: 0; margin-block-end: 2px; font-size: var(--fs-small); font-weight: 600; color: var(--deep); }
.cal-dep {
  display: flex;
  align-items: center;
  gap: 10px;
  min-height: 48px;
  padding: 10px 14px;
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm);
  background: var(--paper);
  cursor: pointer;
  transition: border-color var(--t-hover) ease, background-color var(--t-hover) ease;
}
.cal-dep-r { flex: 0 0 auto; width: 18px; height: 18px; margin: 0; accent-color: var(--deep); }
.cal-dep-b {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 6px var(--space-3);
  flex: 1 1 auto;
  min-width: 0;
}
.cal-dep-t { font-family: var(--font-sub); font-size: 1.125rem; font-weight: 600; color: var(--deep); font-variant-numeric: tabular-nums; }
.cal-dep-s { font-size: var(--fs-small); color: var(--muted); }
.cal-dep:has(.cal-dep-r:checked) { border-color: var(--deep); background: var(--paper-2); }
.cal-dep--out { border-style: dashed; background: var(--paper-3); color: var(--muted); cursor: not-allowed; }
.cal-dep--out .cal-dep-t { color: var(--muted); text-decoration: line-through; }
/* "Only 3 seats left": gold, static. No pulse. */
.chip-seats {
  display: inline-flex;
  align-items: center;
  padding: 3px 10px;
  border: 1px solid color-mix(in srgb, var(--gold) 45%, transparent);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--gold-lt) 22%, var(--paper));
  color: var(--gold-ink);
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
}

@media (hover: hover) and (pointer: fine) {
  .cal-arw:not(:disabled):hover { border-color: var(--deep); background: var(--paper-2); }
  .cal-d--has:hover, .cal-d--full:hover { border-color: var(--deep-2); }
  .cal-d--on:hover { border-color: var(--deep); }
  .cal-dep:not(.cal-dep--out):hover { border-color: var(--deep-2); }
}
@media (prefers-reduced-motion: reduce) {
  .cal-d--sk::before { animation: none; }
  .cal-arw, .cal-d, .cal-dep { transition: none; }
}

/* =====================================================================
   HOMEPAGE EDITORIAL REFRESH

   The home page has its own, calmer visual rhythm: one island-led hero, a
   concise service switchboard and a contained planning surface. Everything
   is scoped to body[data-page="home"] so the booking and detail pages keep
   their compact, task-first UI.
   ===================================================================== */

body[data-page="home"] {
  --home-card-r: var(--r-lg);
  background: var(--paper-2);
}

/* The opener follows the client's preferred two-world composition: rental on
   the left, island discovery on the right, joined by one branded seam. */
body[data-page="home"] .hero--duo {
  position: relative;
  isolation: isolate;
  display: grid;
  grid-template-columns: minmax(0, 52fr) minmax(0, 48fr);
  min-height: clamp(700px, 86svh, 900px);
  margin-block-start: calc(var(--hdr-h) * -1);
  overflow: hidden;
  background: var(--deep-ink);
  color: #fff;
}
body[data-page="home"] .demo-note + #main .hero--duo { margin-block-start: 0; }
body[data-page="home"] .hdr[data-hdr="over"]:not(.hdr--solid) {
  border-block-end: 0;
  background: linear-gradient(180deg, rgba(2, 31, 39, .72), rgba(2, 31, 39, .25) 66%, transparent);
  box-shadow: none;
}
body[data-page="home"] .hdr-logo img { height: 40px; }

/* French navigation is materially wider than English. Collapse the repeated
   phone number to its icon before it can push the primary action off-canvas. */
@media (min-width: 960px) and (max-width: 1499px) {
  body[data-page="home"] .hdr-tel span { display: none; }
  body[data-page="home"] .nav { gap: clamp(12px, 1.4vw, 22px); }
  body[data-page="home"] .nav-list { gap: clamp(12px, 1.4vw, 22px); }
}

.hero-duo-defs {
  position: absolute;
  width: 0;
  height: 0;
}
.hero-duo-panel {
  position: relative;
  min-width: 0;
  overflow: hidden;
}
.hero-duo-panel--drive { z-index: 0; }
.hero-duo-panel--discover {
  z-index: 1;
  width: calc(100% + 6vw);
  margin-inline-start: -6vw;
  clip-path: url("#home-hero-discover-clip");
}
.hero-duo-img,
.hero-duo-shade {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}
.hero-duo-img {
  object-fit: cover;
  filter: saturate(.94) contrast(1.04);
  scale: 1.015;
  transition: scale 1.2s var(--ease-out), filter 1.2s var(--ease-out);
}
.hero-duo-panel--drive .hero-duo-img { object-position: 48% center; }
.hero-duo-panel--discover .hero-duo-img { object-position: 48% center; }
.hero-duo-panel--drive .hero-duo-shade {
  background:
    linear-gradient(90deg, rgba(2, 32, 40, .82), rgba(2, 43, 54, .34) 74%, rgba(2, 43, 54, .18)),
    linear-gradient(0deg, rgba(2, 32, 40, .8), transparent 58%),
    linear-gradient(180deg, rgba(2, 32, 40, .24), transparent 32%);
}
.hero-duo-panel--discover .hero-duo-shade {
  background:
    linear-gradient(90deg, rgba(2, 43, 54, .62), rgba(2, 43, 54, .27) 76%),
    linear-gradient(0deg, rgba(2, 32, 40, .75), transparent 60%),
    linear-gradient(180deg, rgba(2, 32, 40, .2), transparent 32%);
}
.hero-duo-copy {
  position: absolute;
  z-index: 2;
  inset-inline-start: clamp(28px, 5.25vw, 88px);
  inset-block-end: clamp(98px, 13vh, 142px);
  display: grid;
  justify-items: start;
  width: min(72%, 470px);
  text-shadow: 0 8px 32px rgba(2, 31, 39, .35);
}
.hero-duo-panel--discover .hero-duo-copy {
  inset-inline-start: clamp(100px, 11vw, 178px);
  width: min(64%, 470px);
}
.hero-duo-kicker {
  margin-block-end: clamp(10px, 1.5vh, 18px);
  color: var(--gold-lt);
  font-size: clamp(9px, .7vw, 11px);
  font-weight: 700;
  letter-spacing: .22em;
  line-height: 1.4;
  text-transform: uppercase;
}
.hero-duo-title {
  color: #fff;
  font-family: var(--font-display);
  font-size: clamp(4.5rem, 6.7vw, 7.25rem);
  font-weight: 400;
  line-height: .9;
  letter-spacing: -.025em;
}
.hero-duo-rule {
  width: min(100%, 330px);
  height: 1px;
  margin-block: clamp(17px, 2.7vh, 28px) clamp(13px, 2vh, 20px);
  background: linear-gradient(90deg, var(--gold-lt), color-mix(in srgb, var(--gold-lt) 20%, transparent));
}
.hero-duo-body {
  max-width: 33ch;
  color: color-mix(in srgb, #fff 88%, transparent);
  font-family: var(--font-display);
  font-size: clamp(1.125rem, .65vw + .8rem, 1.35rem);
  line-height: 1.4;
}
.hero-duo-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 12px;
  min-height: 48px;
  margin-block-start: clamp(22px, 3vh, 32px);
  padding: 12px 24px;
  border: 1px solid var(--gold-lt);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .08em;
  text-transform: uppercase;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease, translate var(--t-hover) var(--ease-out);
}
.hero-duo-cta--discover {
  background: var(--gold-lt);
  color: var(--deep-ink);
}
.hero-duo-cta .arw { display: inline-flex; }
.hero-duo-cta svg { width: 16px; height: 16px; }
.hero-duo-seam {
  position: absolute;
  z-index: 3;
  inset-block: 0;
  inset-inline-start: 46%;
  width: 5vw;
  height: 100%;
  overflow: visible;
  pointer-events: none;
}
.hero-duo-seam path {
  fill: none;
  stroke: color-mix(in srgb, var(--gold-lt) 86%, #fff);
  stroke-width: 2;
  vector-effect: non-scaling-stroke;
}
.hero-duo-divider {
  position: absolute;
  z-index: 4;
  inset-block-start: 50%;
  inset-inline-start: 49.15%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 62px;
  height: 62px;
  border: 1px solid var(--gold-lt);
  border-radius: 50%;
  background: color-mix(in srgb, var(--deep-ink) 82%, transparent);
  color: var(--gold-lt);
  box-shadow: 0 14px 35px rgba(2, 31, 39, .3);
  backdrop-filter: blur(8px);
  pointer-events: none;
}
.hero-duo-divider span { display: grid; place-items: center; }
.hero-duo-divider .mark { width: 32px; height: auto; }
.hero-scroll {
  position: absolute;
  z-index: 4;
  inset-inline-start: 50%;
  inset-block-end: 22px;
  translate: -50% 0;
  display: block;
  width: 28px;
  height: 44px;
  border: 1px solid color-mix(in srgb, var(--gold-lt) 86%, transparent);
  border-radius: var(--r-pill);
  background: color-mix(in srgb, var(--deep-ink) 36%, transparent);
  box-shadow: 0 8px 24px rgba(2, 31, 39, .24);
  backdrop-filter: blur(6px);
  transition: background-color var(--t-hover) ease, border-color var(--t-hover) ease;
}
.hero-scroll-dot {
  position: absolute;
  inset-block-start: 8px;
  inset-inline-start: 50%;
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--gold-lt);
  translate: -50% 0;
  /* Counted, not infinite (HANDOVER motion rule 1): a few passes to be noticed,
     then the dot rests at the top of the pill. */
  animation: hero-scroll-cue 1.8s ease-in-out 5;
}
@keyframes hero-scroll-cue {
  0% { opacity: 0; transform: translateY(0); }
  18% { opacity: 1; }
  68% { opacity: 1; }
  100% { opacity: 0; transform: translateY(21px); }
}

@media (hover: hover) and (pointer: fine) {
  .hero-duo-panel:hover .hero-duo-img { scale: 1.045; filter: saturate(1.02) contrast(1.04); }
  .hero-duo-cta:hover { background: var(--gold-lt); color: var(--deep-ink); translate: 0 -2px; }
  .hero-duo-cta--discover:hover { background: #f3d89a; }
  .hero-scroll:hover { background: color-mix(in srgb, var(--deep-ink) 70%, transparent); border-color: #fff; }
}

/* Planning now reads as a premium tool, not a full-width promotional stripe. */
body[data-page="home"] .finder {
  padding-block: clamp(72px, 9vw, 118px);
  background: linear-gradient(
    135deg,
    var(--gold-lt),
    color-mix(in srgb, var(--gold-lt) 58%, var(--cream))
  );
}
body[data-page="home"] .finder-in { gap: var(--space-6); }
body[data-page="home"] .finder-head {
  grid-template-columns: minmax(150px, .55fr) minmax(280px, 1.45fr);
  align-items: end;
  gap: var(--space-5) var(--space-8);
}
body[data-page="home"] .finder .eyebrow {
  align-self: start;
  padding-block-start: 9px;
  color: var(--gold-ink);
}
body[data-page="home"] .finder-intro {
  max-width: 34ch;
  color: var(--deep);
  font-family: var(--font-display);
  font-size: clamp(1.85rem, 1.35rem + 1.3vw, 2.8rem);
  line-height: 1.08;
  letter-spacing: -.015em;
  text-wrap: balance;
}
body[data-page="home"] .finder .tabs {
  justify-self: start;
  gap: 4px;
  width: auto;
  margin: 0;
  padding: 5px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--paper);
  box-shadow: 0 8px 26px -20px rgba(2, 43, 54, .55);
}
body[data-page="home"] .finder .tabs::after { display: none; }
body[data-page="home"] .finder .tab {
  min-height: 42px;
  padding: 9px 18px;
  border-radius: var(--r-pill);
  color: var(--muted);
  font-family: var(--font-body);
  font-size: 13px;
}
body[data-page="home"] .finder .tab[aria-selected="true"] {
  background: var(--deep);
  color: #fff;
  box-shadow: 0 8px 20px -12px rgba(2, 43, 54, .75);
}
body[data-page="home"] .finder-panels {
  padding: clamp(22px, 3.5vw, 40px);
  border: 1px solid var(--line);
  border-radius: var(--home-card-r);
  background: color-mix(in srgb, var(--paper) 97%, transparent);
  box-shadow: 0 24px 68px -42px rgba(2, 43, 54, .52);
}
body[data-page="home"] .finder-panel { padding-block-start: 0; }
body[data-page="home"] .finder-form { gap: clamp(14px, 2vw, 22px); }
body[data-page="home"] .finder .fld-in {
  min-height: 50px;
  border-color: var(--line-2);
  border-radius: 12px;
  background-color: var(--paper-2);
}
body[data-page="home"] .finder .finder-go { min-height: 50px; padding-inline: 24px; }

/* Bring the rest of the page into the same editorial system without touching
   shared components on the deeper, conversion-focused pages. */
body[data-page="home"] .section { padding-block: clamp(76px, 9vw, 128px); }
body[data-page="home"] .sec-head { gap: var(--space-5); margin-block-end: clamp(40px, 6vw, 72px); }
body[data-page="home"] .sec-head .lede { font-size: clamp(1rem, .94rem + .3vw, 1.18rem); }
body[data-page="home"] #tours { background: var(--paper); }
body[data-page="home"] #cars {
  background:
    radial-gradient(circle at 92% 7%, color-mix(in srgb, var(--sea) 8%, transparent), transparent 30%),
    var(--paper-2);
}
body[data-page="home"] .tcard-media .chip { inset-block-start: 16px; inset-inline-start: 16px; }
body[data-page="home"] .tcard-body,
body[data-page="home"] .ccard-body { padding: clamp(22px, 2.5vw, 30px); }
body[data-page="home"] .band-media img { border-radius: var(--home-card-r); }
body[data-page="home"] .band--deep {
  background:
    radial-gradient(circle at 82% 25%, color-mix(in srgb, var(--sea) 20%, transparent), transparent 34%),
    linear-gradient(150deg, var(--deep-ink), var(--deep));
}
body[data-page="home"] .band-cap { border-radius: 18px; }
body[data-page="home"] .band--gold-split { background: var(--paper-3); }
body[data-page="home"] .band--gold-split .band-side--gold,
body[data-page="home"] .band-form { border-radius: var(--home-card-r); }

@media (max-width: 959px) {
  body[data-page="home"] .hero--duo { min-height: clamp(680px, 90svh, 820px); }
  body[data-page="home"] .hdr-logo img { height: 36px; }
  .hero-duo-copy { inset-inline-start: clamp(24px, 4vw, 42px); width: 77%; }
  .hero-duo-panel--discover .hero-duo-copy { inset-inline-start: clamp(76px, 10vw, 112px); width: 66%; }
  .hero-duo-title { font-size: clamp(3.55rem, 7.8vw, 5rem); }
  .hero-duo-rule { width: min(100%, 240px); }
}

@media (max-width: 759px) {
  body[data-page="home"] .hero--duo {
    grid-template-columns: 1fr;
    grid-template-rows: repeat(2, minmax(390px, 1fr));
    min-height: max(820px, 100svh);
  }
  .hero-duo-panel--discover {
    width: 100%;
    margin-inline-start: 0;
    clip-path: none;
    border-block-start: 1px solid color-mix(in srgb, var(--gold-lt) 85%, transparent);
  }
  .hero-duo-panel--drive .hero-duo-img { object-position: 58% center; }
  .hero-duo-panel--discover .hero-duo-img { object-position: 50% 52%; }
  .hero-duo-panel--drive .hero-duo-shade,
  .hero-duo-panel--discover .hero-duo-shade {
    background:
      linear-gradient(90deg, rgba(2, 32, 40, .84), rgba(2, 43, 54, .3) 84%),
      linear-gradient(0deg, rgba(2, 32, 40, .72), transparent 64%);
  }
  .hero-duo-copy,
  .hero-duo-panel--discover .hero-duo-copy {
    inset-inline: 22px auto;
    inset-block-end: 30px;
    width: min(78%, 430px);
  }
  .hero-duo-panel--drive .hero-duo-copy { inset-block-end: 34px; }
  .hero-duo-panel--discover .hero-duo-copy { inset-block-end: 70px; }
  .hero-duo-kicker { margin-block-end: 8px; font-size: clamp(9.5px, 2.9vw, 11px); }
  .hero-duo-title { font-size: clamp(3.25rem, 14vw, 4.6rem); line-height: .86; }
  .hero-duo-rule { width: min(100%, 220px); margin-block: 13px 10px; }
  .hero-duo-body { max-width: 30ch; font-size: .9rem; line-height: 1.42; }
  .hero-duo-cta { min-height: 44px; margin-block-start: 15px; padding: 10px 18px; font-size: clamp(10.5px, 3.1vw, 12px); }
  .hero-duo-seam { display: none; }
  .hero-duo-divider {
    inset-block-start: 50%;
    inset-inline-start: 50%;
    width: 48px;
    height: 48px;
  }
  .hero-duo-divider .mark { width: 26px; }
  .hero-scroll { display: none; }
}

@media (max-width: 639px) {
  body[data-page="home"] .finder { padding-block: 68px 80px; }
  body[data-page="home"] .finder-head { grid-template-columns: 1fr; gap: 10px; }
  body[data-page="home"] .finder .eyebrow { padding-block-start: 0; }
  body[data-page="home"] .finder-intro { font-size: clamp(1.65rem, 7.5vw, 2.15rem); }
  body[data-page="home"] .finder .tabs { width: 100%; }
  body[data-page="home"] .finder .tab { flex: 1 1 0; padding-inline: 8px; }
  body[data-page="home"] .finder-panels { padding: 20px 16px; border-radius: 20px; }
  body[data-page="home"] .section { padding-block: 76px; }
}

@media (prefers-reduced-motion: reduce) {
  .hero-duo-img { scale: 1 !important; transition: none; }
  .hero-scroll-dot { animation: none; }
}

/* =====================================================================
   CONSISTENT DATE PICKER

   Native date inputs remain in the document as the no-JS fallback. Once the
   lazy calendar enhancement is ready, these rules give every form the same
   trigger and the same responsive calendar instead of the browser-dependent
   popup shown by Chromium, Safari or the operating system.
   ===================================================================== */

html[data-date-ui="on"] input[type="date"].fld-in {
  -webkit-appearance: none;
  appearance: none;
  min-width: 0;
  padding-inline-end: 52px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='%23043D4C' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='5' width='18' height='16' rx='2'/%3E%3Cpath d='M8 3v4M16 3v4M3 10h18'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 21px 21px;
  cursor: pointer;
}
html[data-date-ui="on"] input[type="date"].fld-in::-webkit-calendar-picker-indicator {
  display: none;
}
html[data-date-ui="on"] input[type="date"].fld-in:focus {
  background-color: var(--paper);
}

.date-popover {
  position: fixed;
  z-index: 500;
  width: min(348px, calc(100vw - 24px));
  padding: 18px;
  border: 1px solid color-mix(in srgb, var(--line) 88%, transparent);
  border-radius: 22px;
  background: color-mix(in srgb, var(--paper) 98%, transparent);
  color: var(--deep);
  box-shadow: 0 26px 70px -26px rgba(2, 31, 39, .56), 0 8px 24px -18px rgba(2, 31, 39, .4);
  font-family: var(--font-body);
  animation: date-popover-in 180ms var(--ease-out) both;
  backdrop-filter: blur(16px);
}
.date-popover[hidden] { display: none; }
@keyframes date-popover-in {
  from { opacity: 0; translate: 0 6px; }
  to { opacity: 1; translate: 0 0; }
}
.date-popover-head {
  display: grid;
  grid-template-columns: 42px 1fr 42px;
  align-items: center;
  gap: 7px;
  margin-block-end: 14px;
}
.date-month {
  color: var(--deep);
  font-family: var(--font-display);
  font-size: 1.2rem;
  font-weight: 600;
  line-height: 1.2;
  text-align: center;
}
.date-nav {
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0 0 3px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--paper-2);
  color: var(--deep);
  font: 400 1.8rem/1 var(--font-body);
  cursor: pointer;
  transition: background-color var(--t-hover) ease, border-color var(--t-hover) ease, color var(--t-hover) ease;
}
.date-nav:disabled { opacity: .3; cursor: not-allowed; }
/* Each week is its own row element (a gridcell needs a row around it), so the
   seven columns are set per row, as .cal-row does. */
.date-days { display: grid; gap: 3px; }
.date-row {
  display: grid;
  grid-template-columns: repeat(7, minmax(0, 1fr));
  column-gap: 2px;
}
.date-row--head {
  margin-block-end: 2px;
  color: var(--muted);
  font-size: 10px;
  font-weight: 700;
  letter-spacing: .09em;
  text-align: center;
  text-transform: uppercase;
}
.date-wd { padding-block: 7px; }
.date-day {
  position: relative;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  margin: auto;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: transparent;
  color: var(--deep);
  font: 600 13px/1 var(--font-body);
  font-variant-numeric: tabular-nums;
  cursor: pointer;
  transition: background-color var(--t-hover) ease, color var(--t-hover) ease, box-shadow var(--t-hover) ease;
}
.date-day--outside { color: var(--muted); opacity: .56; }
.date-day:disabled { color: var(--muted); opacity: .25; cursor: not-allowed; }
.date-day--today:not(.date-day--selected) {
  color: var(--gold-ink);
  box-shadow: inset 0 0 0 1px var(--gold);
}
.date-day--range:not(.date-day--selected) {
  border-radius: 10px;
  background: color-mix(in srgb, var(--gold-lt) 34%, var(--paper));
}
.date-day--range-start:not(.date-day--selected),
.date-day--range-end:not(.date-day--selected) {
  background: color-mix(in srgb, var(--gold-lt) 58%, var(--paper));
  color: var(--deep);
}
.date-day--selected {
  background: var(--deep);
  color: #fff;
  box-shadow: 0 8px 18px -10px rgba(2, 43, 54, .9);
}
.date-popover-foot {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  margin-block-start: 13px;
  padding-block-start: 13px;
  border-block-start: 1px solid var(--line);
}
.date-quick {
  min-height: 40px;
  padding: 8px 13px;
  border: 0;
  border-radius: var(--r-pill);
  background: transparent;
  color: var(--deep);
  font: 600 12px/1 var(--font-body);
  cursor: pointer;
}
.date-quick--today { background: color-mix(in srgb, var(--gold-lt) 38%, var(--paper)); }
.date-quick:disabled { opacity: .32; cursor: not-allowed; }

@media (hover: hover) and (pointer: fine) {
  .date-nav:not(:disabled):hover { border-color: var(--deep); background: var(--deep); color: #fff; }
  .date-day:not(:disabled):hover { background: color-mix(in srgb, var(--gold-lt) 50%, var(--paper)); color: var(--deep); }
  .date-day--selected:not(:disabled):hover { background: var(--deep-ink); color: #fff; }
  .date-quick:not(:disabled):hover { background: color-mix(in srgb, var(--gold-lt) 48%, var(--paper)); }
}

@media (max-width: 639px) {
  .date-popover {
    inset: auto 12px max(12px, env(safe-area-inset-bottom)) 12px !important;
    width: auto;
    max-height: calc(100svh - 24px - env(safe-area-inset-bottom));
    padding: 18px clamp(14px, 5vw, 22px);
    overflow-y: auto;
    border-radius: 24px;
  }
  /* The track is (0.9vw - 36) / 7, so a fixed 42px circle only fits from about
     367px up; at 320px each one overlapped its neighbours by 4.2px (measured)
     and the tap targets collided. Cap it by the track instead. */
  .date-day { width: min(42px, 100%); height: auto; aspect-ratio: 1; font-size: 14px; }
}

@media (prefers-reduced-motion: reduce) {
  .date-popover { animation: none; }
}

/* =====================================================================
   HOME POLISH PASS 2 — texture, brand watermarks, entrance and drift.

   Everything here is additive and lives at the end of the file on purpose:
   the rules re-declare full background stacks for surfaces defined above,
   and end-of-file order is what lets them win without extra specificity.

   The house motion rules still hold (HANDOVER §"motion"):
   1. Nothing loops forever — the hero entrance runs once, and the drift is
      scroll-driven, so it only moves while the reader does.
   2. The hero PHOTO never animates opacity (LCP); only the copy enters.
   3. Anything on a [data-reveal] element composes via a different property
      than the reveal's `translate` (the drift is `transform`, the overlap
      is `top`).
   ===================================================================== */

:root {
  /* Film grain, ~5% alpha, and the brand horizon as tone-on-tone watermarks.
     Encoded like the calendar icon above: <, > and # only. */
  --noise: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='.05'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
  --horizon-deep: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 54 19' fill='none' stroke='%23043D4C' stroke-linecap='round' opacity='.07'%3E%3Cpath d='M8 13.2A26 26 0 0 1 46 13.2' stroke-width='.6'/%3E%3Cpath d='M0 15.8q13.5-4 27 0t27 0' stroke-width='.6'/%3E%3C/svg%3E");
  --horizon-gold: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 54 19' fill='none' stroke='%23E9C174' stroke-linecap='round' opacity='.08'%3E%3Cpath d='M8 13.2A26 26 0 0 1 46 13.2' stroke-width='.6'/%3E%3Cpath d='M0 15.8q13.5-4 27 0t27 0' stroke-width='.6'/%3E%3C/svg%3E");
}

/* --- flat bands get light, grain and the horizon ---------------------- */
body[data-page="home"] .finder {
  background:
    var(--noise),
    var(--horizon-deep) no-repeat right -70px bottom -30px / 560px auto,
    radial-gradient(120% 90% at 10% -10%, rgba(255, 255, 255, .5), transparent 55%),
    linear-gradient(135deg, var(--gold-lt), color-mix(in srgb, var(--gold-lt) 58%, var(--cream)));
}
body[data-page="home"] .band--deep {
  background:
    var(--noise),
    var(--horizon-gold) no-repeat left -90px top 30px / 640px auto,
    radial-gradient(circle at 82% 25%, color-mix(in srgb, var(--sea) 22%, transparent), transparent 36%),
    linear-gradient(150deg, var(--deep-ink), var(--deep));
}
body[data-page="home"] .band--gold-split .band-side--gold {
  background:
    var(--noise),
    var(--horizon-deep) no-repeat right -46px bottom -18px / 380px auto,
    linear-gradient(160deg, var(--gold-lt), color-mix(in srgb, var(--gold-lt) 55%, var(--cream)));
}

/* --- the assurance strip that closes the finder band ------------------- */
.proof {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3) var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid color-mix(in srgb, var(--deep) 18%, transparent);
}
.proof-it {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--deep);
  font-size: var(--fs-small);
  font-weight: 600;
}
.proof-ic { display: inline-flex; color: var(--gold-ink); }
.proof-ic svg { width: 17px; height: 17px; }

/* --- solid header: frosted deep instead of a flat slab ----------------- */
@supports ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .hdr--solid {
    background: color-mix(in srgb, var(--deep) 86%, transparent);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
  }
}

/* --- hero copy enters once; the photo (LCP) never animates ------------- */
@media (prefers-reduced-motion: no-preference) {
  .hero-duo-panel--discover { --hero-d: 140ms; }
  .hero-duo-kicker, .hero-duo-title, .hero-duo-body, .hero-duo-cta {
    animation: hero-rise 760ms var(--ease-out) backwards;
  }
  .hero-duo-kicker { animation-delay: calc(var(--hero-d, 0ms) + 160ms); }
  .hero-duo-title { animation-delay: calc(var(--hero-d, 0ms) + 240ms); }
  .hero-duo-rule {
    transform-origin: left;
    animation: hero-draw 900ms var(--ease-out) backwards;
    animation-delay: calc(var(--hero-d, 0ms) + 380ms);
  }
  .hero-duo-body { animation-delay: calc(var(--hero-d, 0ms) + 430ms); }
  .hero-duo-cta { animation-delay: calc(var(--hero-d, 0ms) + 520ms); }
}
@keyframes hero-rise { from { opacity: 0; translate: 0 16px; } }
@keyframes hero-draw { from { scale: 0 1; } }

/* --- band photos drift against their copy while scrolled past ---------- */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .band-media {
      animation: band-drift linear both;
      animation-timeline: view();
      animation-range: entry 10% exit 90%;
    }
    @keyframes band-drift {
      from { transform: translateY(26px); }
      to { transform: translateY(-26px); }
    }
  }
}

/* --- the photos break their band's edge on desktop ---------------------
   The offsets have to clear the section's own top padding (~76-128px)
   before the photo visibly crosses the boundary; `top` moves the paint,
   not the layout, so the band keeps its height and nothing below shifts. */
@media (min-width: 960px) {
  /* align-self: start removes the centering gap that would otherwise eat
     the offset (the text column is the taller grid item). */
  body[data-page="home"] .band--deep .band-media {
    align-self: start;
    top: clamp(-196px, -13.5vw, -128px);
  }
  body[data-page="home"] .band-media img {
    box-shadow: 0 32px 80px -42px rgba(2, 31, 39, .5);
  }
}
