  /*
    Direction A / B shared brand system
    Palette and typography are committed as a single, unique brand identity for this client
    (no light/dark toggle tied to the visitor's OS theme: a brand showcase site
    does not re-theme itself to its visitor's system, exactly as the real site
    will not). All colours are set explicitly so the page holds on
    any host background.
  */

  :root{
    --ink:#0D2B26;
    --ink-2:#123A33;
    --teal:#1F6F63;
    --teal-2:#2C8577;
    --teal-text:#155850; /* darker than --teal specifically for text-on-sand, keeps AA contrast */
    --sand:#F3EEDD;
    --sand-2:#E9E0C7;
    --sand-ink:#4C5F58;
    --coral:#E2794F;
    --coral-2:#C96038;
    --cream:#FBF7EE;
    --cream-2:#C3D0C9;
    --line-light:rgba(13,43,38,.14);
    --line-dark:rgba(251,247,238,.16);
    --wa:#25D366;
    --wa-2:#1DA851;
    --success:#2F8F5B;
    --warning:#C98A2E;
    --error:#C24F3D;
    --focus-light:#0D2B26;
    --focus-dark:#FBF7EE;

    --sp-1:.25rem; --sp-2:.5rem; --sp-3:.75rem; --sp-4:1rem; --sp-5:1.5rem;
    --sp-6:2rem; --sp-7:3rem; --sp-8:4.5rem; --sp-9:7rem;

    --radius-sm:3px; --radius-pill:999px;
    --shadow-1:0 8px 24px -8px rgba(13,43,38,.35);
    --ease:cubic-bezier(.22,.7,.22,1);
    --dur-s:.2s; --dur-m:.5s; --dur-l:.8s;

    --header-h:76px;
    color-scheme: light;
    background:var(--sand);
  }

  *,*::before,*::after{box-sizing:border-box}
  /* Smooth in-page scrolling (anchor links, back-to-top) on every viewport.
     Mobile has no scroll-snap at all below 761px (see the next rule), so
     there's nothing to conflict with there. On desktop/tablet it runs
     alongside scroll-snap-type without issue for real anchor-link
     navigation — the known browser bugs in this combination are narrow
     (a Firefox/Windows case specific to JS-driven carousel button clicks,
     already fixed by default in current Firefox) and don't apply to a
     plain full-page vertical snap + <a href="#section"> jump. Turned off
     under prefers-reduced-motion below, same as scroll-snap itself. */
  html{scroll-behavior:smooth}
  /* Scroll-snap is the site's signature on desktop/tablet, but several sections
     (reviews, footer, the services/route/fleet grids) genuinely hold more
     content than fits one phone screen at real body-copy sizes — forcing a
     100vh snap there would mean shrinking type past comfortable reading size
     or hiding real content. Below 761px, sections scroll normally instead;
     each still opens near full-screen (min-height:100svh, untouched), it just
     isn't snap-locked to that height. Tablets and up keep the full treatment. */
  @media (min-width:761px){
    html.snap-page{scroll-snap-type:y mandatory; scroll-padding-top:0;}
  }
  body{margin:0;background:var(--sand);color:var(--ink);
    font-family:'Work Sans',ui-sans-serif,system-ui,-apple-system,sans-serif;
    -webkit-font-smoothing:antialiased;}
  h1,h2,h3{font-family:'Fraunces',ui-serif,Georgia,serif; margin:0; text-wrap:balance; font-weight:600;}
  p{margin:0}
  a{color:inherit}
  img,svg{max-width:100%; display:block}
  button{font:inherit; color:inherit; background:none; border:0; cursor:pointer}

  .visually-hidden{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}

  .skip-link{position:fixed; top:-100%; left:var(--sp-4); z-index:200;
    background:var(--ink); color:var(--cream); padding:var(--sp-3) var(--sp-5);
    border-radius:var(--radius-sm); transition:top var(--dur-s) var(--ease);}
  .skip-link:focus{top:var(--sp-4)}

  :focus-visible{outline:3px solid var(--focus-light); outline-offset:3px}
  .slide--dark :focus-visible{outline-color:var(--focus-dark)}

  /* ---------- header ---------- */
  .site-header{position:fixed; inset:0 0 auto 0; height:var(--header-h); z-index:100;
    display:flex; align-items:center; background:rgba(243,238,221,.82);
    backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
    border-bottom:1px solid var(--line-light);}
  .header-inner{width:100%; max-width:1400px; margin:0 auto; padding:0 var(--sp-6);
    display:grid; grid-template-columns:auto 1fr auto; align-items:center; gap:var(--sp-4);}
  .logo{display:flex; align-items:center; gap:var(--sp-3); text-decoration:none; color:var(--ink);}
  .logo-mark{width:34px; height:34px; flex:none}
  .logo-word{font-family:'Fraunces',serif; font-weight:600; font-size:.95rem; line-height:1.15}
  .header-actions{display:flex; align-items:center; gap:var(--sp-5); justify-self:end}

  /* ---------- primary nav (visible bar on tablet/desktop; hamburger below) ---------- */
  .header-nav{display:none}
  @media (min-width:900px){
    .header-nav{display:flex; align-items:center; justify-content:center; gap:var(--sp-6); justify-self:center}
    .header-nav a{text-decoration:none; font-family:'Work Sans',sans-serif; font-weight:600;
      font-size:.88rem; color:var(--sand-ink); padding:.3rem .05rem; white-space:nowrap;
      border-bottom:2px solid transparent; transition:color var(--dur-s) var(--ease), border-color var(--dur-s) var(--ease);}
    .header-nav a:hover,.header-nav a:focus-visible{color:var(--ink)}
    .header-nav a[aria-current="page"],.header-nav a.is-active-section{color:var(--ink); border-bottom-color:var(--ink)}
    .header-actions .menu-btn{display:none}
  }
  .lang-toggle{display:flex; border:1px solid var(--line-light); border-radius:var(--radius-pill); padding:3px;}
  .lang-btn{padding:.35rem .75rem; border-radius:var(--radius-pill); font-size:.8rem; font-weight:600;
    letter-spacing:.02em; color:var(--sand-ink); text-decoration:none; display:inline-block; line-height:1.2;
    transition:background var(--dur-s) var(--ease), color var(--dur-s) var(--ease);}
  a.lang-btn:hover,a.lang-btn:focus-visible{color:var(--ink)}
  .lang-btn.is-active{background:var(--ink); color:var(--cream)}
  .menu-btn{display:flex; align-items:center; gap:var(--sp-2); padding:.5rem; border-radius:var(--radius-sm);}
  .menu-btn-bars{position:relative; width:22px; height:14px; display:inline-block;}
  .menu-btn-bars::before,.menu-btn-bars::after{content:"";position:absolute; left:0; right:0; height:2px;
    background:var(--ink); transition:transform var(--dur-s) var(--ease), top var(--dur-s) var(--ease);}
  .menu-btn-bars::before{top:0}
  .menu-btn-bars::after{top:12px}
  .menu-btn-bars span{position:absolute; top:6px; left:0; right:0; height:2px; background:var(--ink);}
  .menu-btn[aria-expanded="true"] .menu-btn-bars::before{top:6px; transform:rotate(45deg)}
  .menu-btn[aria-expanded="true"] .menu-btn-bars::after{top:6px; transform:rotate(-45deg)}
  .menu-btn[aria-expanded="true"] .menu-btn-bars span{opacity:0}

  /* ---------- off-canvas menu ---------- */
  .site-menu{position:fixed; inset:0; z-index:150; background:var(--ink); color:var(--cream);
    display:flex; flex-direction:column; align-items:flex-start; justify-content:center;
    padding:var(--sp-8) var(--sp-7);
    transform:translateX(100%); transition:transform var(--dur-m) var(--ease);}
  .site-menu[data-open="true"]{transform:translateX(0)}
  .menu-close{position:absolute; top:var(--sp-5); right:var(--sp-6); font-size:2rem; line-height:1; padding:var(--sp-2) var(--sp-3);}
  .menu-logo{width:56px; height:56px; margin-bottom:var(--sp-6); opacity:.92}
  .site-menu ul{list-style:none; margin:0; padding:0; display:flex; flex-direction:column; gap:var(--sp-3)}
  .site-menu a{text-decoration:none; font-family:'Fraunces',serif; font-weight:500;
    font-size:clamp(2rem,6vw,3.5rem); color:var(--cream); display:inline-block;
    border-bottom:2px solid transparent; transition:border-color var(--dur-s) var(--ease), opacity var(--dur-s) var(--ease);}
  .site-menu a:hover,.site-menu a:focus-visible{border-color:var(--coral)}
  .site-menu a[aria-current="page"],.site-menu a.is-active-section{border-bottom-color:var(--ink); opacity:1}

  /* ---------- slides ---------- */
  .snap-container{position:relative}
  .slide{position:relative; min-height:100svh; padding:calc(var(--header-h) + var(--sp-8)) var(--sp-6) var(--sp-8);
    scroll-snap-align:start; scroll-snap-stop:always;
    display:flex; flex-direction:column; justify-content:center; overflow:hidden;}
  .slide-hero{min-height:100svh}
  /* Tighten the home hero's own box (padding/margins only, never font-size)
     so its natural content height matches 100svh on real desktop/laptop
     viewports (768–900px tall is the common range) instead of overflowing
     it — keeps the scroll-snap "one screen per section" rhythm intact. */
  #hero.slide-hero{padding-top:calc(var(--header-h) + var(--sp-6)); padding-bottom:var(--sp-6)}
  #hero .photo-card{padding-top:var(--sp-6); padding-bottom:var(--sp-6)}
  #hero .hero-eyebrow{margin-bottom:var(--sp-3)}
  #hero .hero-lead{margin-top:var(--sp-4)}
  #hero .hero-ctas{margin-top:var(--sp-5)}
  /* Same principle for the "Get in touch + footer" slide: trim the box
     (top padding, block gaps, footer paddings) rather than type, so the
     whole CTA + footer fits one screen instead of spilling past it —
     this was the section with the most unused vertical slack. */
  .slide--final{padding-top:calc(var(--header-h) + var(--sp-6)); padding-bottom:20px}
  .slide--light{background:var(--sand); color:var(--ink)}
  .slide--dark{background:var(--ink); color:var(--cream)}
  .slide-inner{width:100%; max-width:1400px; margin:0 auto; position:relative; z-index:2}
  .prose-narrow{max-width:42rem}
  .prose-narrow h2{font-family:'Fraunces',serif; font-weight:600; font-size:clamp(2rem,1.6vw + 1.6rem,2.8rem); line-height:1.1}
  /* Was ">p" (direct-child), which never matched: the heading and
     paragraph both sit inside a ".reveal" wrapper for the scroll-in
     animation, so they're grandchildren of .prose-narrow, not direct
     children — the intro paragraph silently lost its top margin. */
  .prose-narrow p{margin-top:var(--sp-5); line-height:1.65; font-size:1.05rem; color:var(--sand-ink)}
  .prose-narrow .stat-line{margin-top:var(--sp-6)}
  .prose-narrow .stat-line b{color:var(--ink)}
  .ta-logo{flex:none}
  .ta-credibility{display:flex; align-items:center; gap:var(--sp-4); margin-top:var(--sp-6)}
  .ta-credibility b{display:block; font-family:'Fraunces',serif; font-weight:600; font-size:1.05rem; color:var(--ink)}
  .ta-credibility span{display:block; margin-top:.2rem; font-size:.82rem; color:var(--sand-ink)}
  .hero-badges{display:flex; flex-wrap:wrap; gap:var(--sp-3)}
  .hero-award{display:inline-flex; align-items:center; gap:.65rem; text-decoration:none;
    transition:transform var(--dur-s) var(--ease), opacity var(--dur-s) var(--ease); opacity:.96}
  .hero-award:hover,.hero-award:focus-visible{transform:translateY(-2px); opacity:1}
  .hero-award img{display:block; flex:none; width:34px; height:auto}
  .hero-award span{font-family:'Work Sans',sans-serif; font-weight:700; font-size:.8rem;
    line-height:1.3; letter-spacing:.01em; color:#fff; text-shadow:0 1px 6px rgba(13,43,38,.6);}
  @media (max-width:560px){
    .ta-credibility{gap:var(--sp-3)}
    .ta-credibility svg{width:38px; height:38px}
    .hero-award img{width:28px}
    .hero-award span{font-size:.74rem}
  }

  /* ---------- service / fleet cards (Kayak Expedition page) ---------- */
  .section-head{max-width:38rem; margin:0 0 var(--sp-8)}
  .section-head h1,.section-head h2{font-family:'Fraunces',serif; font-weight:600; font-size:clamp(2rem,1.6vw + 1.6rem,2.8rem); line-height:1.1}
  .section-head p{margin-top:var(--sp-4); font-size:1.05rem; line-height:1.6; color:var(--sand-ink)}
  .service-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:var(--sp-5)}
  .service-card{position:relative; overflow:hidden; border-radius:var(--radius-sm); min-height:320px;
    display:flex; align-items:flex-end; isolation:isolate;
    transition:transform var(--dur-m) var(--ease), box-shadow var(--dur-m) var(--ease);}
  .service-card:hover,.service-card:focus-within{transform:translateY(-3px); box-shadow:var(--shadow-1)}
  .service-card-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0;
    transition:transform var(--dur-l) var(--ease);}
  .service-card:hover .service-card-img,.service-card:active .service-card-img,
  .service-card:focus-within .service-card-img{transform:scale(1.06)}
  .service-card-overlay{position:absolute; inset:0; z-index:1; background:rgba(13,43,38,.65)}
  /* Not-yet-photographed services (hiking, table d'hôte): same card shape and
     text treatment, a plain brand-ink gradient standing in for the photo
     until one is supplied — never a wrong or generic stock image. */
  .service-card--placeholder{background:linear-gradient(160deg,var(--ink-2),var(--ink))}
  .service-card-body{position:relative; z-index:2; padding:var(--sp-6) var(--sp-5); width:100%}
  .service-card-body h3{font-family:'Fraunces',serif; font-weight:600;
    font-size:clamp(1.5rem,1.4vw + 1.2rem,1.9rem); color:var(--cream)}
  .service-card-body p{margin-top:var(--sp-2); font-size:.92rem; line-height:1.55; color:#fff}

  .private-band{background:var(--ink); color:var(--cream); border-radius:var(--radius-sm);
    padding:var(--sp-7) var(--sp-6); display:flex; flex-wrap:wrap; align-items:center; justify-content:flex-start; gap:var(--sp-6);
    margin-top:var(--sp-8); max-width:1100px; padding-right:calc(var(--sp-6) + 8rem);}
  .private-band h3{font-family:'Fraunces',serif; font-weight:600; font-size:clamp(1.5rem,1.2vw + 1.2rem,2rem); max-width:26ch}
  .private-band p{margin-top:var(--sp-3); color:var(--cream-2); max-width:42ch; line-height:1.6}

  .fleet-grid{display:grid; grid-template-columns:repeat(auto-fit,minmax(240px,1fr)); gap:var(--sp-5); margin-top:var(--sp-8)}
  .fleet-card{border:1px solid var(--line-light); border-radius:var(--radius-sm); overflow:hidden; background:var(--cream)}
  .fleet-photo{aspect-ratio:5/2; width:100%; background:linear-gradient(135deg,var(--sand-2),var(--cream-2));
    display:flex; align-items:center; justify-content:center; color:var(--sand-ink); font-size:.75rem;
    text-transform:uppercase; letter-spacing:.08em; text-align:center; padding:var(--sp-4);}
  .fleet-photo img{width:100%; height:100%; object-fit:contain; object-position:center}
  .fleet-card .fleet-body{padding:var(--sp-5)}
  .fleet-card h3{font-family:'Work Sans',sans-serif; font-weight:700; font-size:.82rem;
    text-transform:uppercase; letter-spacing:.06em; color:var(--teal-text)}
  .fleet-card p{margin-top:var(--sp-3); font-size:.9rem; color:var(--sand-ink); line-height:1.5}

  @media (max-width:640px){
    .private-band{flex-direction:column; align-items:flex-start; padding-right:var(--sp-6); max-width:100%; margin-bottom:calc(var(--sp-7) + 3.5rem)}
  }

  /* ---------- route / itinerary stepper ---------- */
  .route-block{margin-top:var(--sp-8)}
  .route-block:first-of-type{margin-top:var(--sp-7)}
  .route-head{display:flex; align-items:baseline; justify-content:space-between; gap:var(--sp-4); flex-wrap:wrap}
  .route-head h3{font-family:'Fraunces',serif; font-weight:600; font-size:1.3rem}
  .route-duration{font-size:.72rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase; color:var(--teal-text);
    padding:.3rem .8rem; border:1px solid var(--teal-text); border-radius:var(--radius-pill); flex:none;}

  .route-upsell{margin-top:var(--sp-6); padding:var(--sp-5); border:1px solid var(--line-light); border-radius:var(--radius-sm);
    display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:var(--sp-4);}
  .route-upsell p{max-width:52ch; line-height:1.5}
  .route-upsell strong{font-family:'Fraunces',serif; font-weight:600}

  /* ---------- route stepper: wavy photo-stop path ----------
     An S-curve line connects each stop's photo, alternating above/below
     the path (.wave-stop--up / --down) so labels never collide with the
     line or with neighbouring stops. Flat site palette throughout — the
     ring colour alternates teal/coral per stop via the --ring custom
     property set inline on each .wave-stop. Collapses to a plain
     vertical stack below 640px (see media query). */
  .wave-stepper{position:relative; width:100%; max-width:none; margin:var(--sp-5) auto 0; aspect-ratio:760/340}
  .wave-stepper-line{position:absolute; inset:0; width:100%; height:100%; overflow:visible}
  .wave-stepper-line path{fill:none; stroke:var(--line-light); stroke-width:3; stroke-linecap:round}
  .wave-stop{position:absolute; display:flex; flex-direction:column; align-items:center; gap:.5rem;
    width:200px; text-align:center; left:calc(var(--x) / 760 * 100%); top:calc(var(--y) / 340 * 100%);
    transform:translate(-50%,-50%)}
  .wave-photo{width:150px; height:150px; border-radius:50%; overflow:hidden; flex:none;
    border:5px solid var(--ring, var(--teal)); box-shadow:0 8px 18px -6px rgba(13,43,38,.4); background:var(--sand-2)}
  .wave-photo img{width:100%; height:100%; object-fit:cover; display:block}
  .wave-pin{width:2px; height:22px; background:var(--line-light); flex:none}
  .wave-label{font-size:1.05rem; line-height:1.3; font-weight:600; color:var(--ink)}
  .wave-label span{display:block; font-weight:400; color:var(--sand-ink); font-size:.85rem; margin-top:.15rem}
  @media (max-width:640px){
    /* No room for a wide wave at phone widths — fall back to a plain
       vertical stack of photo + label, connected by a straight line. */
    .wave-stepper{aspect-ratio:auto; max-width:280px; display:flex; flex-direction:column; align-items:center; gap:0}
    .wave-stepper-line{display:none}
    .wave-stop{position:static; transform:none; width:100%}
    /* Force photo-then-label reading order regardless of --up/--down source
       order (that markup order matters only for the desktop wave, where it
       controls whether the label sits above or below its circle). */
    .wave-photo{order:1; width:88px; height:88px; border-width:4px}
    .wave-pin{display:none}
    .wave-label{order:2; font-size:.78rem}
    .wave-label span{font-size:.72rem}
    .wave-stop:not(:last-child)::after{content:""; display:block; order:3; width:2px; height:22px; background:var(--line-light); margin:.3rem 0}
  }

  /* ---------- gallery grid + lightbox ----------
     Editorial, uneven rhythm instead of a uniform photo-grid: a dense CSS grid
     with a handful of tiles spanning extra columns/rows (assigned by gallery.js
     via a deterministic pattern), so the wall reads like a curated spread
     rather than a generic thumbnail wall. Collapses to a plain 2-column grid
     on small screens, where an irregular masonry reads as cramped/broken. */
  .gallery-grid{display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); grid-auto-rows:130px;
    grid-auto-flow:dense; gap:var(--sp-4); margin-top:var(--sp-7)}
  .gallery-tile{position:relative; grid-row:span 2; border-radius:var(--radius-sm); overflow:hidden;
    border:1px solid var(--line-light); background:none; padding:0; cursor:pointer;
    opacity:0; transform:translateY(14px); transition:opacity var(--dur-l) var(--ease), transform var(--dur-l) var(--ease);}
  .gallery-tile--wide{grid-column:span 2}
  .gallery-tile--tall{grid-row:span 3}
  .gallery-tile--big{grid-column:span 2; grid-row:span 3}
  @media (max-width:640px){
    .gallery-grid{grid-template-columns:repeat(2,1fr); grid-auto-rows:120px}
    .gallery-tile, .gallery-tile--wide, .gallery-tile--tall, .gallery-tile--big{grid-column:span 1; grid-row:span 2}
  }
  .gallery-tile.is-shown{opacity:1; transform:none}
  .gallery-tile .tile-img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
    opacity:1; transition:transform var(--dur-m) var(--ease), opacity var(--dur-m) var(--ease);}
  .gallery-tile:hover .tile-img, .gallery-tile:focus-visible .tile-img{transform:scale(1.04)}
  .gallery-tile .tile-play{position:absolute; top:50%; left:50%; width:44px; height:44px;
    transform:translate(-50%,-50%); pointer-events:none; opacity:1; transition:opacity var(--dur-s) var(--ease);}
  .gallery-tile .tile-caption{position:absolute; left:0; right:0; bottom:0; padding:var(--sp-3) var(--sp-3) var(--sp-2);
    background:linear-gradient(to top, rgba(6,20,18,.78), rgba(6,20,18,0));
    color:var(--cream); font-size:.72rem; letter-spacing:.01em; text-align:left; line-height:1.3;
    opacity:0; transform:translateY(6px); transition:opacity var(--dur-m) var(--ease), transform var(--dur-m) var(--ease);}
  .gallery-tile:hover .tile-caption, .gallery-tile:focus-visible .tile-caption{opacity:1; transform:none}
  /* Per-tile skeleton: each tile is inserted already sized (same span
     classes as the final layout, so nothing reflows) and carries .is-loading
     until its own thumbnail reports load/error — a YouTube-style shimmer
     block rather than a single spinner row floating below the grid. Removed
     the moment gallery.js detects the image is ready. */
  .gallery-tile.is-loading .tile-img{opacity:0}
  .gallery-tile.is-loading .tile-play{opacity:0}
  .gallery-tile.is-loading::before,
  .gallery-tile.is-loading::after{content:""; position:absolute; inset:0; pointer-events:none;}
  .gallery-tile.is-loading::before{background:var(--line-light)}
  .gallery-tile.is-loading::after{
    background:linear-gradient(100deg, transparent 32%, rgba(255,255,255,.6) 50%, transparent 68%);
    background-size:200% 100%; animation:tile-shimmer 1.6s ease-in-out infinite;}
  @keyframes tile-shimmer{0%{background-position:160% 0} 100%{background-position:-60% 0}}
  @media (prefers-reduced-motion: reduce){
    .gallery-tile.is-loading::after{animation:none; background-position:50% 0}
  }
  .gallery-sentinel{height:1px}

  .lightbox{position:fixed; inset:0; z-index:300; background:rgba(6,20,18,.92);
    display:flex; align-items:center; justify-content:center; opacity:0; pointer-events:none;
    transition:opacity var(--dur-m) var(--ease);}
  .lightbox[data-open="true"]{opacity:1; pointer-events:auto}
  .lightbox-frame{position:relative; display:flex; flex-direction:column; align-items:center;
    max-width:94vw; max-height:90vh; gap:var(--sp-3); padding:0 var(--sp-7);}
  .lightbox-media{display:flex; align-items:center; justify-content:center; max-width:100%; max-height:78vh;}
  .lightbox-media img, .lightbox-media video{display:block; max-width:min(1100px,84vw); max-height:78vh;
    width:auto; height:auto; border-radius:var(--radius-sm); box-shadow:0 24px 60px -12px rgba(0,0,0,.5);}
  /* Fluid 16:9 box instead of the embed's fixed 560x315 markup — width
     capped to match photos/video, height follows from the aspect ratio so
     it never blows past the lightbox's own 78vh ceiling. */
  .lightbox-youtube{position:relative; width:min(1100px,84vw); max-height:78vh; aspect-ratio:16/9;
    border-radius:var(--radius-sm); overflow:hidden; box-shadow:0 24px 60px -12px rgba(0,0,0,.5);}
  .lightbox-youtube iframe{position:absolute; inset:0; display:block; width:100%; height:100%; border:0}
  .lightbox-caption{margin:0; color:var(--cream); font-size:.88rem; text-align:center; max-width:60ch}
  .lightbox-close, .lightbox-prev, .lightbox-next{position:fixed; background:rgba(13,43,38,.7); color:var(--cream);
    border:none; border-radius:var(--radius-pill); width:44px; height:44px; display:flex; align-items:center; justify-content:center;
    cursor:pointer; z-index:301;}
  .lightbox-close{top:var(--sp-5); right:var(--sp-5)}
  .lightbox-prev{left:var(--sp-5); top:50%; transform:translateY(-50%)}
  .lightbox-next{right:var(--sp-5); top:50%; transform:translateY(-50%)}
  @media (max-width:640px){
    .lightbox-frame{padding:0 var(--sp-5)}
    .lightbox-media img, .lightbox-media video{max-width:92vw}
    .lightbox-youtube{width:92vw}
    .lightbox-close{top:var(--sp-4); right:var(--sp-4)}
    .lightbox-prev{left:var(--sp-3)}
    .lightbox-next{right:var(--sp-3)}
  }

  /* ---------- contact page ---------- */
  .contact-grid{display:grid; grid-template-columns:1.1fr .9fr; gap:var(--sp-8); align-items:start; margin-top:var(--sp-7)}

  .contact-form{display:grid; grid-template-columns:1fr 1fr; gap:var(--sp-5); background:var(--cream);
    border:1px solid var(--line-light); border-radius:var(--radius-sm); padding:var(--sp-7);}
  /* An author rule setting `display` always beats the browser's built-in
     [hidden]{display:none} default, regardless of selector specificity —
     so .contact-form's own display:grid above silently cancelled the
     [hidden] attribute assets/contact.js sets after a successful submit.
     This explicit override (higher specificity than .contact-form alone)
     is what actually makes that hide work. */
  .contact-form[hidden]{display:none}
  .contact-form-kicker{grid-column:1/-1; font-size:.72rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
    color:var(--teal-text); margin-bottom:calc(var(--sp-2) * -1)}
  .form-field{display:flex; flex-direction:column; gap:.4rem}
  .form-field--full{grid-column:1/-1}
  .form-field label{font-size:.82rem; font-weight:600; letter-spacing:.02em}
  .form-field input, .form-field textarea, .form-field select{font:inherit; font-size:1rem; padding:.85rem 1rem; border-radius:var(--radius-sm);
    border:1.5px solid var(--line-light); background:var(--sand); color:var(--ink); width:100%;
    transition:border-color var(--dur-s) var(--ease), box-shadow var(--dur-s) var(--ease);}
  .form-field input:focus, .form-field textarea:focus, .form-field select:focus{outline:none; border-color:var(--teal-text); box-shadow:0 0 0 3px rgba(21,88,80,.14)}
  .form-field textarea{resize:vertical; min-height:7rem}
  .form-field .hint{font-size:.78rem; color:var(--sand-ink)}
  .form-field .field-error{font-size:.8rem; color:var(--error); min-height:1.1em}

  /* native select: browser chrome swapped for a chevron that matches the
     rest of the icon set, since the default arrow doesn't sit well on the
     sand background. */
  .form-field select{appearance:none; -webkit-appearance:none; -moz-appearance:none;
    padding-right:2.6rem; cursor:pointer;
    background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 24 24' fill='none'%3E%3Cpath d='M6 9l6 6 6-6' stroke='%23155850' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
    background-repeat:no-repeat; background-position:right 1rem center; background-size:16px;}
  .form-field select:invalid{color:var(--sand-ink)}

  /* ---------- custom date picker ----------
     Base state (no JS): the real <input type="date"> is shown and styled
     like any other field, so the browser's own picker still works. Once
     datepicker.js runs, it adds .is-enhanced to the wrapper, which visually
     hides the native input (kept in the DOM so its value still submits with
     the form) and swaps in the styled trigger + panel below. */
  .date-picker{position:relative}
  .date-picker .date-trigger, .date-picker .date-panel{display:none}
  .date-picker.is-enhanced .date-native{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
    overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}
  .date-picker.is-enhanced .date-trigger{display:flex; align-items:center; justify-content:space-between; gap:.75rem;
    width:100%; font:inherit; font-size:1rem; text-align:left; padding:.85rem 1rem; border-radius:var(--radius-sm);
    border:1.5px solid var(--line-light); background:var(--sand); color:var(--ink); cursor:pointer;
    transition:border-color var(--dur-s) var(--ease), box-shadow var(--dur-s) var(--ease);}
  .date-picker.is-enhanced .date-trigger:hover{border-color:var(--teal-2)}
  .date-picker.is-enhanced .date-trigger:focus-visible, .date-picker.is-enhanced .date-trigger[aria-expanded="true"]{
    outline:none; border-color:var(--teal-text); box-shadow:0 0 0 3px rgba(21,88,80,.14)}
  .date-trigger-text{color:var(--sand-ink)}
  .date-trigger.has-value .date-trigger-text{color:var(--ink); font-weight:500}
  .date-trigger-icon{flex:none; color:var(--teal-text)}

  .date-panel{position:absolute; z-index:20; top:calc(100% + .5rem); left:0; width:min(320px,100%);
    background:var(--cream); border:1px solid var(--line-light); border-radius:var(--radius-sm);
    box-shadow:var(--shadow-1); padding:var(--sp-4); opacity:0; transform:translateY(-6px);
    transition:opacity var(--dur-s) var(--ease), transform var(--dur-s) var(--ease);}
  .date-panel:not([hidden]){display:block}
  .date-panel.is-open{opacity:1; transform:translateY(0)}
  .date-panel-head{display:flex; align-items:center; justify-content:space-between; margin-bottom:var(--sp-3)}
  .date-panel-title{font-family:'Fraunces',serif; font-weight:600; font-size:1rem; margin:0}
  .date-nav{display:flex; align-items:center; justify-content:center; width:2rem; height:2rem; border-radius:var(--radius-pill);
    color:var(--ink); transition:background var(--dur-s) var(--ease)}
  .date-nav:hover, .date-nav:focus-visible{background:var(--sand-2); outline:none}
  .date-nav:disabled{opacity:.3; pointer-events:none}
  .date-weekdays{display:grid; grid-template-columns:repeat(7,1fr); gap:2px; margin-bottom:.25rem}
  .date-weekdays span{text-align:center; font-size:.68rem; font-weight:600; letter-spacing:.04em;
    text-transform:uppercase; color:var(--sand-ink)}
  .date-grid{display:grid; grid-template-columns:repeat(7,1fr); gap:2px}
  .date-cell{aspect-ratio:1; display:flex; align-items:center; justify-content:center; font-size:.85rem;
    font-variant-numeric:tabular-nums; border-radius:var(--radius-pill); color:var(--ink);
    transition:background var(--dur-s) var(--ease), color var(--dur-s) var(--ease)}
  .date-cell:hover:not(:disabled), .date-cell:focus-visible{background:var(--sand-2); outline:none}
  .date-cell:disabled{color:var(--line-light); cursor:default}
  .date-cell.is-outside{color:transparent; pointer-events:none}
  .date-cell.is-today{position:relative}
  .date-cell.is-today::before{content:""; position:absolute; bottom:4px; left:50%; width:4px; height:4px;
    border-radius:50%; background:currentColor; transform:translateX(-50%)}
  .date-cell.is-selected{background:var(--ink); color:var(--cream)}
  .date-cell.is-selected:hover{background:var(--ink-2)}
  .date-panel-hint{margin:var(--sp-3) 0 0; font-size:.74rem; color:var(--sand-ink); text-align:center}

  @media (max-width:520px){
    .date-panel{left:50%; transform:translate(-50%,-6px); width:min(330px,92vw); padding:var(--sp-3)}
    .date-panel.is-open{transform:translate(-50%,0)}
    .date-grid{gap:3px}
  }

  .form-status{padding:var(--sp-4); border-radius:var(--radius-sm); font-size:.92rem; display:none; margin-bottom:var(--sp-4)}
  .form-status[data-state="success"]{display:block; background:rgba(47,143,91,.12); color:var(--success)}
  .form-status[data-state="error"]{display:block; background:rgba(194,79,61,.12); color:var(--error)}
  .form-status[data-state="sending"]{display:block; background:var(--sand-2); color:var(--sand-ink)}
  .btn--primary{background:var(--ink); color:var(--cream)}
  .btn--primary:hover{background:var(--ink-2)}
  .btn:disabled{opacity:.4; cursor:not-allowed; pointer-events:none}

  /* Contact form confirmation panel — replaces .contact-form in place after
     a successful submit (assets/contact.js toggles the two [hidden]
     attributes). Same card treatment as .contact-form/.info-card so it
     reads as the same design system, not a bolted-on alert box. */
  .contact-success{background:var(--cream); border:1px solid var(--line-light); border-radius:var(--radius-sm);
    padding:var(--sp-7); text-align:center; outline:none}
  .contact-success-icon{display:inline-flex; align-items:center; justify-content:center; width:52px; height:52px;
    border-radius:50%; background:rgba(47,143,91,.14); color:var(--success); margin-bottom:var(--sp-4)}
  .contact-success-title{font-family:'Fraunces',serif; font-weight:600; font-size:1.5rem; margin-bottom:var(--sp-3)}
  .contact-success-message{font-size:1.02rem; line-height:1.6; max-width:32rem; margin:0 auto var(--sp-4)}
  .contact-success-note{font-size:.82rem; line-height:1.6; color:var(--sand-ink); max-width:30rem; margin:0 auto}
  .contact-success-note a{color:var(--teal-text); font-weight:600; text-decoration:underline; text-underline-offset:2px}
  .contact-success-note a:hover{color:var(--ink)}

  .info-card{background:var(--cream); border:1px solid var(--line-light); border-radius:var(--radius-sm); padding:var(--sp-6); margin-bottom:var(--sp-5)}
  .info-card h3{font-family:'Fraunces',serif; font-weight:600; font-size:1.05rem; margin-bottom:var(--sp-3)}
  .info-divider{border:0; border-top:1px solid var(--line-light); margin:var(--sp-5) 0}
  .info-note-title{font-size:.78rem; font-weight:600; text-transform:uppercase; letter-spacing:.04em; color:var(--sand-ink); margin-bottom:.4rem}
  .info-note p{font-size:.85rem; line-height:1.6; color:var(--sand-ink)}
  .hours-table{width:100%; border-collapse:collapse; font-size:.92rem}
  .hours-table td{padding:.35rem 0; border-bottom:1px solid var(--line-light)}
  .hours-table tr:last-child td{border-bottom:none}
  .hours-table td:last-child{text-align:right; font-variant-numeric:tabular-nums}
  .hours-table tr.is-closed td:last-child{color:var(--error)}
  .map-frame{width:100%; aspect-ratio:4/3; border:1px solid var(--line-light); border-radius:var(--radius-sm); overflow:hidden}
  .map-frame iframe{width:100%; height:100%; border:0; display:block}
  .map-frame--full{aspect-ratio:21/9; border:0; border-radius:0; border-top:1px solid var(--line-light); border-bottom:1px solid var(--line-light)}

  @media (max-width:900px){
    .contact-grid{grid-template-columns:1fr}
  }
  @media (max-width:520px){
    .contact-form{grid-template-columns:1fr; padding:var(--sp-6) var(--sp-5)}
    .contact-success{padding:var(--sp-6) var(--sp-5)}
    .map-frame--full{aspect-ratio:4/3}
  }

  .eyebrow-tag{position:absolute; top:calc(var(--header-h) + var(--sp-4)); left:var(--sp-6);
    font-size:.75rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase;
    z-index:2}
  .slide--light .eyebrow-tag{color:var(--sand-ink)}
  .slide--dark .eyebrow-tag{color:var(--cream-2)}
  .slide-photo .eyebrow-tag{color:var(--cream); background:rgba(13,43,38,.72);
    backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
    padding:.45rem .85rem; border-radius:var(--radius-pill);}

  .reveal{opacity:0; transform:translateY(18px); transition:opacity var(--dur-l) var(--ease), transform var(--dur-l) var(--ease);}
  .is-in .reveal{opacity:1; transform:translateY(0)}
  .reveal.d1{transition-delay:.05s} .reveal.d2{transition-delay:.15s} .reveal.d3{transition-delay:.25s}

  .btn{display:inline-flex; align-items:center; gap:var(--sp-2); padding:.9rem 1.6rem;
    border-radius:var(--radius-pill); font-weight:600; font-size:.95rem; text-decoration:none;
    text-wrap:balance; text-align:center;
    transition:background var(--dur-s) var(--ease), transform var(--dur-s) var(--ease), color var(--dur-s) var(--ease);}
  .btn:hover{transform:translateY(-2px)}
  .btn--wa{background:var(--wa); color:#06210F;}
  .btn--wa:hover{background:var(--wa-2)}
  .btn--ghost-dark{border:1.5px solid var(--line-dark); color:var(--cream)}
  .btn--ghost-dark:hover{border-color:var(--cream)}
  .btn--ghost-light{border:1.5px solid var(--line-light); color:var(--ink)}
  .btn--ghost-light:hover{border-color:var(--ink)}

  .link-arrow{display:inline-flex; align-self:flex-start; align-items:center; gap:.4rem; text-decoration:none;
    font-weight:600; padding-bottom:2px; border-bottom:1.5px solid currentColor;
    transition:gap var(--dur-s) var(--ease)}
  .link-arrow:hover{gap:.65rem}

  /* eyebrow / badge */
  .badge{display:inline-flex; align-items:center; gap:var(--sp-3); padding:.5rem 1rem;
    border:1px solid var(--line-light); border-radius:var(--radius-pill); font-size:.85rem;}
  .slide--dark .badge{border-color:var(--line-dark)}
  .badge b{font-weight:700}

  /* ---------- full-bleed photo slides (hero + story sections) ---------- */
  /* Each section sets its own --photo-*-lg/-sm custom properties inline
     (see tools/image-pipeline/); this rule is what turns those into a
     format-negotiated, viewport-appropriate background for every one of
     them, so there's one place to tune the responsive-image behaviour
     rather than repeating it per section. */
  .slide-photo{background-size:cover; background-position:center;
    background-image:var(--photo-jpg-lg);
    background-image:image-set(var(--photo-avif-lg) type("image/avif"), var(--photo-webp-lg) type("image/webp"), var(--photo-jpg-lg) type("image/jpeg"));}
  @media (max-width:760px){
    .slide-photo{background-image:var(--photo-jpg-sm);
      background-image:image-set(var(--photo-avif-sm) type("image/avif"), var(--photo-webp-sm) type("image/webp"), var(--photo-jpg-sm) type("image/jpeg"));}
  }
  /* Retina/high-DPR phones (practically all real phones in 2026) get the
     same -lg tier as desktop instead of the bandwidth-saving -sm one.
     Full-bleed background-size:cover on a tall mobile viewport routinely
     needs MORE physical pixels than the viewport is wide (a landscape
     photo cropped to a portrait hero scales off the container's height,
     not its width), so the -sm tier was the actual cause of the "worse on
     mobile than desktop" blur — this fixes it with no new image
     generation, at the cost of a heavier download only for screens that
     can actually resolve it. True 1x-DPR phones (vanishingly rare now)
     still fall back to the lighter -sm tier above. */
  @media (max-width:760px) and (min-resolution:2dppx){
    .slide-photo{background-image:var(--photo-jpg-lg);
      background-image:image-set(var(--photo-avif-lg) type("image/avif"), var(--photo-webp-lg) type("image/webp"), var(--photo-jpg-lg) type("image/jpeg"));}
  }
  .slide-photo::before{content:"";position:absolute; inset:0; background:rgba(13,43,38,.24); pointer-events:none; z-index:1;}
  .photo-card{position:relative; z-index:2; width:min(560px,100%);
    background:rgba(13,43,38,.45); backdrop-filter:blur(10px); -webkit-backdrop-filter:blur(10px);
    border-radius:var(--radius-sm); padding:var(--sp-7) var(--sp-6); box-shadow:var(--shadow-1); color:var(--cream);}
  .photo-card h1,.photo-card h2{color:var(--cream)}
  .photo-card p{color:var(--cream-2)}
  .photo-card .stat-line div > span{opacity:.8}

  /* ---------- #press: photo-card + video side by side, badges below ---------- */
  /* Same full-bleed .slide-photo/.photo-card mechanism as #amber/#mangroves/
     #expeditions — the video card and badge row are the only additions. */
  .press-row{display:flex; flex-wrap:wrap; align-items:flex-start; gap:var(--sp-6); max-width:1160px;}
  /* Video card now matches the text card's width at every breakpoint where
     they sit side by side: both grow from a zero flex-basis and share the
     same 560px cap as .photo-card, so they scale down together and stay
     the same size instead of the video trailing smaller than the text. */
  .press-row .photo-card{flex:1 1 0; width:auto; max-width:560px;}
  .press-video-card{flex:1 1 0; max-width:560px; position:relative; z-index:2;}
  .press-video{position:relative; aspect-ratio:16/9; border-radius:var(--radius-sm); overflow:hidden; box-shadow:var(--shadow-1); background:#000;}
  .press-video iframe, .press-video video{position:absolute; inset:0; width:100%; height:100%; border:0; display:block; object-fit:cover;}
  .press-credit{margin-top:var(--sp-3); font-size:.85rem; color:var(--cream-2);}
  .press-credit span{font-weight:600; color:var(--cream)}
  .press-credit a{text-decoration:none}
  .press-credit a:hover, .press-credit a:focus-visible{text-decoration:underline}
  .press-badge-row{position:relative; z-index:2; margin-top:1rem; display:flex; gap:var(--sp-3);}
  .press-badge{width:110px; height:110px; border-radius:50%; overflow:hidden; box-shadow:var(--shadow-1);
    display:block; object-fit:cover; background:#fff;}
  @media (max-width:760px){
    .press-row{flex-direction:column;}
    .press-row .photo-card{max-width:100%;}
    .press-video-card{flex:1 1 auto; max-width:100%;}
    /* The video bleeds to the true screen edge on mobile (client request) —
       only the media box, not the credit line under it, so that caption
       keeps the page's normal side padding and stays readable. Cancelled
       via a negative margin matching .slide's own horizontal padding,
       which itself tightens at the 560px breakpoint below. */
    .press-video{margin-left:calc(-1 * var(--sp-6)); margin-right:calc(-1 * var(--sp-6)); border-radius:0; box-shadow:none;}
  }

  .hero-eyebrow{font-size:.8rem; font-weight:600; letter-spacing:.14em; text-transform:uppercase; color:var(--cream-2); margin-bottom:var(--sp-4);}
  .hero-heading{font-size:clamp(2.4rem,4vw + 1rem,4.6rem); line-height:1.03; letter-spacing:-.01em;}
  .hero-lead{margin-top:var(--sp-5); max-width:42ch; font-size:clamp(1.02rem,.4vw + 1rem,1.2rem); line-height:1.6;}
  .hero-ctas{display:flex; flex-wrap:wrap; align-items:center; gap:var(--sp-5); margin-top:var(--sp-6);}

  /* ---------- home hero carousel ---------- */
  /* Same var()-driven image-set background as .slide-photo (desktop/tablet
     "-lg" tier, mobile "-sm" tier below 760px), but stacked as absolutely
     positioned layers that crossfade on opacity instead of one static
     background — #hero.slide-photo itself never gets --photo-*-lg/-sm set
     any more, so its own background-image declaration resolves to nothing
     and only these layers paint. .slide-photo::before (dark tint) and
     .photo-card stay exactly as they were, sat on top via z-index. */
  .hero-carousel{position:absolute; inset:0; z-index:0;}
  .hero-carousel-slide{position:absolute; inset:0; opacity:0;
    background-size:cover; background-position:center;
    background-image:var(--photo-jpg-lg);
    background-image:image-set(var(--photo-avif-lg) type("image/avif"), var(--photo-webp-lg) type("image/webp"), var(--photo-jpg-lg) type("image/jpeg"));
    transition:opacity 1.6s var(--ease);}
  .hero-carousel-slide.is-active{opacity:1;}
  @media (max-width:760px){
    .hero-carousel-slide{background-image:var(--photo-jpg-sm);
      background-image:image-set(var(--photo-avif-sm) type("image/avif"), var(--photo-webp-sm) type("image/webp"), var(--photo-jpg-sm) type("image/jpeg"));}
  }
  /* Same retina-only escalation to the -lg tier as .slide-photo above. */
  @media (max-width:760px) and (min-resolution:2dppx){
    .hero-carousel-slide{background-image:var(--photo-jpg-lg);
      background-image:image-set(var(--photo-avif-lg) type("image/avif"), var(--photo-webp-lg) type("image/webp"), var(--photo-jpg-lg) type("image/jpeg"));}
  }
  .hero-carousel-controls{position:absolute; z-index:2; right:var(--sp-6); bottom:var(--sp-5);
    display:flex; align-items:center; gap:var(--sp-3);}
  .hero-carousel-btn{width:42px; height:42px; border-radius:50%; flex:none; padding:0;
    border:1px solid rgba(251,247,238,.28); background:rgba(13,43,38,.5);
    backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
    color:var(--cream); display:flex; align-items:center; justify-content:center; cursor:pointer;
    transition:background var(--dur-s) var(--ease);}
  .hero-carousel-btn:hover{background:rgba(13,43,38,.8);}
  .hero-carousel-btn svg{width:16px; height:16px; display:block;}
  /* Icon shows the action a click performs (pause icon while playing, play
     triangle while paused) rather than the current state, same convention
     as any media player control. */
  .hero-carousel-playpause .icon-play{display:none;}
  .hero-carousel-playpause.is-paused .icon-play{display:block;}
  .hero-carousel-playpause.is-paused .icon-pause{display:none;}
  /* Mobile bug fix: below 760px .photo-card is full-width (no empty space
     beside it for the controls to float over), so the fixed bottom-right
     overlay position used to sit on top of the card's own bottom content
     (the TripAdvisor badge row) whenever the heading/lead wrapped to extra
     lines on a given phone — the exact overlap reported on-device. Taking
     the controls out of absolute positioning and back into #hero's own
     flex column (it's the next sibling of .slide-inner there, and #hero
     is display:flex/flex-direction:column) puts them in normal flow right
     after the card instead, so there is no longer any way for the two to
     overlap regardless of how tall the text content gets. */
  @media (max-width:760px){
    .hero-carousel-controls{position:static; right:auto; bottom:auto; margin-top:var(--sp-5);}
  }
  @media (max-width:560px){
    .hero-carousel-controls{gap:var(--sp-2);}
    .hero-carousel-btn{width:38px; height:38px;}
    .hero-carousel-btn svg{width:14px; height:14px;}
  }
  @media (prefers-reduced-motion: reduce){
    .hero-carousel-slide{transition:none;}
  }

  /* Now an <a href="#about"> (was a purely decorative aria-hidden div) — the
     jump itself needs no JS: html{scroll-behavior:smooth} plus
     html.snap-page{scroll-snap-type:y mandatory} (both above) already turn a
     plain in-page anchor click into a smooth, snapped landing on #about's
     .slide, same as any other anchor link on the site. */
  .scroll-cue{position:absolute; left:50%; bottom:var(--sp-5); transform:translateX(-50%);
    display:flex; flex-direction:column; align-items:center; gap:var(--sp-2); z-index:2;
    font-size:.7rem; letter-spacing:.12em; text-transform:uppercase; color:var(--cream);
    text-shadow:0 1px 6px rgba(13,43,38,.6); text-decoration:none;}
  .scroll-cue:hover span, .scroll-cue:focus-visible span{text-decoration:underline}
  .scroll-cue svg{animation:bob 2.4s ease-in-out infinite}
  @keyframes bob{0%,100%{transform:translateY(0)}50%{transform:translateY(6px)}}
  @media (max-width:760px){
    .scroll-cue{display:none}
  }

  /* decorative svg motifs */
  .motif{position:absolute; pointer-events:none; opacity:.5}
  .motif--waves{inset:auto -5% -8% -5%; width:110%}
  .motif--contour{top:8%; right:-8%; width:46%; opacity:.35}
  .motif--roots{bottom:-6%; left:-6%; width:55%; opacity:.4}
  .motif--route{top:12%; left:-4%; width:40%; opacity:.55}
  .motif--turtle{bottom:6%; right:2%; width:150px; opacity:.5}

  /* ---------- story-card content (inside .photo-card) ---------- */
  .photo-card h2{font-size:clamp(1.9rem,2.6vw + 1rem,3rem); line-height:1.08}
  .photo-card .card-body{margin-top:var(--sp-5); max-width:46ch; line-height:1.65; font-size:1.05rem;}
  .photo-card .link-arrow{margin-top:var(--sp-6)}
  .stat-line{display:flex; gap:var(--sp-7); flex-wrap:wrap; margin-top:var(--sp-4)}
  .stat-line div{display:flex; flex-direction:column; gap:.15rem}
  .stat-line b{font-family:'Fraunces',serif; font-size:clamp(1.9rem,1.1vw + 1.55rem,2.6rem); font-weight:600}
  .stat-line div > span{font-size:.78rem; text-transform:uppercase; letter-spacing:.08em; opacity:.65}

  /* ---------- proof slide ---------- */
  .proof-grid{display:grid; grid-template-columns:.9fr 1.1fr; gap:var(--sp-8); align-items:center;}
  .proof-top{display:flex; align-items:flex-start; justify-content:space-between; flex-wrap:wrap; gap:var(--sp-6);}
  .proof-badges{display:flex; align-items:flex-start; gap:var(--sp-5); flex:none;}
  .proof-award{display:flex; flex-direction:column; align-items:center; width:140px; text-align:center;
    text-decoration:none; transition:transform var(--dur-s) var(--ease), opacity var(--dur-s) var(--ease); opacity:.94}
  .proof-award:hover,.proof-award:focus-visible{transform:translateY(-2px); opacity:1}
  .proof-award-icon{display:block; width:104px; height:128px}
  .rank-shape{display:block; width:128px; height:128px; border-radius:14px; margin:0 auto;}
  .rank-caption{display:block; margin-top:var(--sp-3); font-family:'Work Sans',sans-serif; font-weight:800;
    font-size:.95rem; line-height:1.22; letter-spacing:-.01em; color:#171310;}
  .proof-number{font-family:'Fraunces',serif; font-weight:600; font-size:clamp(4.5rem,11vw,8.5rem);
    line-height:.9; color:var(--ink)}
  .proof-number small{display:block; font-family:'Work Sans',sans-serif; font-weight:600; font-size:1rem;
    letter-spacing:.03em; margin-top:var(--sp-3); color:var(--sand-ink)}
  .proof-stats{display:flex; gap:var(--sp-7); margin-top:var(--sp-6); flex-wrap:wrap}
  .proof-stats div b{display:block; font-family:'Fraunces',serif; font-size:clamp(2.3rem,1.6vw + 1.9rem,3.4rem);
    font-variant-numeric:tabular-nums; letter-spacing:-.01em;}
  .proof-stats div span{font-size:.82rem; color:var(--sand-ink)}
  .proof-stats .count{display:inline-block; font-variant-numeric:tabular-nums; font-size:2.5rem;}

  .quotes{display:flex; flex-direction:column; gap:var(--sp-6)}
  .quote{padding-left:var(--sp-5); border-left:3px solid var(--coral);}
  /* mobile override for .quote's padding-left lives further down, in the
     max-width:560px block — see comment there. */
  .quote p{font-family:'Fraunces',serif; font-size:1.3rem; font-weight:500; line-height:1.42}
  .quote footer{margin-top:var(--sp-3); font-size:.85rem; color:var(--sand-ink)}
  .quote--sm p{font-size:1.05rem; font-family:'Work Sans',sans-serif; font-weight:500}

  /* ---------- final ---------- */
  .final-wrap{display:flex; flex-direction:column; gap:var(--sp-6)}
  .final-top h2{font-size:clamp(2.4rem,4.5vw + 1rem,4.4rem)}
  .final-top p{margin-top:var(--sp-4); max-width:40ch; color:var(--sand-ink); font-size:1.1rem; line-height:1.6}
  .final-ctas{display:flex; flex-wrap:wrap; gap:var(--sp-5); margin-top:var(--sp-6)}
  .foot{display:grid; grid-template-columns:repeat(4,1fr); gap:var(--sp-6);
    padding-top:var(--sp-5); border-top:1px solid var(--line-light); font-size:.9rem; color:var(--sand-ink)}
  .foot h3{font-family:'Work Sans',sans-serif; font-size:.78rem; text-transform:uppercase;
    letter-spacing:.1em; color:var(--ink); font-weight:600; margin-bottom:var(--sp-3)}
  .foot a{text-decoration:none; display:block; padding:.15rem 0; color:var(--sand-ink)}
  .foot a:hover{color:var(--ink)}
  .foot-social{display:flex; gap:var(--sp-3); margin-top:var(--sp-2)}
  .foot-social a{width:45px; height:45px; border:1px solid var(--line-light); border-radius:var(--radius-pill);
    display:flex; align-items:center; justify-content:center; flex:none; transition:background var(--dur-s) var(--ease), border-color var(--dur-s) var(--ease);}
  .foot-social a:hover{background:var(--ink); color:var(--cream); border-color:var(--ink)}
  .foot-social a.foot-social-gyg{display:none}
  .foot-badges{display:flex; align-items:center; gap:var(--sp-6)}
  .foot-badges img{height:44px; width:auto; display:block}
  .foot-badges--col{gap:var(--sp-5); margin-top:var(--sp-1); flex-wrap:wrap}

  .foot-bottom{display:flex; align-items:center; flex-wrap:wrap; gap:var(--sp-5);
    margin-top:var(--sp-5); padding-top:var(--sp-4); border-top:1px solid var(--line-light);}
  .foot-copyright{font-size:.8rem; color:var(--sand-ink)}

  /* ---------- scroll progress ---------- */
  .scroll-progress{position:fixed; top:0; left:0; height:3px; width:100%; z-index:200;
    background:transparent; pointer-events:none;}
  .scroll-progress::after{content:""; display:block; height:100%; width:var(--progress,0%);
    background:var(--coral); transition:width .08s linear;}

  /* ---------- whatsapp pill ---------- */
  .wa-pill{position:fixed; z-index:95; display:flex; align-items:center; gap:var(--sp-3);
    background:var(--wa); color:#06210F; text-decoration:none; font-weight:700; font-size:.95rem;
    padding:.85rem 1.4rem .85rem 1rem; border-radius:var(--radius-pill); box-shadow:var(--shadow-1);
    right:var(--sp-6); bottom:var(--sp-6);
    opacity:0; transform:translateY(16px) scale(.96); pointer-events:none;
    transition:opacity var(--dur-m) var(--ease), transform var(--dur-m) var(--ease), background var(--dur-s) var(--ease);}
  .wa-pill.is-visible{opacity:1; transform:translateY(0) scale(1); pointer-events:auto}
  .wa-pill:hover{background:var(--wa-2)}
  .wa-pill svg{width:24px; height:24px; flex:none}
  /* On phones this collapses from a labelled pill to a plain round icon
     button — a persistent full-width bar with a text label reads as an
     intrusive chat-plugin widget on a small screen and permanently eats
     into the content viewport. A circular FAB in the corner is the
     established mobile pattern (WhatsApp's own app included) and stays
     a comfortably large tap target. The "Message us" label is kept for
     screen readers via aria-label rather than removed outright. */
  @media (max-width:640px){
    .wa-pill{left:auto; right:var(--sp-4); bottom:calc(var(--sp-4) + env(safe-area-inset-bottom));
      width:56px; height:56px; padding:0; justify-content:center;}
    .wa-pill span{position:absolute; width:1px; height:1px; padding:0; margin:-1px;
      overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;}
  }

  /* ---------- back to top (thin, secondary to WhatsApp) ---------- */
  .back-to-top{position:fixed; z-index:94; left:var(--sp-5); bottom:var(--sp-5);
    width:36px; height:36px; border-radius:50%;
    background:rgba(13,43,38,.5); border:1px solid rgba(251,247,238,.28);
    backdrop-filter:blur(8px); -webkit-backdrop-filter:blur(8px);
    display:flex; align-items:center; justify-content:center; color:var(--cream);
    text-decoration:none; opacity:0; transform:translateY(8px); pointer-events:none;
    transition:opacity var(--dur-m) var(--ease), transform var(--dur-m) var(--ease), background var(--dur-s) var(--ease), opacity var(--dur-s) var(--ease);}
  .back-to-top.is-visible{opacity:.5; transform:translateY(0); pointer-events:auto}
  .back-to-top:hover,.back-to-top:focus-visible{opacity:1; background:rgba(13,43,38,.8)}
  .back-to-top svg{width:14px; height:14px}

  /* ---------- responsive ---------- */
  @media (max-width:900px){
    .proof-grid{grid-template-columns:1fr}
    .foot{grid-template-columns:1fr 1fr; row-gap:var(--sp-6)}
  }
  @media (max-width:560px){
    .slide{padding-left:var(--sp-4); padding-right:var(--sp-4)}
    .header-inner{padding:0 var(--sp-4)}
    .logo-word{font-size:.8rem}
    .foot{grid-template-columns:1fr}
    /* Language toggle stays visible next to the hamburger rather than
       hiding inside the off-canvas menu: on a two-language site with no
       account/cart icon competing for header space, a persistent switch
       is one fewer tap for a visitor who's landed on the "wrong" locale
       straight from search — exactly the traffic the /en//fr/ split
       targets. Shrunk down (tighter padding, smaller gap) so it sits
       comfortably beside a full-size 44px hamburger tap target without
       crowding the logo wordmark. */
    .header-actions{gap:var(--sp-3)}
    .lang-toggle{padding:2px}
    .lang-btn{padding:.28rem .5rem; font-size:.72rem}
    .photo-card{padding:var(--sp-6) var(--sp-5)}
    /* Narrower gutter at this breakpoint (16px vs 32px above) means the
       press video's edge-to-edge negative margin has to shrink to match,
       or it'd either overshoot the viewport or leave a thin gap. */
    .press-video{margin-left:calc(-1 * var(--sp-4)); margin-right:calc(-1 * var(--sp-4));}
    .proof-badges{gap:var(--sp-4)}
    .proof-award{width:104px}
    .proof-award-icon{width:84px; height:104px}
    .rank-shape{width:104px; height:104px}
    /* .quote's own 24px padding-left (desktop, above) stacks on top of the
       .slide mobile padding just set above, pushing the pull-quote text in
       by ~40px total versus ~16px for every other section on the page.
       The coral border-left is a deliberate editorial accent, but nobody
       accounted for how it compounds with the mobile-only slide padding
       cut — tighten it to a small 10px offset here so the quote text sits
       close to the rest of the page's mobile content, while the border
       still marks it as a quote. margin:unset clears any inherited margin
       at this breakpoint. */
    .quote{padding-left:10px; margin:unset;}
  }

  /* ---------- mobile landscape: don't force full-screen sections ----------
     A 100svh section on a short, wide phone-in-landscape viewport (e.g.
     375x667 rotated) squeezes vw-scaled headings/CTAs into a sliver of
     height and distorts the layout. On that specific viewport shape, let
     sections size to their content instead — snapping/scroll-behaviour is
     unaffected, only the forced full-screen height is relaxed. Portrait
     phones (the common case) keep the full 100svh treatment untouched. */
  @media (max-height:500px) and (orientation:landscape){
    .slide, .slide-hero{min-height:auto; padding-top:calc(var(--header-h) + var(--sp-5)); padding-bottom:var(--sp-5)}
    .hero-heading{font-size:clamp(1.8rem,3vw + 1rem,3rem)}
    .scroll-cue{display:none}
  }

  /* ---------- reduced motion & no-snap fallback ---------- */
  @media (prefers-reduced-motion: reduce){
    /* Also re-targets html.snap-page: a plain "html" selector here is
       lower specificity than "html.snap-page{scroll-snap-type:y mandatory}"
       (min-width:761px, above), so on desktop/tablet that rule was
       silently winning and reduced-motion visitors kept getting
       snap-locked scrolling despite this override. */
    html,html.snap-page{scroll-behavior:auto; scroll-snap-type:none}
    .reveal{opacity:1; transform:none; transition:none}
    .scroll-cue svg{animation:none}
    .site-menu{transition:none}
    .wa-pill{transition:none}
    .service-card{transition:none}
    .service-card-img{transition:none}
    .service-card:hover .service-card-img,.service-card:active .service-card-img,
    .service-card:focus-within .service-card-img{transform:none}
    .date-panel{transition:none}
  }
