/* ==========================================================================
   EXPLORA VOYAGE — site stylesheet
   Palette sampled from the logo: wordmark teal, wave cyan/aqua, VOYAGE gold.
   All text pairs verified against WCAG AA (ratios noted inline).
   ========================================================================== */

:root{
  /* -- Ink & grounds -------------------------------------------------- */
  --deep:        #06272F;   /* night sea — dark panel ground              */
  --deep-2:      #0E3B47;   /* raised field on dark (image plates)        */
  --ink:         #0A2C36;   /* body text on light            14.7:1 ✓     */
  --ink-mid:     #3E5D64;   /* secondary / lede text          7.1:1 ✓     */
  --ink-soft:    #47686F;   /* captions, meta                 6.0:1 ✓     */
  --paper:       #FFFFFF;
  --mist:        #EDF3F4;   /* image placeholder fields, tinted bands     */

  /* -- Brand ----------------------------------------------------------- */
  --harbour:     #10657F;   /* logo wordmark teal — primary   6.6:1 ✓     */
  --tide:        #00BEF0;   /* logo wave cyan     — on dark   7.2:1 ✓     */
  --foam:        #4CC9C0;   /* logo wave aqua     — on dark   7.8:1 ✓     */
  --brass:       #A6813F;   /* logo VOYAGE gold — rules, large type       */
  --brass-deep:  #7A5F30;   /* gold small text on light       6.0:1 ✓     */
  --brass-light: #C9A45E;   /* gold on dark                   6.7:1 ✓     */

  /* -- Lines ------------------------------------------------------------ */
  --line:        #DCE6E8;   /* decorative hairline on light               */
  --line-int:    #47686F;   /* interactive border (≥3:1 required)         */
  --line-dark:   rgba(255,255,255,.17);
  --line-brass:  rgba(166,129,63,.45);

  /* -- Rhythm ----------------------------------------------------------- */
  --sbw:         0px;       /* scrollbar width; site.js measures the real one */
  --gutter:      clamp(20px, 5vw, 64px);
  --measure:     64ch;
  --shell:       1240px;
  --btn-w:       212px;     /* every CTA is this wide, whatever the label  */

  /* -- Motion ----------------------------------------------------------- */
  --ease:        cubic-bezier(.22,.72,.24,1);
  --dur:         240ms;
}

*,*::before,*::after{ box-sizing:border-box }

html{ -webkit-text-size-adjust:100%; scroll-behavior:smooth; scroll-padding-top:100px }

body{
  margin:0;
  overflow-x:clip;
  background:var(--paper);
  color:var(--ink);
  font:400 17px/1.65 Archivo, "Helvetica Neue", Arial, sans-serif;
  font-feature-settings:"kern" 1;
  -webkit-font-smoothing:antialiased;
}
@media (max-width:600px){ body{ font-size:16px } }

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

h1,h2,h3{
  font-family:Fraunces, Georgia, "Times New Roman", serif;
  font-weight:400;
  font-variation-settings:"opsz" 96;
  letter-spacing:-.012em;
  line-height:1.12;
  margin:0;
  text-wrap:balance;
}

p{ margin:0 }

a{ color:var(--harbour) }

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

/* Focus — never removed, always visible on both grounds ------------------- */
:focus-visible{
  outline:3px solid var(--harbour);
  outline-offset:3px;
  border-radius:2px;
}
.on-dark :focus-visible{ outline-color:var(--tide) }

.skip{
  position:absolute; left:12px; top:-64px; z-index:200;
  background:var(--paper); color:var(--ink);
  padding:12px 18px; border:1px solid var(--ink);
  font-weight:500; text-decoration:none;
  transition:top 180ms var(--ease);
}
.skip:focus{ top:12px }

.wrap{
  width:100%; max-width:var(--shell);
  margin-inline:auto;
  padding-inline:var(--gutter);
}

/* Shared micro-typography ------------------------------------------------ */
.eyebrow{
  font-size:11px; font-weight:600;
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--brass-deep);
}
.on-dark .eyebrow{ color:var(--brass-light) }

/* Section index: position, not a bare ordinal. Hierarchy comes from size,
   not colour, so both halves clear AA. Hidden from screen readers — the
   heading structure already gives non-visual users the whole outline. */
.num{
  display:inline-flex; align-items:baseline; gap:5px;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 24;
  font-weight:300;
  font-variant-numeric:tabular-nums;
}
.num__i { font-size:16px; color:var(--ink) }       /* 14.7:1 ✓ */
.num__of{ font-size:12px; color:var(--ink-soft) }  /*  6.0:1 ✓ */
.on-dark .num__i { color:#C9D8DB }                 /* 11.4:1 on --deep ✓ */
.on-dark .num__of{ color:#8FA9AF }                 /*  6.3:1 on --deep ✓ */

.lede{
  color:var(--ink-mid);
  font-size:clamp(17px, 1.55vw, 19px);
  line-height:1.62;
  max-width:var(--measure);
}
.on-dark .lede{ color:#A9BEC3 }   /* 8.1:1 on --deep ✓ */

.prose{ display:grid; gap:20px; max-width:var(--measure) }
.prose p{ color:var(--ink-mid); font-size:17px; line-height:1.66 }
.on-dark .prose p{ color:#A9BEC3 }

.fineprint{
  margin-top:28px; max-width:var(--measure);
  font-size:13.5px; line-height:1.6; color:var(--ink-soft);
}

/* ==========================================================================
   BUTTONS — every CTA is exactly --btn-w wide, so labels of different
   lengths still line up. Full width on phones.
   ========================================================================== */
.btn{
  display:inline-flex; align-items:center; justify-content:center; gap:10px;
  width:var(--btn-w);
  min-height:48px; padding:12px 20px;
  font:600 14px/1 Archivo, sans-serif;
  letter-spacing:.06em; text-transform:uppercase;
  text-decoration:none; border-radius:2px; border:1px solid transparent;
  cursor:pointer; text-align:center;
  transition:background-color var(--dur) var(--ease),
             color var(--dur) var(--ease),
             border-color var(--dur) var(--ease);
}
.btn svg{ width:17px; height:17px; flex:none }

.btn--primary{ background:var(--harbour); color:#fff }          /* 6.6:1 ✓ */
.btn--primary:hover{ background:#0C566C }

.btn--ghost{ background:transparent; color:var(--ink); border-color:var(--line-int) }
.btn--ghost:hover{ background:var(--mist); border-color:var(--ink) }

/* on dark grounds */
.on-dark .btn--primary{ background:var(--brass-light); color:var(--deep) }  /* 6.7:1 ✓ */
.on-dark .btn--primary:hover{ background:#DBBB7E }
.on-dark .btn--ghost{ color:#fff; border-color:rgba(255,255,255,.42) }
.on-dark .btn--ghost:hover{ background:rgba(255,255,255,.09); border-color:#fff }

.btn-row{ display:flex; flex-wrap:wrap; gap:14px; align-items:center }
@media (max-width:559px){
  .btn-row{ display:grid; gap:12px; width:100%; justify-self:stretch }
  .btn{ width:100% }
}

/* Text link with a rule that draws on hover ------------------------------- */
.link{
  display:inline-flex; align-items:center; gap:9px;
  min-height:44px;
  font:600 13px/1 Archivo, sans-serif;
  letter-spacing:.11em; text-transform:uppercase;
  color:var(--harbour); text-decoration:none;
}
.link svg{ width:15px; height:9px; flex:none; transition:transform var(--dur) var(--ease) }
.link span{ box-shadow:inset 0 -1px 0 0 var(--line-brass); transition:box-shadow var(--dur) var(--ease) }
.link:hover span{ box-shadow:inset 0 -1px 0 0 var(--brass) }
.link:hover svg{ transform:translateX(4px) }
.on-dark .link{ color:var(--brass-light) }

/* ==========================================================================
   HEADER — clear at the top, solid sea in the hero, solid paper past it
   ========================================================================== */
.masthead{
  position:sticky; top:0; z-index:100;
  transition:background-color 300ms var(--ease), box-shadow 300ms var(--ease);
}
.masthead__bar{ display:flex; align-items:center; gap:24px; min-height:76px }
.masthead.is-scrolled:not(.is-solid){
  background:var(--deep);
  box-shadow:inset 0 -1px 0 0 var(--line-dark);
}
.masthead.is-solid{
  background:var(--paper);
  box-shadow:inset 0 -1px 0 0 var(--line);
}

/* Brand lockup ------------------------------------------------------------
   LIVE: the real logo renders; the text lockup below is the dormant fallback.
   To go back to the text lockup, set .brand__mark{display:none} and
   .brand__type{display:block} and delete the two state rules.
   The header inverts as you scroll, so it carries both artworks: the reversed
   file over the dark hero, the colour file once the bar turns white.         */
.brand{ display:flex; align-items:center; min-height:48px; text-decoration:none; margin-right:auto }
/* 52px: at 44 the VOYAGE wordmark under the script fell to ~7px cap height */
.brand__mark{ display:none; height:52px; width:auto }
.masthead:not(.is-solid) .brand__mark--reversed{ display:block }
.masthead.is-solid       .brand__mark--color{ display:block }
.brand__type{ display:none; line-height:1 }
.brand__word{
  display:block;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 48, "SOFT" 40;
  font-weight:400; font-size:26px; letter-spacing:-.01em;
  color:var(--harbour);
  transition:color 300ms var(--ease);
}
.brand__sub{
  display:block; margin-top:3px;
  font:600 9.5px/1 Archivo, sans-serif;
  letter-spacing:.42em; text-indent:.42em;
  color:var(--brass);
  transition:color 300ms var(--ease);
}
.masthead:not(.is-solid) .brand__word{ color:#fff }
.masthead:not(.is-solid) .brand__sub{ color:var(--brass-light) }

/* Primary nav ------------------------------------------------------------- */
.nav{ display:none }
@media (min-width:940px){ .nav{ display:flex; align-items:center; gap:2px } }

.nav__link,
.nav__toggle{
  display:inline-flex; align-items:center; gap:6px;
  min-height:44px; padding:10px 14px;
  background:none; border:0; font:500 14px/1 Archivo, sans-serif;
  color:#fff; text-decoration:none; cursor:pointer;
  position:relative;
  transition:color 300ms var(--ease);
}
.masthead.is-solid .nav__link,
.masthead.is-solid .nav__toggle{ color:var(--ink) }

.nav__link::after,
.nav__toggle::after{
  content:""; position:absolute; left:14px; right:14px; bottom:16px;
  height:1px; background:currentColor;
  transform:scaleX(0); transform-origin:left;
  transition:transform var(--dur) var(--ease);
}
.nav__link:hover::after,
.nav__toggle:hover::after,
.nav__toggle[aria-expanded="true"]::after{ transform:scaleX(1) }

.nav__link[aria-current="page"],
.nav__toggle.is-current{ color:var(--brass-light) }
.masthead.is-solid .nav__link[aria-current="page"],
.masthead.is-solid .nav__toggle.is-current{ color:var(--brass-deep) }
.nav__link[aria-current="page"]::after,
.nav__toggle.is-current::after{ transform:scaleX(1); background:currentColor }

.nav__chev{ width:9px; height:6px; transition:transform var(--dur) var(--ease) }
.nav__toggle[aria-expanded="true"] .nav__chev{ transform:rotate(180deg) }

.nav__group{ position:relative }
.nav__menu{
  position:absolute; top:calc(100% + 6px); right:0; z-index:10;
  min-width:230px; margin:0; padding:6px;
  list-style:none;
  background:var(--paper); border:1px solid var(--line);
  opacity:0; visibility:hidden; transform:translateY(-6px);
  transition:opacity 180ms var(--ease), transform 180ms var(--ease), visibility 180ms;
}
.nav__group.is-open .nav__menu{ opacity:1; visibility:visible; transform:none }
.nav__menu a{
  display:flex; align-items:center; min-height:44px; padding:10px 14px;
  font:500 14px/1.3 Archivo, sans-serif;
  color:var(--ink); text-decoration:none;
  transition:background-color 160ms var(--ease), color 160ms var(--ease);
}
.nav__menu a:hover{ background:var(--mist); color:var(--harbour) }
.nav__menu a[aria-current="page"]{ color:var(--brass-deep); font-weight:600 }

/* Mobile menu ------------------------------------------------------------- */
.burger{
  display:inline-flex; flex-direction:column; justify-content:center; gap:5px;
  width:48px; height:48px; padding:0 11px;
  background:none; border:0; cursor:pointer; margin-left:auto;
}
@media (min-width:940px){ .burger{ display:none } }
.burger span{
  display:block; height:1.5px; background:#fff;
  transition:transform 260ms var(--ease), opacity 200ms var(--ease), background-color 300ms var(--ease);
}
.masthead.is-solid .burger span{ background:var(--ink) }
.burger[aria-expanded="true"] span{ background:#fff }
.burger[aria-expanded="true"] span:nth-child(1){ transform:translateY(6.5px) rotate(45deg) }
.burger[aria-expanded="true"] span:nth-child(2){ opacity:0 }
.burger[aria-expanded="true"] span:nth-child(3){ transform:translateY(-6.5px) rotate(-45deg) }

.drawer{
  position:fixed; inset:0; z-index:99;
  background:var(--deep);
  padding:96px var(--gutter) 40px;
  overflow-y:auto;
  opacity:0; visibility:hidden;
  transition:opacity 260ms var(--ease), visibility 260ms;
}
.drawer.is-open{ opacity:1; visibility:visible }
@media (min-width:940px){ .drawer{ display:none } }
.drawer ul{ list-style:none; margin:0; padding:0 }
/* scoped to `ul a` so it can't reach the CTA that sits beside them */
.drawer ul a{
  display:flex; align-items:center; min-height:56px;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 36;
  font-size:26px; font-weight:300; color:#fff; text-decoration:none;
  box-shadow:inset 0 -1px 0 0 var(--line-dark);
}
.drawer ul a[aria-current="page"]{ color:var(--brass-light) }
.drawer__label{
  margin:34px 0 4px;
  font:600 11px/1 Archivo, sans-serif;
  letter-spacing:.2em; text-transform:uppercase; color:var(--brass-light);
}
.drawer .btn{ margin-top:32px; width:100% }

/* ==========================================================================
   HOME HERO — flat night-sea panel, full-bleed horizon rule, plate crosses it
   ========================================================================== */
.hero{
  background:var(--deep);
  padding-block:clamp(48px, 9vw, 88px) clamp(56px, 8vw, 96px);
  margin-top:-76px; padding-top:calc(clamp(48px, 9vw, 88px) + 76px);
  position:relative;
}
.hero__grid{ display:grid; gap:0 }

.hero__title{
  font-size:clamp(38px, 7.2vw, 74px);
  font-variation-settings:"opsz" 144;
  font-weight:300; line-height:1.03; letter-spacing:-.022em;
  color:#fff; max-width:15ch;
}
.hero__title em{ font-style:normal; color:var(--brass-light) }

/* The horizon. One 1px line carrying the logo's wave gradient — the only
   place the wave appears. Bleeds past both edges; the plate covers it. */
.hero__rule,
.phero__rule{
  position:relative; height:1px;
  /* full-bleed both sides; --sbw keeps 100vw honest when a scrollbar is present */
  margin:clamp(28px, 4vw, 44px) calc(50% - (100vw - var(--sbw)) / 2);
  background:linear-gradient(90deg,
    rgba(16,101,127,0) 0%, var(--harbour) 8%,
    var(--tide) 40%, var(--foam) 70%, rgba(76,201,192,0) 100%);
  transform:scaleX(0); transform-origin:left center;
  animation:draw 1100ms var(--ease) 120ms forwards;
  z-index:1;
}
.hero__rule::before, .hero__rule::after,
.phero__rule::before, .phero__rule::after{
  content:""; position:absolute; top:-4px;
  width:1px; height:9px; background:rgba(255,255,255,.34);
}
.hero__rule::before, .phero__rule::before{ left:34% }
.hero__rule::after,  .phero__rule::after { left:58% }
@keyframes draw{ to{ transform:scaleX(1) } }

.hero__body{ display:grid; gap:clamp(24px, 3vw, 34px); justify-items:start }
.hero__body .lede{ max-width:52ch }
.hero__plate{ z-index:2 }
/* Mobile order is headline → rule → plate → lede → buttons. The rule's own
   bottom margin already spaces the plate, so the plate needs no top margin;
   the body picks up the gap underneath it instead. */
@media (max-width:959px){
  .hero__body{ margin-top:clamp(28px, 4.5vw, 40px) }
}

@media (min-width:960px){
  .hero__grid{
    grid-template-columns:minmax(0,1.04fr) minmax(0,.96fr);
    column-gap:clamp(40px, 5vw, 72px);
    align-items:start;
  }
  .hero__title{ grid-column:1; grid-row:1 }
  .hero__rule { grid-column:1 / -1; grid-row:2 }
  .hero__body { grid-column:1; grid-row:3 }
  /* the rule keeps full strength where the plate cuts it, so the crossing reads */
  .hero__rule{
    background:linear-gradient(90deg,
      rgba(16,101,127,0) 0%, var(--harbour) 8%,
      var(--tide) 30%, var(--foam) 52%, var(--foam) 100%);
  }
  /* Plate bleeds to the right edge and sits flush on the hero's bottom line.
     NB: the usual `50% - 50vw` trick is wrong here — a grid item's percentage
     margin resolves against its grid AREA, not the page, so it overshoots.
     Measure the bleed from the shell instead: gutter + the centring margin. */
  /* The plate keeps its own 3:2 ratio at every width — it no longer stretches
     to the hero's height, so the prepared crop renders exactly as authored.
     It centres against the taller type column instead of sitting flush.
     --sbw is subtracted because 100vw counts the scrollbar but the centred
     .wrap does not; without it the bleed overshoots by the scrollbar width
     at any viewport wider than --shell. */
  .hero__plate{
    grid-column:2; grid-row:1 / 4;
    align-self:center; margin-top:0;
    margin-right:calc(-1 * (var(--gutter) + max(0px, (100vw - var(--sbw) - var(--shell)) / 2)));
  }
}

/* ==========================================================================
   PAGE HERO — inner pages. Same night-sea ground and horizon, no plate.
   ========================================================================== */
.phero{
  background:var(--deep);
  padding-block:clamp(44px, 7vw, 76px) clamp(48px, 7vw, 80px);
  margin-top:-76px; padding-top:calc(clamp(44px, 7vw, 76px) + 76px);
}
.phero__meta{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:8px 16px;
  padding-top:12px; border-top:1px solid var(--brass-light);
  max-width:64ch;
}
.phero__sub{ font-size:14px; color:#A9BEC3 }
.phero__title{
  margin-top:clamp(20px, 2.6vw, 30px);
  font-size:clamp(34px, 5.4vw, 60px);
  font-variation-settings:"opsz" 144;
  font-weight:300; line-height:1.06; letter-spacing:-.02em;
  color:#fff; max-width:18ch;
}
.phero__body{ display:grid; gap:clamp(22px, 3vw, 30px); justify-items:start }
.phero__body .lede{ max-width:58ch }

/* Cruise line mark beside the title on a line page hero. Uses the reversed
   (white) artwork from cruise-lines/reversed/, so it needs no tile behind it.
   No breakpoint: the row wraps on its own once the title no longer fits
   beside the mark — measured at 443px with this title, so it is side by side
   on every phone in landscape and up, and stacked below that. A longer line
   name wraps earlier; re-measure rather than assuming this figure. */
.phero__titlerow{
  display:flex; align-items:center; flex-wrap:wrap;
  gap:clamp(16px, 2.4vw, 30px);
  margin-top:clamp(20px, 2.6vw, 30px);
}
.phero__titlerow .phero__title{ margin-top:0 }
.phero__mark{
  flex:none; display:grid; place-items:center;
  /* 2:1 box matches the 400x200 artwork, so `contain` fills it exactly */
  width:clamp(116px, 12vw, 152px); aspect-ratio:2 / 1;
}
.phero__mark img{ width:100%; height:100%; object-fit:contain }

/* Alternative treatment, kept for reference: colour artwork on a white tile,
   for a line whose reversed variant does not exist. 2:1 box, same rule. */
.phero__logo{
  display:grid; place-items:center;
  width:clamp(128px, 14vw, 168px); aspect-ratio:2 / 1;
  margin-top:clamp(20px, 2.6vw, 28px);
  padding:10px 14px;
  background:var(--paper);
  outline:1px solid var(--line-dark); outline-offset:-1px;
}
.phero__logo img{ width:100%; height:100%; object-fit:contain }

/* Offer page hero. A square banner at the lede's full measure would stand
   631px tall and push the offer below the fold, so from 960px (the home
   hero's breakpoint) it sits beside the text; below that it stacks above it,
   in the same place the voyage pages put their hero image. */
.phero__text{ display:grid; gap:clamp(22px, 3vw, 30px); justify-items:start }
.phero .plate--offer{ background:var(--deep-2); outline-color:var(--line-dark) }
.phero .plate--offer figcaption{ color:var(--brass-light) }
@media (min-width:960px){
  .phero__body--offer{
    /* banner left, offer wording right (client, 15 Sep) */
    grid-template-columns:clamp(300px, 31vw, 440px) minmax(0,1fr);
    column-gap:clamp(40px, 5vw, 72px);
    /* centred, not top-aligned: with the lede removed (client, 15 Sep) the
       text column is far shorter than the square and hung off its top edge */
    align-items:center;
  }
  .phero__body--offer > .plate--offer{ grid-column:1; grid-row:1 }
  .phero__body--offer > .phero__text{ grid-column:2; grid-row:1 }
}

/* Voyage detail hero image — sits between the title and the body copy rather
   than in §01, so it lands on the dark ground. It takes the lede's own measure
   so the two share a left and right edge, and it drops the light placeholder
   ground and hairline that the light-page plates carry. */
.plate--hero-lead{
  /* `ch` resolves against the element's own font, and a bare figure inherits
     16px while .lede runs clamp(17px,1.55vw,19px) — so 58ch here is 66px
     narrower than 58ch there unless the basis is matched exactly. The figure
     holds no text; the size only sets the measure. Keep this clamp in step
     with `.lede`. */
  width:100%; font-size:clamp(17px, 1.55vw, 19px); max-width:58ch;
  background:var(--deep-2);
  outline-color:var(--line-dark);
}
/* An unwired lead plate sits on the dark ground. `.plate` is declared further
   down at the same specificity and wins, so without the doubled class here the
   placeholder paints the light --mist field with an unreadable ink-soft caption.
   Scoped to the empty state so wired voyage heroes render exactly as before. */
.plate.plate--hero-lead:has(img[src=""]){ background:var(--deep-2); outline-color:var(--line-dark) }
.plate.plate--hero-lead:has(img[src=""]) figcaption{ color:var(--brass-light) }

/* FAQ jump nav — plain numerals here; the list already shows the total */
.jump{
  margin-top:clamp(32px, 4vw, 44px);
  display:grid; gap:0 4px;
  border-top:1px solid var(--line-dark);
}
@media (min-width:640px){ .jump{ grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:clamp(24px,4vw,56px) } }
@media (min-width:1080px){ .jump{ grid-template-columns:repeat(3,minmax(0,1fr)) } }
.jump a{
  display:flex; align-items:baseline; gap:14px;
  min-height:56px; padding:15px 0;
  border-bottom:1px solid var(--line-dark);
  color:#fff; text-decoration:none; font-size:16px;
  transition:color var(--dur) var(--ease);
}
.jump a:hover{ color:var(--brass-light) }
.jump .num__i{ font-size:14px; color:#8FA9AF }

/* ==========================================================================
   PLATES — image placeholders at fixed ratios.
   The caption doubles as the placeholder label and hides itself the moment a
   real src is present, so final imagery needs no CSS changes.
   ========================================================================== */
.plate{
  position:relative; margin:0;
  display:grid;
  aspect-ratio:16/10;
  background:var(--mist);
  outline:1px solid var(--line); outline-offset:-1px;
  overflow:hidden;
}
.plate--wide{ aspect-ratio:16/9 }
.plate--banner{ aspect-ratio:21/7 }
.plate--portrait{ aspect-ratio:4/3 }
/* Article lead — capped to the reading measure so it sits on the prose column
   rather than the full content width. A 4:3 photograph at the full 920px
   column renders 690px tall, which reads as a billboard; on the measure it
   reads as a lead. Also keeps the export at 1280x960, the same master the
   16:9 journal card is cropped from. */
.plate--lead{ max-width:var(--measure) }
/* fixed 3:2 at every width, matching the prepared hero crop exactly */
.plate--hero{ aspect-ratio:3/2; background:var(--deep-2); outline-color:var(--line-brass) }

/* --focal keeps the subject in frame when a plate's box is a different shape
   from its file. The hero no longer needs it (plate and photo are both 3:2),
   but it stays available for any plate whose crop can't match its box. */
.plate img{ grid-area:1/1; width:100%; height:100%; object-fit:cover; object-position:var(--focal, 50% 50%) }
.plate img[src=""]{ display:none }

/* Offer banners — 1:1, the shape most cruise lines supply (client, 15 Sep).
   `contain`, not `cover`: the artwork carries the offer wording, so a file that
   arrives in another shape is letterboxed instead of having its text cropped.
   Capped at 440px wherever it sits (offer hero, offer cards), so the largest
   it ever renders is 440 CSS px and a 1080 × 1080 file clears 2× at 2.45×. */
.plate--offer{ aspect-ratio:1/1; width:100%; max-width:440px }
.plate--offer img{ object-fit:contain }
/* A line that supplies a banner smaller than the 440px slot (Seabourn, 300x300,
   16 Sep — the client confirmed it is the only file they have). Capped to the
   artwork's own pixel width so it renders 1:1 rather than being upscaled and
   blurred. Set the cap to match whatever the supplied file measures. */
.plate--offer--native{ max-width:300px }

.plate figcaption{
  grid-area:1/1; align-self:end;
  max-width:38ch; padding:18px 20px;
  font:500 10.5px/1.8 Archivo, sans-serif;
  letter-spacing:.11em; text-transform:uppercase;
  color:var(--ink-soft);
}
.plate--hero figcaption{ font-size:11.5px; padding:26px 28px; color:var(--brass-light) }
.plate:has(img[src]:not([src=""])) figcaption{ display:none }

/* corner tick — marks the field as a reserved plate, not a broken image */
.plate::before{
  content:""; position:absolute; top:12px; left:12px;
  width:14px; height:14px;
  border-top:1px solid var(--brass); border-left:1px solid var(--brass);
  opacity:.55;
}
.plate--hero::before{ top:20px; left:20px; width:20px; height:20px; opacity:.8 }
.plate:has(img[src]:not([src=""]))::before{ display:none }

/* ==========================================================================
   SECTIONS — sticky label rail on the left, content on the right
   ========================================================================== */
.section{ padding-block:clamp(58px, 9vw, 116px) }
.section--tint{ background:var(--mist) }


.section__inner{ display:grid; gap:clamp(24px, 3vw, 36px) }
/* grid items default to min-width:auto, which lets a wide child (the ledger
   tables) stretch the whole page instead of scrolling inside its wrapper */
.section__inner > *{ min-width:0 }
@media (min-width:1024px){
  .section__inner{
    grid-template-columns:190px minmax(0,1fr);
    column-gap:clamp(48px, 5vw, 80px);
    align-items:start;
  }
  .section__label{ position:sticky; top:112px }
}

.section__label{
  display:flex; align-items:baseline; gap:14px;
  padding-top:6px;
  border-top:1px solid var(--brass);
}
@media (min-width:1024px){
  .section__label{ flex-direction:column; align-items:flex-start; gap:8px; padding-top:12px }
}
.on-dark .section__label{ border-top-color:var(--brass-light) }

.section__head{ display:grid; gap:clamp(16px, 2vw, 22px) }
.section__title{ font-size:clamp(27px, 3.4vw, 42px); font-weight:300; max-width:19ch }
.on-dark .section__title{ color:#fff }

.section__body{ margin-top:clamp(36px, 5vw, 60px) }
.section__foot{ margin-top:clamp(30px, 4vw, 44px) }
.section__sub{
  margin-top:clamp(40px, 5vw, 64px);
  padding-top:clamp(24px, 3vw, 32px);
  border-top:1px solid var(--line);
}
.section__sub h2, .section__sub h3{
  font-size:clamp(19px,2vw,23px); font-weight:400; margin-bottom:22px;
}

/* ==========================================================================
   CLOSING CTA — unnumbered, no rail, always a light ground so it never
   stacks against the dark footer
   ========================================================================== */
.close{
  background:var(--mist);
  padding-block:clamp(60px, 8vw, 100px);
}
.close--paper{ background:var(--paper); border-top:1px solid var(--line) }
.close__inner{ display:grid; gap:clamp(20px,2.6vw,28px); max-width:660px }
.close__rule{ display:block; width:56px; height:1px; background:var(--brass) }
.close h2{ font-size:clamp(28px, 3.8vw, 44px); font-weight:300 }

/* ==========================================================================
   CARD GRID — no shadows, no boxes. A plate, a hairline, and type.
   ========================================================================== */
.grid3{ display:grid; gap:clamp(34px, 4vw, 44px) clamp(22px, 2.4vw, 30px) }
@media (min-width:620px){ .grid3{ grid-template-columns:repeat(2,minmax(0,1fr)) } }
@media (min-width:1024px){ .grid3{ grid-template-columns:repeat(3,minmax(0,1fr)) } }

.card{ position:relative; display:flex; flex-direction:column; margin:0 }
.card__meta{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:8px;
  margin-top:20px; padding-top:14px;
  border-top:1px solid var(--line);
  font-size:11px; font-weight:600;
  letter-spacing:.17em; text-transform:uppercase;
  color:var(--brass-deep);
  transition:border-color var(--dur) var(--ease);
}
.card:hover .card__meta{ border-color:var(--brass) }
.card__tag{
  display:inline-block; padding:4px 9px;
  border:1px solid var(--line-brass);
  font-size:10px; letter-spacing:.16em; color:var(--brass-deep);
}

/* i. / ii. / iii. — roman ordinals set as an editorial marker, not a badge */
.card__ord{
  margin-top:20px; padding-top:14px;
  border-top:1px solid var(--line);
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 24;
  font-weight:400; font-size:15px; letter-spacing:.02em;
  color:var(--brass-deep);
  transition:border-color var(--dur) var(--ease);
}
.card:hover .card__ord{ border-color:var(--brass) }

.card__title{
  margin-top:12px;
  font-size:clamp(20px, 1.75vw, 23px);
  font-weight:400; line-height:1.24;
}
.card__title a{ color:var(--ink); text-decoration:none }
.card__title a::after{ content:""; position:absolute; inset:0 }  /* full-card hit area */
.card__title a:hover{ color:var(--harbour) }

.card__spec{ margin-top:10px; font-size:14px; color:var(--ink-soft); font-variant-numeric:tabular-nums }
.card__price-block{ margin-top:14px }
.card__price-label{
  display:block; margin-bottom:3px;
  font:600 11px/1.4 Archivo, sans-serif;
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--brass-deep);
}
.card__price-value{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:4px 7px;
  font-family:Fraunces, Georgia, serif; font-variation-settings:"opsz" 24;
  font-variant-numeric:tabular-nums;
}
.card__price-value .ctx{ font-size:14px; font-weight:400; color:var(--ink-soft) }
.card__price-value .amt{ font-size:24px; font-weight:600; color:var(--brass-deep) }
.card__price-incl{
  display:block; margin-top:6px;
  font:500 10.5px/1.6 Archivo, sans-serif;
  letter-spacing:.08em; text-transform:uppercase; color:var(--ink-soft);
}
.card__note{ margin-top:14px; font-size:15px; line-height:1.6; color:var(--ink-mid) }
.card__expiry{
  margin-top:10px; display:inline-flex; align-items:center; gap:8px;
  font-size:12.5px; font-weight:500; color:var(--ink-mid);
  font-variant-numeric:tabular-nums;
}
.card__expiry::before{ content:""; width:5px; height:5px; border-radius:50%; background:var(--brass); flex:none }
.card__cta{ margin-top:auto; padding-top:18px }

/* Featured article — one large plate beside the copy ---------------------- */
.feature{ position:relative; display:grid; gap:clamp(24px,3vw,40px); margin:0 }
@media (min-width:820px){
  .feature{ grid-template-columns:minmax(0,1.05fr) minmax(0,1fr); align-items:center }
}
.feature .card__title{ font-size:clamp(24px,2.6vw,32px) }

/* ==========================================================================
   MANIFEST — commitments as a ship's document rather than cards.
   One hairline-drawn icon per row, all on a 24px grid at 1.5px stroke.
   ========================================================================== */
.band{ background:var(--deep); color:#fff }
.manifest{ display:grid; margin:0 }
.manifest dt{
  display:flex; align-items:flex-start; gap:12px;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 36;
  font-size:clamp(21px, 2.1vw, 26px); font-weight:300;
  color:var(--brass-light);
}
.manifest dt svg{ width:24px; height:24px; flex:none; margin-top:4px; color:var(--brass-light) }
.manifest dd{ margin:0; color:#C9D8DB; font-size:16px; line-height:1.6 }
@media (max-width:719px){
  .manifest dt{ border-top:1px solid var(--line-dark); padding-top:22px }
  .manifest dd{ padding:6px 0 22px 36px }
}
@media (min-width:720px){
  /* wide enough that "Professional standards" stays on one line beside its icon */
  .manifest{ grid-template-columns:minmax(230px,340px) minmax(0,1fr); column-gap:clamp(28px,4vw,56px) }
  .manifest dt{ grid-column:1; border-top:1px solid var(--line-dark); padding:24px 0 }
  /* +12px lines the 16px body baseline up with the 26px display baseline */
  .manifest dd{ grid-column:2; border-top:1px solid var(--line-dark); padding:36px 0 26px }
}
/* light-ground variant (About) */
.manifest--light dt{ color:var(--harbour) }
.manifest--light dt svg{ color:var(--brass) }
.manifest--light dd{ color:var(--ink-mid) }
@media (max-width:719px){ .manifest--light dt{ border-top-color:var(--line) } }
@media (min-width:720px){
  .manifest--light dt,
  .manifest--light dd{ border-top-color:var(--line) }
}

/* ==========================================================================
   LISTS — brass dash instead of a bullet
   ========================================================================== */
.ticks{ list-style:none; margin:0; padding:0; display:grid; gap:0; max-width:68ch }
.ticks li{
  position:relative;
  padding:16px 0 16px 30px;
  border-top:1px solid var(--line);
  font-size:16px; line-height:1.6; color:var(--ink-mid);
}
.ticks li:last-child{ border-bottom:1px solid var(--line) }
.ticks li::before{
  content:""; position:absolute; left:0; top:26px;
  width:14px; height:1px; background:var(--brass);
}
.on-dark .ticks li{ border-top-color:var(--line-dark); color:#C9D8DB }
.on-dark .ticks li:last-child{ border-bottom-color:var(--line-dark) }

/* Pull quote — a rule and a change of voice, no quote marks --------------- */
.pull{
  margin:clamp(32px,4vw,48px) 0 0;
  padding-top:clamp(22px,3vw,30px);
  border-top:1px solid var(--brass);
  max-width:34ch;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 72;
  font-weight:300; font-size:clamp(22px,2.4vw,29px); line-height:1.28;
  color:var(--ink);
}
.on-dark .pull{ color:#fff; border-top-color:var(--brass-light) }

/* Inset note — a quiet aside, set apart by ground not by a box ------------ */
.note{
  margin-top:clamp(28px,3.5vw,40px);
  padding:clamp(20px,2.6vw,28px) clamp(20px,2.6vw,30px);
  background:var(--mist);
  border-left:2px solid var(--brass);
  max-width:70ch;
}
.section--tint .note{ background:var(--paper) }
.note p{ font-size:15.5px; line-height:1.65; color:var(--ink-mid) }

/* ==========================================================================
   LEDGER TABLES — hairline rules, sticky row header while scrolling wide
   ========================================================================== */
.table-wrap{
  margin-top:clamp(28px,3.5vw,40px);
  max-width:100%;
  overflow-x:auto;
  -webkit-overflow-scrolling:touch;
  outline-offset:4px;
}
.ledger{
  width:100%; min-width:620px;
  border-collapse:collapse;
  font-size:15px;
  background:var(--paper);
}
.section--tint .ledger{ background:var(--mist) }
.ledger caption{
  text-align:left; padding-bottom:16px;
  font-size:11px; font-weight:600; letter-spacing:.2em; text-transform:uppercase;
  color:var(--brass-deep);
}
.ledger th, .ledger td{
  text-align:left; vertical-align:top;
  padding:16px 20px 16px 0;
  border-bottom:1px solid var(--line);
}
.ledger thead th{
  padding-top:0;
  border-bottom:1px solid var(--brass);
  font:600 11px/1.5 Archivo, sans-serif;
  letter-spacing:.17em; text-transform:uppercase;
  color:var(--brass-deep);
  white-space:nowrap;
}
.ledger tbody th{
  position:sticky; left:0;
  background:inherit;
  padding-right:24px;
  font-weight:500; color:var(--ink);
  min-width:170px;
}
.ledger td{ color:var(--ink-mid); line-height:1.6 }
.ledger tbody tr:hover th,
.ledger tbody tr:hover td{ background:var(--mist) }
.section--tint .ledger tbody tr:hover th,
.section--tint .ledger tbody tr:hover td{ background:var(--paper) }

.scroll-hint{
  margin-top:10px;
  font-size:12.5px; color:var(--ink-soft);
}
@media (min-width:900px){ .scroll-hint{ display:none } }

/* ==========================================================================
   ACCORDION — questions, not display type: Archivo for scanability
   ========================================================================== */
.qa{ border-top:1px solid var(--line) }
.qa details{ border-bottom:1px solid var(--line) }
.qa summary{
  display:flex; align-items:flex-start; gap:18px;
  min-height:60px; padding:19px 0;
  list-style:none; cursor:pointer;
  font:500 17px/1.5 Archivo, sans-serif;
  color:var(--ink);
  transition:color var(--dur) var(--ease);
}
.qa summary::-webkit-details-marker{ display:none }
.qa summary:hover{ color:var(--harbour) }
.qa summary::after{
  content:""; flex:none; margin-left:auto; margin-top:7px;
  width:11px; height:11px;
  border-right:1.5px solid var(--brass); border-bottom:1.5px solid var(--brass);
  transform:rotate(45deg);
  transition:transform var(--dur) var(--ease);
}
.qa details[open] summary{ color:var(--harbour) }
.qa details[open] summary::after{ transform:rotate(-135deg); margin-top:11px }

.qa__body{
  display:grid; gap:16px;
  padding:2px 0 28px;
  max-width:72ch;
  animation:qaIn 280ms var(--ease);
}
.qa__body p{ font-size:16px; line-height:1.68; color:var(--ink-mid) }
.qa__body ul{ margin:0; padding-left:20px; display:grid; gap:10px }
.qa__body li{ font-size:16px; line-height:1.6; color:var(--ink-mid) }
.qa__body li::marker{ color:var(--brass) }
@keyframes qaIn{ from{ opacity:0; transform:translateY(-4px) } to{ opacity:1; transform:none } }

/* ==========================================================================
   LOGO GRIDS
   ========================================================================== */
/* Affiliations — logos only, no labels */
/* Capped so three tiles stay near the canvas aspect. Left unconstrained the
   tiles stretch to the full section body (271px at 1440), and since the tile
   height was fixed the box went to 235×60 — aspect 3.9 against the artwork's
   1.97, so `contain` fitted by height and threw away half the box width. */
.creds{
  list-style:none; margin:0; padding:0;
  display:grid; gap:18px;
  grid-template-columns:repeat(2,minmax(0,1fr));
  max-width:726px;
}
@media (min-width:720px){ .creds{ grid-template-columns:repeat(3,minmax(0,1fr)) } }
/* three independents in a two-column phone grid leave a hole; centre the
   orphan under the pair above it instead */
@media (max-width:719px){
  .creds > li:last-child:nth-child(3){
    grid-column:1 / -1; justify-self:center; width:calc(50% - 9px);
  }
}
/* `aspect-ratio`, not a fixed height: the tile's height then tracks whatever
   width the column happens to be, so the image box holds ~1.97 at every
   breakpoint and the artwork fills it instead of letterboxing. 230/133 is that
   ratio plus the 16px inset on each side. */
.creds li{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center;
  aspect-ratio:230 / 133; padding:16px;
  background:var(--paper);
  outline:1px solid var(--line); outline-offset:-1px;
}
/* Logo-in-a-box recipe: let the element fill the container's content box and
   let object-fit:contain letterbox the artwork inside it. The intrinsic
   `max-height:100%; width:auto` approach does NOT work here — the auto grid
   row grows to the image's natural height and the percentage never bites. */
.creds img{ width:100%; height:100%; min-width:0; min-height:0; object-fit:contain }
.creds img[src=""]{ display:none }
/* placeholder mark, inside the container — vanishes when a real logo lands */
.creds li::after{
  content:"LOGO"; font:500 9px/1 Archivo, sans-serif;
  letter-spacing:.22em; color:#9FB4B9;
}
.creds li:has(img[src]:not([src=""]))::after{ display:none }

/* --------------------------------------------------------------------------
   Credential groups — independent memberships vs. a host-agency lockup.

   Signature Travel Network's usage policy requires an affiliated advisor to
   show the host agency's mark alongside theirs, never standalone. So TPI and
   Signature share ONE tile, divided by a hairline, and sit under their own
   label. Reading them as a single credential is the whole point — do not
   flatten them back into the independent row.
   -------------------------------------------------------------------------- */
/* Nothing labels these two groups — the gap between them does the work, so it
   has to beat the 18px gap *inside* a group by enough to read as a break
   rather than a wide row. 2:1 is the floor; below that they read as one grid. */
.creds + .creds{ margin-top:38px }

/* the lockup occupies two of the three tracks, so the row it sits in stays
   in rhythm with the independents above it */
.creds--pair > li{ grid-column:1 / -1 }
@media (min-width:720px){ .creds--pair > li{ grid-column:span 2 } }

/* scoped past `.creds li` / `.foot__creds li`, which set their own padding and
   centre their single child — the lockup needs neither */
.creds .pair, .foot__creds .pair{
  display:grid; grid-template-columns:1fr 1px 1fr;
  grid-template-rows:minmax(0,1fr);
  place-items:stretch;
  padding:0;                                    /* the halves carry the inset */
}
/* The pair spans multiple columns, so it cannot inherit the singles' ratio —
   it needs its own, chosen so the tile lands at the same height as a single
   tile beside it. Derived from (columns spanned × track + gaps) ÷ single
   height, and it holds at both the 2-column and 3-column grids. */
.creds .pair{ aspect-ratio:3.6 }
.foot__creds .pair{ aspect-ratio:5.42 }
/* Tighter top/bottom inset than a single tile. Both marks in the lockup are
   wide lockups (3.8:1 and 4.9:1) inside a 1.97:1 canvas, so `contain` fits
   them by height and leaves the box's width unused — buying back 12px of
   height is the only lever that makes them bigger. */
.pair__mark{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center;
  min-width:0; padding:12px 18px;
}
.pair__mark img{ width:100%; height:100%; min-width:0; min-height:0; object-fit:contain }
.pair__mark img[src=""]{ display:none }
.pair__rule{ align-self:stretch; margin-block:14px; background:var(--line) }

/* placeholder chip moves from the tile to each half, so one mark can be
   wired ahead of the other */
.creds .pair::after, .foot__creds .pair::after{ content:none }
.pair__mark::after{
  content:"LOGO"; font:500 9px/1 Archivo, sans-serif;
  letter-spacing:.22em; color:#9FB4B9;
}
.pair__mark:has(img[src]:not([src=""]))::after{ display:none }

/* Named index — long lists where the label carries the information */
.logos{
  list-style:none; margin:0; padding:0;
  display:grid; gap:14px;
  grid-template-columns:repeat(auto-fill, minmax(150px, 1fr));
}
.logos li{
  display:grid; gap:10px; justify-items:center; text-align:center;
  padding:16px 12px;
  outline:1px solid var(--line); outline-offset:-1px;
  background:var(--paper);
  font-size:12.5px; line-height:1.4; color:var(--ink-mid);
}
.section--tint .logos li{ background:var(--paper) }
.logos .logos__box{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center;
  width:100%; height:44px;
}
.logos img{ width:100%; height:100%; min-width:0; min-height:0; object-fit:contain }
.logos img[src=""]{ display:none }
.logos .logos__box::after{
  content:"LOGO"; font:500 8px/1 Archivo, sans-serif;
  letter-spacing:.2em; color:#9FB4B9;
}
.logos .logos__box:has(img[src]:not([src=""]))::after{ display:none }

/* ---- §05 cruise lines: no caption, so the box takes the room -------------
   Scoped to `.logos--bare`. The §04 certifications list shares `.logos` but
   keeps its labels, and must keep its 44px box.

   Height is the only lever that matters here. The box stays wider than the
   2.00 artwork at every viewport, so `contain` binds on height and the
   painted canvas is `2 x box-height` — raising 44 to 62 takes the logos from
   88x44 to 124x62 without any of them ever hitting a width constraint.

   Do not go past ~67px: at box-width/2 the canvas exactly fills the box, and
   beyond that width binds instead, the logos stop growing, and vertical slack
   opens up under them. */
.logos--bare .logos__box{ height:62px }
.logos--bare .logos__box::after{ font-size:9.5px }   /* chip keeps pace with the box */

/* 12 training badges divide cleanly into 4 x 3. The default
   `auto-fill, minmax(150px, 1fr)` resolves to 5 columns here, which would
   leave a ragged 5 + 5 + 2. Four columns also keeps the box wider than the
   ~1.97 artwork, so the badges stay height-bound at full painted size —
   six columns would pull the box under 124px and start shrinking them. */
@media (min-width:720px){
  .logos--trainings{ grid-template-columns:repeat(4,minmax(0,1fr)) }

  /* Taller box than the cruise-line grid, and deliberately so. These badges
     are compact — median ink is 53% of canvas width against the cruise lines'
     91% — so at a 62px box the painted canvas came to 122px inside a 178px
     box and the tiles read two-thirds empty. 88px grows the canvas to ~173px,
     just under the point where box width binds (178 / 1.97 = 90.4) and the
     artwork would stop growing. Do not exceed 90. */
  .logos--trainings .logos__box{ height:88px }
}

/* Linked line index (Offers → browse by line) */
.linelist{
  list-style:none; margin:0; padding:0;
  display:grid; gap:0;
  border-top:1px solid var(--line);
}
/* Two columns at most. The row carries a logo, an offer count and an expiry
   date; at three columns (~208px a cell) the date wrapped onto three lines. */
@media (min-width:640px){ .linelist{ grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:clamp(24px,4vw,56px) } }
.linelist a{
  display:flex; align-items:center; gap:14px;
  min-height:60px; padding:12px 0;
  border-bottom:1px solid var(--line);
  color:var(--ink); text-decoration:none; font-size:15.5px;
  transition:color var(--dur) var(--ease);
}
.linelist a:hover{ color:var(--harbour) }
.linelist__box{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center; flex:none;
  /* 2.00, matching the cruise-line artwork, so `contain` fills the box exactly
     rather than letterboxing. Sized up on 22 Aug when the line name was
     removed from the row — the logo is now the only identifier. */
  width:112px; height:56px;
  outline:1px solid var(--line); outline-offset:-1px;
}
.linelist img{ width:100%; height:100%; min-width:0; min-height:0; object-fit:contain }
.linelist img[src=""]{ display:none }
.linelist__box:has(img[src=""])::after{
  content:"·"; color:#9FB4B9; font-size:16px;
}
/* Right side of the row: how many offers the line has and when the soonest one
   ends. Replaced a "View offers" label on 11 Sep — repeated on every row it said
   nothing; a count and a date differ per line and tell the visitor something. */
.linelist__info{
  margin-left:auto; min-width:0;
  display:grid; gap:5px; justify-items:end; text-align:right;
}
.linelist__count{
  font:600 10.5px/1 Archivo, sans-serif;
  letter-spacing:.14em; text-transform:uppercase; color:var(--brass-deep);
}
.linelist__ends{ font-size:13px; line-height:1.3; color:var(--ink-soft); font-variant-numeric:tabular-nums; white-space:nowrap }
.linelist__arrow{ display:flex; flex:none; color:var(--brass-deep) }
.linelist__arrow svg{ width:15px; height:9px; transition:transform var(--dur) var(--ease) }
.linelist a:hover .linelist__arrow svg{ transform:translateX(4px) }

/* ==========================================================================
   PARTNERS — Shore Excursions operator blocks
   ========================================================================== */
.partners{ display:grid; gap:clamp(40px,5vw,52px) }
@media (min-width:1024px){ .partners{ grid-template-columns:repeat(3,minmax(0,1fr)); gap:clamp(24px,2.6vw,32px) } }
.partner{ display:flex; flex-direction:column; margin:0 }
.partner__box{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center;
  height:80px; padding:10px; margin-bottom:22px;
  background:var(--paper);
  outline:1px solid var(--line); outline-offset:-1px;
}
/* Padding, not box height, is the lever here. The box stays 80px so the row
   rhythm is untouched; dropping the padding from 16 to 10 raises the content
   box from 48 to 60 and the painted canvas from 144x48 to 180x60 — 25% more
   mark for no layout change. 10px is the floor: at 8px the painted width
   (192) clears the narrowest inner box (193.1 at vw 1024) by 1.1px, and
   anything under that goes width-bound and the logos shrink again. */
.section--tint .partner__box{ background:var(--paper) }
.partner__box img{ width:100%; height:100%; min-width:0; min-height:0; object-fit:contain }
.partner__box img[src=""]{ display:none }
.partner__box:has(img[src=""])::after{
  content:"LOGO"; font:500 9px/1 Archivo, sans-serif;
  letter-spacing:.22em; color:#9FB4B9;
}
.partner h3{
  padding-top:16px; border-top:1px solid var(--brass);
  font-size:clamp(21px,2vw,25px); font-weight:400;
}
.partner__lead{ margin-top:14px; font-size:15px; line-height:1.65; color:var(--ink-mid) }
.partner__best{ margin-top:14px; font-size:15px; line-height:1.65; color:var(--ink) }
.partner__facts, .facts{
  list-style:none; margin:22px 0 0; padding:0;
  display:grid; gap:0; border-top:1px solid var(--line);
}
.partner__facts li, .facts li{
  position:relative; padding:12px 0 12px 010px;
  padding-left:18px;
  border-bottom:1px solid var(--line);
  font-size:14px; line-height:1.55; color:var(--ink-mid);
}
.partner__facts li::before, .facts li::before{
  content:""; position:absolute; left:0; top:21px;
  width:9px; height:1px; background:var(--brass);
}
.partner__cta{ margin-top:auto; padding-top:24px }

.ext{ display:inline-block; width:11px; height:11px; margin-left:2px; vertical-align:baseline }

/* ==========================================================================
   NUMBERED STEPS — a real sequence, so large numerals in the content column
   ========================================================================== */
.steps{ list-style:none; margin:0; padding:0; counter-reset:step; display:grid }
.steps li{
  counter-increment:step;
  display:grid; gap:4px 22px;
  grid-template-columns:auto minmax(0,1fr);
  padding:clamp(22px,2.6vw,28px) 0;
  border-top:1px solid var(--line);
}
.steps li:last-child{ border-bottom:1px solid var(--line) }
.steps li::before{
  content:counter(step, decimal-leading-zero);
  grid-row:1 / 3;
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 72;
  font-weight:300; font-size:clamp(30px,3.4vw,40px); line-height:1;
  color:var(--brass); font-variant-numeric:tabular-nums;
}
.steps h3{ font-size:clamp(19px,1.9vw,22px); font-weight:400; align-self:center }
.steps p{ font-size:15.5px; line-height:1.6; color:var(--ink-mid); max-width:56ch }
@media (max-width:539px){
  .steps li{ grid-template-columns:1fr; gap:10px }
  .steps li::before{ grid-row:auto; font-size:26px }
}

/* ==========================================================================
   CHANNELS — Contact "how to reach us"
   ========================================================================== */
.channels{ display:grid; gap:clamp(28px,3vw,32px) }
@media (min-width:760px){
  .channels{ grid-template-columns:repeat(3,minmax(0,1fr)) }
  .channels--2{ grid-template-columns:repeat(2,minmax(0,1fr)) }
}
.channel{ position:relative; display:flex; flex-direction:column; margin:0; padding-top:16px; border-top:1px solid var(--brass) }
.channel__tag{ font-size:11px; font-weight:600; letter-spacing:.17em; text-transform:uppercase; color:var(--brass-deep) }
.channel h3{ margin-top:12px; font-size:clamp(22px,2.2vw,26px); font-weight:400 }
.channel p{ margin-top:12px; font-size:15px; line-height:1.6; color:var(--ink-mid) }
.channel__num{ margin-top:10px; font-size:16px; color:var(--ink); font-variant-numeric:tabular-nums }
.channel__cta{ margin-top:auto; padding-top:20px }

/* ==========================================================================
   FORM
   ========================================================================== */
.form{ display:grid; gap:22px; max-width:760px }
@media (min-width:680px){
  .form{ grid-template-columns:repeat(2,minmax(0,1fr)); column-gap:24px }
  .form__full{ grid-column:1 / -1 }
}
.field{ display:grid; gap:8px }
.field label{
  font:600 11px/1.4 Archivo, sans-serif;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink);
}
.field .req{ color:var(--brass-deep) }
.field input,
.field textarea{
  width:100%; min-height:52px; padding:14px 16px;
  font:400 16px/1.5 Archivo, sans-serif; color:var(--ink);
  background:var(--paper);
  border:1px solid var(--line-int); border-radius:2px;
  transition:border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.field textarea{ min-height:130px; resize:vertical }
.field input::placeholder,
.field textarea::placeholder{ color:#7E959B }
.field input:hover, .field textarea:hover{ border-color:var(--ink) }
.field input:focus, .field textarea:focus{ border-color:var(--harbour); background:#FBFDFD }

.choice{ border:0; margin:0; padding:0; display:grid; gap:12px }
.choice legend{
  padding:0; margin-bottom:4px;
  font:600 11px/1.4 Archivo, sans-serif;
  letter-spacing:.16em; text-transform:uppercase; color:var(--ink);
}
/* equal-width options: flex-basis 0 makes the boxes match regardless of how
   long each label is, capped at the shared CTA width so they read as a pair */
.choice__row{ display:flex; flex-wrap:wrap; gap:12px }
.choice__opt{
  flex:1 1 0; max-width:var(--btn-w);
  display:inline-flex; align-items:center; gap:10px;
  min-height:48px; padding:10px 20px;
  border:1px solid var(--line-int); border-radius:2px;
  font-size:15px; cursor:pointer;
  transition:border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.choice__opt:hover{ background:var(--mist) }
.choice__opt input{ width:18px; height:18px; accent-color:var(--harbour); margin:0 }
.choice__opt:has(input:checked){ border-color:var(--harbour); background:var(--mist) }
.form__privacy{ font-size:13.5px; line-height:1.6; color:var(--ink-soft); max-width:56ch }

/* Honeypot. Off-canvas rather than display:none — some bots skip hidden
   fields, and none of them read the label. */
.form__trap{
  position:absolute; left:-9999px; width:1px; height:1px;
  overflow:hidden;
}

/* Form outcome banners. `send.php` redirects to #sent / #error /
   #error-email, and `:target` does the rest — no JavaScript, so the form
   still reports its result with scripting off. */
.notice{ display:none; max-width:760px; margin:0 0 28px; padding:18px 20px }
.notice:target{ display:block }
.notice p{ font-size:16px; line-height:1.6 }
.notice strong{ font-weight:600 }
.notice--ok{
  background:var(--mist);
  border-left:3px solid var(--harbour);   /* 6.6:1 on mist */
  color:var(--ink);
}
.notice--err{
  background:#FBF1E8;
  border-left:3px solid var(--brass-deep); /* 6.0:1 on light */
  color:var(--ink);
}

/* ==========================================================================
   FILTER NAV — Journal topics
   ========================================================================== */
.filters{
  display:flex; flex-wrap:wrap; gap:8px;
  margin-bottom:clamp(30px,4vw,42px);
}
.filters__chip{
  display:inline-flex; align-items:center;
  min-height:44px; padding:10px 18px;
  border:1px solid var(--line); border-radius:2px;
  background:none; margin:0;
  font:500 13.5px/1 Archivo, sans-serif;
  color:var(--ink-mid); text-decoration:none; cursor:pointer;
  transition:border-color var(--dur) var(--ease), color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.filters__chip:hover{ border-color:var(--ink-mid); color:var(--ink) }
.filters__chip[aria-pressed="true"]{
  background:var(--harbour); border-color:var(--harbour); color:#fff;
}

/* The count is the only feedback that a filter did anything when the result
   set is short, so it is visible text and not sr-only. */
.filters__count{
  margin:-18px 0 clamp(30px,4vw,42px);
  font:500 12.5px/1.6 Archivo, sans-serif;
  letter-spacing:.06em; color:var(--ink-soft);
}
.filters__count:empty{ display:none }

/* `.card` sets display:flex and `.section` is a block, both of which out-rank
   the UA sheet's [hidden]{display:none}. Without these two rules the filter
   silently does nothing. */
.card[hidden], .section[hidden]{ display:none }

/* Voyage detail pages ------------------------------------------------------
   `.tbd` marks a fact waiting on the cruise line's group contract. It is
   deliberately visible rather than sr-only: a blank cell reads as "nothing
   applies", a marked one reads as "not confirmed yet", and on a page carrying
   a real price that difference matters. */
.tbd{
  font:500 10.5px/1.6 Archivo, sans-serif;
  letter-spacing:.11em; text-transform:uppercase;
  color:var(--brass-deep); white-space:nowrap;
}
.on-dark .tbd{ color:var(--brass-light) }
.phero__price{ margin-top:22px }
.phero__price-label{
  display:block; margin-bottom:4px;
  font:600 11px/1.4 Archivo, sans-serif;
  letter-spacing:.14em; text-transform:uppercase;
  color:var(--brass-light);
}
.phero__price-value{
  display:flex; align-items:baseline; flex-wrap:wrap; gap:6px 10px;
  font-family:Fraunces, Georgia, serif; font-variation-settings:"opsz" 28;
  font-variant-numeric:tabular-nums;
}
.phero__price-value .ctx{ font-size:16px; font-weight:400; color:#A9BEC3 }
.phero__price-value .amt{ font-size:clamp(24px,2.4vw,28px); font-weight:600; color:var(--brass-light) }
.phero__price-incl{
  display:block; margin-top:8px;
  font:500 11px/1.6 Archivo, sans-serif;
  letter-spacing:.08em; text-transform:uppercase; color:#A9BEC3;
}

/* ==========================================================================
   FOOTER
   ========================================================================== */
.foot{ background:#041D24; color:#C9D8DB; padding-block:clamp(56px,7vw,80px) 0 }
.foot__grid{ display:grid; gap:clamp(36px,4vw,48px) }
@media (min-width:760px){ .foot__grid{ grid-template-columns:repeat(2,minmax(0,1fr)) } }
/* The credential column is the middle track, and its width sets the logo size —
   nothing else does. It was briefly widened to 1.55fr to enlarge the logos,
   which overshot: the marks started reading as bold white boxes competing with
   the Contact column. Back to the original balance, which sizes them as a
   quiet credit line. Change these tracks and the logos resize with them. */
@media (min-width:1060px){
  .foot__grid{
    grid-template-columns:1.5fr 1fr 1.2fr;
    column-gap:clamp(40px,5vw,72px);
  }
}

/* footer sits on the darkest ground, so it always takes the reversed artwork */
.foot__mark{ display:block; height:56px; width:auto }
.foot__brand .brand__word{ color:#fff; font-size:30px }
.foot__brand .brand__sub{ color:var(--brass-light) }
.foot__brand > img[src=""]{ display:none }
.foot__blurb{ margin-top:20px; max-width:42ch; font-size:15px; line-height:1.65; color:#9DB2B7 }

.foot h3{
  font-family:Archivo, sans-serif;
  font-size:11px; font-weight:600;
  letter-spacing:.2em; text-transform:uppercase;
  color:var(--brass-light);
  margin:0 0 20px;
}
.foot__creds{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); gap:10px;
}
/* the TPI + Signature lockup — see the note above .pair */
.foot__creds + .foot__creds{ margin-top:20px }   /* 2× the 10px in-group gap */
.foot__creds--pair > li{ grid-column:1 / -1 }
.foot__creds .pair{ grid-template-columns:1fr 20px 1fr }
.foot__creds .pair__rule{ width:1px; justify-self:center }
.foot__creds .pair__mark img{ object-position:left center }
.foot__creds .pair__rule{ background:var(--line-dark) }
.foot__creds .pair__mark{ padding:7px 0 }
.foot__creds .pair__mark::after{ font-size:8px; letter-spacing:.2em; color:#6E878D }

/* ---- Below 1060: put the rule between the two LOGOS, not between two halves
   The pair splits into equal `1fr` halves and each mark is left-aligned, but a
   mark paints narrower than its half — so TPI ended 79px short of the rule
   while Signature began 9px after it. Sizing each mark to its own artwork
   (`width:auto; height:100%`) collapses that slack, so the 10px flex gap sits
   on both sides of the rule. TPI stays on the block's left edge, which §7
   requires. Desktop keeps the grid: there the halves must match the tracks
   above them. */
/* Both marks are edge-to-edge wordmarks, while ASTA/CLIA/IATAN are badges
   with clear space in their canvas — at equal height the lockup reads far
   heavier, so it is drawn at 75% of a single's image height. The singles
   scale with the column (44px at 390 wide, ~107px at 744), so the pair has to
   follow the same formula: single image = ((W − 2 gaps) ÷ 3) × 76/130 − 20px
   tile padding, with W taken from the pair's own list, which is the same
   width as the singles' list. */
@media (max-width:1059px){
  .foot__creds--pair{ container-type:inline-size }
  .foot__creds .pair{ display:flex; align-items:center; gap:14px; aspect-ratio:auto; padding:10px 0 }
  .foot__creds .pair__mark{ flex:0 0 auto; min-width:0; padding:0 }
  .foot__creds .pair__mark img{
    width:auto;
    height:32px;                                              /* no container units */
    height:calc((((100cqw - 20px) / 3) * 0.5846 - 20px) * 0.75);
  }
  .foot__creds .pair__rule{ flex:0 0 1px; width:1px; align-self:stretch; margin-block:0 }
}
/* No outline and no fill — the tile is a layout box only. A footer credit line
   is not UI; boxes here read as controls and pull focus from the columns
   either side. The `aspect-ratio` still does the sizing work (see §5). */
.foot__creds li{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center;
  aspect-ratio:130 / 76; padding:10px 0;
}
.foot__creds img{ width:100%; height:100%; min-width:0; min-height:0;
  object-fit:contain; object-position:left center }
.foot__creds img[src=""]{ display:none }
.foot__creds li::after{
  content:"LOGO"; font:500 8px/1 Archivo, sans-serif;
  letter-spacing:.2em; color:#6E878D;
}
.foot__creds li:has(img[src]:not([src=""]))::after{ display:none }

/* ---- Desktop: both rows ride the same three tracks ----------------------
   The label, the row of three, and the lockup all have to start on one left
   edge. That only holds if the lockup's first mark occupies track 1 exactly,
   so at ≥1060 the pair spans two tracks and splits on the same 20px gap the
   singles use — its halves then measure the same as a single tile. Tile
   padding goes to zero so the artwork starts at the track edge rather than
   inset from it.

   Residual: each logo keeps its own clear space inside the shared canvas
   (ASTA 9.5% a side, TPI 2.5%), so painted ink still sits a few px in. That
   is the artwork's own margin, not layout. */
@media (min-width:1060px){
  .foot__creds{ column-gap:20px }
  .foot__creds li{ padding:0 }
  .foot__creds + .foot__creds{ margin-top:10px }
  .foot__creds--pair > li{ grid-column:span 2 }
  /* 1.595 = the ASTA artwork's own aspect, so the tile stops running out of
     height before it uses its width. At 1.968 the box was 74 x 37.6 and every
     mark was height-bound, painting ~19% narrower than the tile allowed.
     The pair ratio is derived: (2 tracks + gap) / single height, so both rows
     stay the same height. Recompute both together if either changes. */
  .foot__creds li{ aspect-ratio:1.595 }
  .foot__creds .pair{ aspect-ratio:3.62 }
  .foot__creds .pair__mark{ padding:0 }
}

.foot dl{ margin:0; display:grid; gap:16px }
.foot dt{ font-size:11px; font-weight:600; letter-spacing:.16em; text-transform:uppercase; color:#7E979D }
.foot dd{ margin:2px 0 0; font-size:15.5px; color:#DCE7E9 }
/* padding + equal negative margin: 44px+ tap target, zero layout change */
.foot dd a{
  display:inline-block; padding:11px 0; margin:-11px 0;
  color:#DCE7E9;
  text-decoration:underline;
  text-decoration-color:rgba(201,164,94,.55);
  text-decoration-thickness:1px;
  text-underline-offset:4px;
  transition:color var(--dur) var(--ease), text-decoration-color var(--dur) var(--ease);
}
.foot dd a:hover{ color:#fff; text-decoration-color:var(--brass-light) }

.foot__social{ display:flex; gap:8px; margin-top:26px }
.foot__social a{
  display:grid; grid-template-rows:minmax(0,1fr); place-items:center; width:46px; height:46px;
  border:1px solid var(--line-dark); border-radius:2px; color:#C9D8DB;
  transition:border-color var(--dur) var(--ease), color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.foot__social a:hover{ border-color:var(--brass-light); color:var(--brass-light); background:rgba(255,255,255,.05) }
.foot__social svg{ width:19px; height:19px }

.foot__base{
  margin-top:clamp(48px,6vw,68px);
  padding-block:26px;
  border-top:1px solid var(--line-dark);
  display:flex; flex-wrap:wrap; gap:8px 24px; justify-content:space-between;
  font-size:13px; color:#7E979D;
}
/* roman, not italic — the italic axis isn't in the font request, and a
   synthesised oblique on a serif this fine reads as a mistake */
.foot__tag{
  color:var(--brass-light);
  font-family:Fraunces, Georgia, serif;
  font-variation-settings:"opsz" 24;
  font-size:15px;
}

/* ==========================================================================
   WHATSAPP FAB — persistent floating CTA, bottom-right, every page
   ========================================================================== */
.wa-fab{
  position:fixed;
  right:max(20px, env(safe-area-inset-right));
  bottom:max(20px, env(safe-area-inset-bottom));
  z-index:150;
  display:flex; align-items:center; justify-content:center;
  width:58px; height:58px; border-radius:50%;
  background:var(--harbour); color:#fff;
  box-shadow:0 6px 20px rgba(6,39,47,.28), 0 2px 6px rgba(6,39,47,.16);
  transition:background-color var(--dur) var(--ease),
             transform var(--dur) var(--ease),
             box-shadow var(--dur) var(--ease);
}
.wa-fab:hover{
  background:#0C566C; transform:translateY(-2px);
  box-shadow:0 10px 26px rgba(6,39,47,.34), 0 3px 8px rgba(6,39,47,.2);
}
.wa-fab:focus-visible{ outline:2px solid var(--tide); outline-offset:3px }
.wa-fab svg{ width:28px; height:28px }
@media (max-width:600px){
  .wa-fab{ width:52px; height:52px }
  .wa-fab svg{ width:25px; height:25px }
}
@media (prefers-reduced-motion:reduce){
  .wa-fab:hover{ transform:none }
}

/* ==========================================================================
   SCROLL REVEAL
   ========================================================================== */
.reveal{
  opacity:0; transform:translateY(16px);
  transition:opacity 620ms var(--ease), transform 620ms var(--ease);
  transition-delay:calc(var(--i, 0) * 70ms);
}
.reveal.is-in{ opacity:1; transform:none }

/* Hero load sequence */
.hero__title, .hero__body > *, .hero__plate,
.phero__meta, .phero__title, .phero__body > *, .jump{
  opacity:0; transform:translateY(18px);
  animation:rise 760ms var(--ease) forwards;
}
.hero__title, .phero__title{ animation-delay:120ms }
.phero__meta{ animation-delay:60ms }
.hero__body > *:nth-child(1), .phero__body > *:nth-child(1){ animation-delay:300ms }
.hero__body > *:nth-child(2), .phero__body > *:nth-child(2){ animation-delay:380ms }
.hero__plate{ animation-delay:200ms }
.jump{ animation-delay:440ms }
@keyframes rise{ to{ opacity:1; transform:none } }

/* ==========================================================================
   REDUCED MOTION — everything static and visible
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html{ scroll-behavior:auto }
  *,*::before,*::after{
    animation-duration:.01ms !important;
    animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
    scroll-behavior:auto !important;
  }
  .reveal{ opacity:1; transform:none }
  .hero__title, .hero__body > *, .hero__plate,
  .phero__meta, .phero__title, .phero__body > *, .jump{ opacity:1; transform:none }
  .hero__rule, .phero__rule{ transform:scaleX(1) }
}
