
@font-face {
  font-family: "Bricolage Grotesque";
  src: url('/fonts/bricolage-grotesque.woff2') format("woff2");
  font-style: normal;
  font-weight: 200 800;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url('/fonts/geist.woff2') format("woff2");
  font-style: normal;
  font-weight: 100 900;
  font-display: swap;
}
:root {
  --navy: #07182d;
  --ink: #102642;
  --blue: #155dfc;
  /*
   * ACCESSIBILITY TOKENS (16 Aug 2026 audit).
   *
   * Fifteen WCAG AA contrast failures, all near-misses at 3.7-4.3 where 4.5 is required, so small
   * token moves clear the whole set without touching the palette's character:
   *   --muted   #60728a -> #4a5a6e   (4.92 -> 7.05 on white; it is used for 11-13px text on tinted
   *                                   cards where it was measuring 3.93-4.01)
   *   --purple  #8b5cf6 -> #6d28d9   (4.23 -> 7.10, and white-on-purple passes too)
   *   --blue-ink                     NEW. --blue #155dfc is fine as a BACKGROUND with white text
   *                                   (5.25) but fails as TEXT on yellow (4.23) and on pale blue
   *                                   (4.28). Rather than darken --blue everywhere and lose the
   *                                   brand blue, text-on-light uses this darker variant: 7.40 on
   *                                   #ffe777, 7.48 on #dce9ff.
   */
  --blue-ink: #0b3fa8;
  --cyan: #00d9ff;
  --mint: #baffc9;
  --purple: #6d28d9;
  --yellow: #ffe777;
  --coral: #ff745d;
  --cream: #fff8dc;
  --foam: #f6fbff;
  --line: #d8e6f8;
  --white: #fff;
  --muted: #4a5a6e;
  --max: 1280px;
  --display: "Bricolage Grotesque", Arial, sans-serif;
  --sans: "Geist", Arial, sans-serif;
}

* {
  box-sizing: border-box;
}
html {
  scroll-behavior: smooth;
}
body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--sans);
  -webkit-font-smoothing: antialiased;
}
button,
select,
input {
  font: inherit;
}
button,
a {
  -webkit-tap-highlight-color: transparent;
}
a {
  color: inherit;
  text-decoration: none;
}
button {
  cursor: pointer;
}
main {
  overflow-x: clip;
  overflow-y: visible;
}
h1,
h2,
h3,
.brand {
  font-family: var(--display);
}

.offer-bar {
  min-height: 36px;
  /* Right padding leaves room for the absolutely-positioned close control. */
  padding: 7px 52px 7px 24px;
  background: var(--yellow);
  color: var(--navy);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  font-size: 14px;
  position: relative;
}

/*
 * THE CSS-ONLY DISMISS.
 *
 * The checkbox is the control and lives immediately before the bar in source order; the label
 * inside the bar is what people click. `~` rather than `+` because the label sits deeper in the
 * tree than the checkbox's own next sibling.
 *
 * ABSOLUTE, not the last flex item: the bar centres its content, and a `margin-left: auto` on the
 * last child would have shoved the message off-centre to make room. Taking the button out of flow
 * keeps the copy centred and puts the cross where it was asked for — hard right.
 */
.offer-dismiss {
  position: absolute;
  width: 1px;
  height: 1px;
  opacity: 0;
  pointer-events: none;
}
/*
 * DISMISSAL LASTS FOR THIS PAGE VIEW ONLY, by design (owner's call, September 2026): the bar comes
 * back on refresh. The previous build persisted it in localStorage via an inline script; that
 * script is gone, and with it the `html.oc` rule it used to set — and inner pages are back to
 * allowing no inline JavaScript at all.
 */
.offer-dismiss:checked ~ .offer-bar {
  display: none;
}
.offer-close {
  position: absolute;
  right: 14px;
  top: 50%;
  transform: translateY(-50%);
  /*
   * ABOVE THE NAV TOGGLE, or the cross does nothing.
   *
   * `.nav-toggle` is an invisible 44x44 checkbox at `top: 0; right: 14px` with `z-index: 3`, and
   * its offset parent is <body> — so it lands on the top-right corner of the PAGE, which is the
   * offer bar, not the header. It sat directly on top of this 26x26 cross and swallowed every
   * click: elementFromPoint over the cross returned INPUT.nav-toggle, and the bar never closed.
   * On desktop that toggle is inert anyway (its .menu-button is display:none), so nothing is lost
   * by putting the cross in front of it.
   */
  z-index: 4;
  /* 24x24 minimum target — the footer links were fixed for exactly this reason (audit F-08). */
  width: 26px;
  height: 26px;
  display: inline-grid;
  place-items: center;
  border-radius: 50%;
  cursor: pointer;
  color: var(--navy);
  transition: background 0.15s;
}
.offer-close:hover {
  background: #0000001a;
}
.offer-close svg {
  width: 13px;
  height: 13px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.2;
  stroke-linecap: round;
}
/* The focus ring belongs to the checkbox, so it has to be drawn on the thing people can see. */
.offer-dismiss:focus-visible ~ .offer-bar .offer-close {
  outline: 3px solid var(--navy);
  outline-offset: 2px;
}
/*
 * The FTC "Ad" tag.
 *
 * Thirteen pages carry the offer bar as their only affiliate link, with the disclosure a full
 * scroll away in the footer — which does not meet the FTC's proximity requirement. Deliberately
 * legible rather than hidden: a disclosure styled to be overlooked is not a disclosure.
 */
/*
 * The BADGE is gone (24 Aug 2026, owner request); the disclosure is not.
 *
 * It was a bordered, uppercase, letter-spaced chip that read as a sticker applied to the bar. Now
 * it is a quiet inline word ahead of the sentence — still legible, still first, still adjacent to
 * the claim it qualifies, which is what the FTC proximity rule actually asks for. A disclosure
 * styled to be overlooked would not be one, so it keeps full opacity and the bar's own colour.
 */
.offer-bar-tag {
  flex: none;
  font-size: 11px;
  font-weight: 700;
  opacity: 0.7;
}

.offer-bar strong {
  padding: 4px 11px;
  background: var(--navy);
  color: var(--white);
  border-radius: 999px;
  font-size: 13px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.offer-bar a {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-weight: 800;
}
.arrow {
  width: 18px;
  height: 18px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.8;
  stroke-linecap: round;
  stroke-linejoin: round;
  flex: none;
}

.site-header {
  height: 72px;
  max-width: var(--max);
  margin: 0 auto;
  padding: 0 24px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 28px;
  background: var(--white);
  position: relative;
  z-index: 30;
}
.brand {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  color: var(--navy);
  font-size: 23px;
  font-weight: 800;
  letter-spacing: -0.045em;
  white-space: nowrap;
}
.brand-accent {
  color: var(--blue);
}
/*
 * THE SAME WORDMARK, TWO BACKGROUNDS (Phase 102).
 *
 * Mobile Lighthouse measured .brand-accent at 3.39:1 in the footer — #155dfc on the navy band —
 * against the 4.5:1 that WCAG 1.4.3 requires of text. It passes in the header because the header
 * is white; nobody had checked it on the dark half, and the desktop run did not surface it either.
 *
 * --mint is the palette's existing on-navy accent (it is what the favicon uses on the same navy)
 * and measures 15.5:1, so this is a token swap rather than a new colour. The header keeps --blue.
 */
.site-footer .brand-accent {
  color: var(--mint);
}
.mark {
  width: 40px;
  height: 40px;
  border-radius: 14px;
  background: var(--navy);
  display: inline-grid;
  place-items: center;
  flex: none;
  transform: rotate(-2deg);
}
.mark svg {
  width: 30px;
  height: 30px;
  fill: none;
  stroke: var(--mint);
  stroke-width: 2.2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.site-header nav {
  display: flex;
  align-items: center;
  gap: 29px;
  margin-left: auto;
}
.site-header nav a {
  position: relative;
  padding: 26px 0;
  font-size: 14px;
  font-weight: 700;
  color: #31465e;
}
.site-header nav a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 100%;
  bottom: 18px;
  height: 2px;
  background: var(--blue);
  transition: right 0.15s ease;
}
.site-header nav a:hover::after {
  right: 0;
}
.header-cta,
.button {
  min-height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 0 21px;
  border-radius: 999px;
  border: 0;
  font-size: 14px;
  font-weight: 800;
  transition:
    transform 0.15s ease,
    box-shadow 0.15s ease;
}
.header-cta {
  background: var(--navy);
  color: var(--white);
}
.header-cta:hover,
.button:hover,
.plan-button:hover {
  transform: translateY(-2px);
}
.menu-button {
  display: none;
  width: 43px;
  height: 43px;
  border: 1px solid var(--line);
  border-radius: 50%;
  background: var(--white);
  padding: 12px;
}
.menu-button span {
  display: block;
  height: 2px;
  background: var(--navy);
  margin: 5px 0;
}

.hero {
  width: 100%;
  min-height: 725px;
  position: relative;
  background: var(--navy);
  overflow: hidden;
}
/*
 * RESPONSIVE HERO PHOTOGRAPH (Phase 102).
 *
 * Mobile Lighthouse listed this file as the largest asset on the homepage: 88 kB of a 1672x941
 * photograph fetched in full onto a 412px phone. It is not the LCP element — that is header text —
 * but it is the biggest competitor for bandwidth in the window where the LCP element is trying to
 * paint, and it finished at 805 ms.
 *
 * Three declarations, deliberately in this order. The plain `url()` stays first and unchanged, so
 * any browser that does not understand what follows keeps exactly what it has today. `image-set()`
 * with `type()` then offers AVIF (61 kB) and is ignored wholesale by browsers that cannot parse it.
 * The media query swaps in a 900px-wide pair below 900px of viewport: 20.5 kB in AVIF, down from
 * 88 kB — the single biggest byte saving available on this page.
 *
 * Variants are built by scripts/gen-hero-photos.mjs, which documents the measured quality settings.
 */
/*
 * NO REVEAL ANIMATION ON THE HERO PHOTO — 14 Sep 2026.
 *
 * It carried `animation: hero-reveal .55s ease-out both`, and `hero-reveal` starts at `opacity: 0`.
 * With `fill-mode: both` the element holds that starting frame until the animation actually runs,
 * so the photo is INVISIBLE until it does. Browsers throttle animations in a backgrounded or
 * hidden tab, and the photo's animation is created after the bitmap decodes — late enough to miss
 * the window. Result: a permanently blank hero, which is what the owner reported on both / and
 * /ports, and what the diagnosis showed (element topmost, opaque background image decoding at
 * 1672x941, computed opacity 0, animation "running" and frozen at currentTime 0).
 *
 * Fill-mode `none` does not fix it either: a frozen animation still pins the animated value at its
 * first frame. The only reliable fix is to stop gating the image's visibility on an animation.
 * A 550ms fade is a nicety; a hero that never appears is a broken page.
 */
/*
 * PLAIN url(), NOT image-set() — 14 Sep 2026.
 *
 * This shipped as `background: url(...webp) ...` followed by `background-image: image-set(
 * url(...avif) type('image/avif'), url(...webp) type('image/webp'))`. The second declaration wins,
 * which DISCARDS the plain-URL fallback — and some engines parse that image-set (computed style
 * echoes it back in full) while painting nothing from it. The result is a hero with no photo at
 * all, which is what the owner reported on / and /ports.
 *
 * `@supports` cannot guard this: it tests whether the syntax PARSES, and the syntax parses fine.
 * The failure is at paint. So the fallback has to be the only declaration.
 *
 * WebP is the format here because it is universally supported and already built. The .avif files
 * stay in /img/ for whenever this is revisited with a <picture> element, which can negotiate format
 * properly instead of relying on a background-image to do it.
 */
.hero-photo {
  position: absolute;
  inset: 0 0 0 43%;
  background: url('/img/cruise-hero.webp') 57% center / cover no-repeat;
}
@media (max-width: 900px) {
  .hero-photo {
    background-image: url('/img/cruise-hero-900.jpg');
  }
}
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(7, 24, 45, 0.08);
}
.hero-panel {
  min-height: 725px;
  width: 57%;
  padding: 92px 105px 150px max(24px, calc((100vw - 1280px) / 2 + 24px));
  background: var(--navy);
  color: var(--white);
  position: relative;
  z-index: 4;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  clip-path: ellipse(98% 80% at 0 50%);
  animation: rise-in 0.55s 0.08s ease-out both;
}
.eyebrow,
.step-label {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--blue);
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.15em;
  text-transform: uppercase;
}
.eyebrow.light,
.step-label.light {
  color: var(--mint);
}
.live-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--mint);
  box-shadow: 0 0 0 5px rgba(186, 255, 201, 0.13);
  animation: signal-pulse 2.8s ease-out infinite;
}
.hero h1 {
  margin: 20px 0 22px;
  max-width: 630px;
  font-size: clamp(58px, 5.3vw, 78px);
  line-height: 0.93;
  letter-spacing: -0.055em;
  font-weight: 750;
}
.hero h1 span,
.hero h1 strong {
  display: block;
}
.hero h1 strong {
  color: var(--mint);
  font-weight: inherit;
}
.hero-panel > p {
  margin: 0;
  max-width: 510px;
  color: #ced9e7;
  font-size: 17px;
  line-height: 1.62;
}
.hero-actions {
  display: flex;
  align-items: center;
  gap: 23px;
  margin-top: 28px;
}
.mint-button {
  color: var(--navy);
  background: var(--mint);
  box-shadow: 0 8px 0 rgba(0, 0, 0, 0.18);
}
.dark-button {
  color: var(--white);
  background: var(--navy);
  box-shadow: 0 8px 0 rgba(4, 14, 27, 0.15);
}
.pale-button {
  color: var(--navy);
  background: var(--white);
}
.text-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--navy);
  font-size: 14px;
  font-weight: 800;
  border-bottom: 1px solid currentColor;
  padding-bottom: 3px;
}
.light-link {
  color: var(--white);
  opacity: 0.88;
}
.hero-proof {
  display: flex;
  align-items: center;
  gap: 13px;
  margin-top: 26px;
  color: #b8c8da;
  font-size: 13px;
  line-height: 1.5;
}
.hero-proof strong {
  color: var(--white);
  font-size: 14px;
}
.proof-avatars {
  display: flex;
}
.proof-avatars i {
  width: 34px;
  height: 34px;
  margin-left: -7px;
  border: 2px solid var(--navy);
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--mint);
  color: var(--navy);
  font-size: 12px;
  font-style: normal;
  font-weight: 900;
}
.proof-avatars i:first-child {
  margin-left: 0;
  background: var(--yellow);
}
.proof-avatars i:last-child {
  background: var(--coral);
}
.hero-route {
  position: absolute;
  z-index: 2;
  right: 0;
  top: 45px;
  width: 58%;
  height: 310px;
  overflow: visible;
}
.hero-route-path {
  fill: none;
  stroke: rgba(255, 255, 255, 0.7);
  stroke-width: 2;
  stroke-dasharray: 8 12;
  animation: route-flow 11s linear infinite;
}
.hero-route-port {
  fill: var(--yellow);
  stroke: var(--white);
  stroke-width: 4;
}
.hero-route-dot {
  fill: var(--mint);
  filter: drop-shadow(0 0 8px var(--mint));
  animation: route-dot 3s ease-in-out infinite;
}
.hero-route-boat {
  fill: var(--white);
  transform-origin: 331px 137px;
  animation: ship-bob 4.8s ease-in-out infinite;
}
.hero-stamp {
  position: absolute;
  z-index: 5;
  right: max(27px, calc((100vw - 1280px) / 2 + 18px));
  bottom: 117px;
  width: 96px;
  height: 96px;
  border-radius: 50%;
  background: var(--yellow);
  color: var(--navy);
  border: 5px solid rgba(255, 255, 255, 0.85);
  display: grid;
  place-content: center;
  text-align: center;
  transform: rotate(7deg);
  box-shadow: 0 15px 30px rgba(7, 24, 45, 0.25);
}
.hero-stamp span {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.12em;
}
.hero-stamp strong {
  line-height: 0.8;
  font-size: 19px;
}
.hero-location {
  position: absolute;
  z-index: 5;
  right: max(25px, calc((100vw - 1280px) / 2 + 150px));
  bottom: 105px;
  padding: 8px 12px;
  border-radius: 999px;
  background: rgba(7, 24, 45, 0.76);
  color: var(--white);
  backdrop-filter: blur(8px);
  font-size: 13px;
  font-weight: 700;
}
.hero-location span {
  color: var(--mint);
  margin-right: 5px;
}
.hero-spark {
  position: absolute;
  z-index: 4;
  color: var(--yellow);
  font-size: 31px;
  animation: sparkle 3.6s ease-in-out infinite;
}
.spark-one {
  top: 89px;
  right: 12%;
}
.spark-two {
  top: 35%;
  right: 46%;
  font-size: 20px;
  animation-delay: 1.1s;
}

.finder-wrap {
  position: relative;
  z-index: 12;
  max-width: var(--max);
  margin: -72px auto 0;
  padding: 0 24px;
  scroll-margin-top: 16px;
}
.finder-card {
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 27px;
  padding: 24px;
  box-shadow: 0 22px 62px rgba(22, 55, 91, 0.18);
}
.journey-tabs {
  display: inline-flex;
  padding: 4px;
  margin-bottom: 16px;
  border-radius: 999px;
  background: var(--foam);
  border: 1px solid var(--line);
}
.journey-tabs button {
  min-height: 31px;
  padding: 0 15px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--muted);
  font-size: 13px;
  font-weight: 850;
}
.journey-tabs button.active {
  background: var(--navy);
  color: var(--white);
}
.finder-heading {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
  margin-bottom: 17px;
}
.finder-heading h2 {
  margin: 5px 0 0;
  font-size: 25px;
  letter-spacing: -0.045em;
}
.finder-note {
  padding: 7px 11px;
  border-radius: 999px;
  background: #ecfff1;
  color: #216239;
  font-size: 13px;
  font-weight: 800;
}
.finder-grid {
  display: grid;
  grid-template-columns: 1fr 1.15fr 1.15fr 0.7fr 0.9fr 1.3fr auto;
  gap: 8px;
}
.finder-grid label {
  min-width: 0;
  padding: 9px 12px;
  background: var(--foam);
  border: 1px solid var(--line);
  border-radius: 14px;
}
.finder-grid label > span {
  display: block;
  margin-bottom: 3px;
  color: var(--muted);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.09em;
  text-transform: uppercase;
}
.finder-grid select {
  width: 100%;
  border: 0;
  outline: 0;
  color: var(--ink);
  background: transparent;
  font-size: 14px;
  font-weight: 800;
}
.sea-toggle {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 11px;
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: 14px;
  text-align: left;
}
.sea-toggle > span:last-child {
  display: grid;
}
.sea-toggle strong {
  font-size: 13px;
}
.sea-toggle small {
  color: var(--muted);
  font-size: 11px;
}
.toggle-track {
  width: 30px;
  height: 17px;
  padding: 2px;
  border-radius: 99px;
  background: #b4c0cc;
  flex: none;
}
.toggle-track i {
  display: block;
  width: 13px;
  height: 13px;
  border-radius: 50%;
  background: var(--white);
  transition: transform 0.2s ease;
}
.sea-toggle.active .toggle-track {
  background: var(--blue);
}
.sea-toggle.active .toggle-track i {
  transform: translateX(13px);
}
.search-button {
  padding: 0 19px;
  min-height: 56px;
  border: 0;
  border-radius: 14px;
  background: var(--blue);
  color: var(--white);
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 900;
  white-space: nowrap;
}

.trust-strip {
  max-width: 1090px;
  margin: 28px auto 0;
  padding: 0 24px;
  display: flex;
  justify-content: space-between;
  gap: 20px;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}
.trust-strip b {
  width: 21px;
  height: 21px;
  margin-right: 6px;
  border-radius: 50%;
  background: var(--mint);
  color: var(--navy);
  display: inline-grid;
  place-items: center;
}
.coverage-library {
  max-width: 840px;
  margin: 20px auto 0;
  padding: 11px 17px;
  border-radius: 999px;
  background: var(--navy);
  color: #c5d3e1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 14px;
  font-size: 13px;
}
.coverage-library > strong {
  color: var(--mint);
  text-transform: uppercase;
  letter-spacing: 0.09em;
  font-size: 11px;
}
.coverage-library b {
  color: var(--white);
  font-size: 14px;
}

.section {
  max-width: var(--max);
  margin: 0 auto;
  padding: 66px 24px;
}
.section-heading {
  margin-bottom: 30px;
}
.section-heading h2 {
  margin: 8px 0 0;
  max-width: 780px;
  color: var(--navy);
  font-size: clamp(38px, 4.2vw, 56px);
  line-height: 0.98;
  letter-spacing: -0.055em;
  font-weight: 750;
}
.split-heading {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 45px;
}
.split-heading > p {
  max-width: 415px;
  margin: 0 0 4px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.65;
}

.zone-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}
.zone-card {
  min-height: 350px;
  position: relative;
  overflow: hidden;
  padding: 22px;
  border: 1px solid var(--line);
  border-radius: 25px;
}
.sea-zone {
  background: var(--navy);
  color: var(--white);
}
.port-zone {
  background: var(--yellow);
}
.wifi-zone {
  background: #e9e3ff;
}
/*
 * THE LAST SEVEN POINTS OF HOMEPAGE ACCESSIBILITY (Phase 102).
 *
 * Phase 98 got homepage a11y to 97 and could not find what held the remaining three points; a
 * MOBILE Lighthouse run found it immediately. These three ordinals sat at opacity 0.35, which
 * measures 3.19:1 on the navy card, 2.07:1 on the yellow one and 2.04:1 on the lilac — against the
 * 4.5:1 WCAG asks of text. `aria-hidden` was tried first and does not clear it: axe checks contrast
 * on anything visible on screen, hidden from the tree or not, and it is right to.
 *
 * 0.66 is the computed minimum that clears 4.5:1 on all three backgrounds (4.58 / 4.54 / 4.62).
 * The numbers are a little more present than the design drew them. That is the trade, and it is
 * defensible on its own terms: at 2.04:1 the number was invisible to plenty of sighted readers too,
 * which makes it decoration pretending to be information. Revert to 0.35 here if the look matters
 * more than the score — one value, one line, and the score drops back to 97.
 */
.zone-number {
  position: absolute;
  right: 20px;
  top: 18px;
  opacity: 0.66;
  font-size: 13px;
  font-weight: 900;
}
.zone-card svg {
  width: 100%;
  height: 110px;
  margin: 9px 0 4px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.zone-card .mini-ship {
  color: var(--mint);
}
.ship-body {
  fill: currentColor;
  stroke: currentColor;
}
.ship-top {
  fill: none;
}
.zone-card .tag {
  display: inline-flex;
}
.tag {
  width: fit-content;
  padding: 5px 9px;
  border-radius: 999px;
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}
.sea-tag,
.tag.sea-port {
  background: var(--mint);
  color: var(--navy);
}
.port-tag,
.tag.port {
  background: var(--yellow);
  color: var(--navy);
}
.wifi-tag {
  background: var(--purple);
  color: var(--white);
}
.tag.sea {
  background: #ffd6cc;
  color: #7a1c10;
}
.tag.ferry {
  background: #dce9ff;
  /* --blue on this tint is 4.28:1 at 12px, just under AA. --blue-ink is 7.48:1 and reads as the
     same colour family — the other .tag variants already pair a dark ink with their own tint. */
  color: var(--blue-ink);
}
.zone-card h3 {
  margin: 13px 0 7px;
  font-size: 25px;
  letter-spacing: -0.04em;
}
.zone-card p {
  margin: 0;
  max-width: 340px;
  min-height: 66px;
  opacity: 0.72;
  font-size: 14px;
  line-height: 1.6;
}
.zone-card > strong {
  display: block;
  margin-top: 16px;
  font-size: 13px;
}
.handoff-card {
  margin-top: 14px;
  padding: 21px 23px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--foam);
  display: grid;
  grid-template-columns: 0.9fr 1.25fr;
  align-items: center;
  gap: 40px;
}
.handoff-copy {
  display: grid;
  gap: 5px;
}
.handoff-copy > span {
  color: var(--blue);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.handoff-copy strong {
  font-size: 14px;
}
.handoff-copy p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
.handoff-route {
  position: relative;
  padding-top: 23px;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 15px;
}
.handoff-route > div:not(.handoff-line) {
  display: grid;
  gap: 2px;
}
.handoff-route b {
  font-size: 13px;
}
.handoff-route small {
  color: var(--muted);
  font-size: 11px;
}
.handoff-line {
  position: absolute;
  left: 5px;
  right: 5px;
  top: 8px;
  height: 3px;
  border-radius: 999px;
  background: var(--blue);
}
.handoff-line i {
  position: absolute;
  top: -5px;
  width: 13px;
  height: 13px;
  border: 3px solid var(--blue);
  border-radius: 50%;
  background: var(--white);
}
.handoff-line i:first-child {
  left: 0;
}
.handoff-line i:nth-child(2) {
  left: 49%;
}
.handoff-line i:last-child {
  right: 0;
  background: var(--mint);
}

.plans-section {
  scroll-margin-top: 12px;
  padding-top: 42px;
}
.plans-heading {
  align-items: flex-end;
}
.result-summary {
  display: grid;
  justify-items: end;
}
.result-summary span {
  font-size: 14px;
  font-weight: 900;
}
.result-summary small {
  margin-top: 4px;
  color: var(--muted);
  font-size: 13px;
}
.filter-row {
  display: flex;
  gap: 7px;
  margin-bottom: 14px;
}
.filter-row button {
  padding: 8px 13px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: var(--white);
  color: var(--muted);
  font-size: 13px;
  font-weight: 900;
}
.filter-row button.active {
  color: var(--white);
  background: var(--navy);
  border-color: var(--navy);
}
.plan-list {
  display: grid;
  gap: 9px;
}
.plan-row {
  display: grid;
  grid-template-columns: 58px minmax(230px, 1.75fr) minmax(160px, 1fr) minmax(
      150px,
      0.9fr
    ) minmax(125px, 0.7fr) auto;
  align-items: center;
  gap: 16px;
  padding: 16px;
  border: 1px solid var(--line);
  border-radius: 18px;
  background: var(--white);
  box-shadow: 0 8px 24px rgba(22, 55, 91, 0.055);
}
/*
 * The provider mark is now the company's OWN logo, not a two-letter tile.
 *
 * The tile rendered "GI" for GigSky and "AI" for Airalo — ambiguous, and on a comparison row a
 * coloured monogram reads as if it were the company's actual branding. `contain` on a neutral
 * card lets marks of any aspect ratio (square favicons, wide wordmarks) sit correctly without
 * being stretched, and the fixed box means swapping a logo can never shift the row.
 */
.provider-mark {
  /*
   * SHAPED BY THE MARK, NOT BY THE BOX.
   *
   * This was a hard 52x52 square. That is correct for the 26 squarish logos and destroys the other
   * 33: RedteaGO is 7.38:1 and rendered SIX PIXELS TALL inside it, OneRoam 6.86:1, Saily 2.33:1 —
   * which is why a real brand mark read as plain text. `object-fit: contain` was behaving
   * correctly; the box was simply the wrong shape.
   *
   * The width/height attributes now come from the measured ratio (see logoBox in data/logos.ts),
   * so the element reserves its true space and CLS stays at zero. The rules below only constrain
   * the extremes.
   */
  height: 40px;
  max-width: 132px;
  min-width: 40px;
  flex: 0 0 auto;
  border-radius: 14px;
  padding: 5px 8px;
  background: var(--white);
  border: 1px solid var(--line);
  object-fit: contain;
}
.plan-title {
  display: flex;
  gap: 5px;
  align-items: center;
}
.best-chip {
  color: var(--purple);
  font-size: 12px;
  font-weight: 900;
  text-transform: uppercase;
}
.plan-main h3 {
  margin: 7px 0 3px;
  color: var(--navy);
  font-size: 18px;
  letter-spacing: -0.03em;
}
.plan-main h3 span {
  color: var(--muted);
  font-weight: 600;
}
.plan-main p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.45;
}
.plan-spec,
.plan-price {
  display: grid;
  gap: 3px;
}
.plan-spec > span,
.plan-price > span {
  color: var(--muted);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.plan-spec strong {
  color: var(--navy);
  font-size: 14px;
}
.plan-spec small,
.plan-price small {
  color: var(--muted);
  font-size: 11px;
  line-height: 1.35;
}
.plan-price strong {
  color: var(--navy);
  font-size: 18px;
  letter-spacing: -0.03em;
}
.plan-button {
  min-height: 42px;
  padding: 0 14px;
  border-radius: 999px;
  background: var(--navy);
  color: var(--white);
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-size: 13px;
  font-weight: 900;
  transition: transform 0.15s ease;
  white-space: nowrap;
}
.affiliate-note {
  margin: 11px 3px 0;
  color: var(--muted);
  font-size: 12px;
}

.deal-section {
  width: 100%;
  padding: 32px 24px;
  background: var(--yellow);
}
.deal-inner {
  max-width: 1170px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1.4fr auto auto;
  align-items: center;
  gap: 28px;
}
.deal-kicker,
.tool-label {
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
/* On the butter-yellow deal section: --blue is 4.23:1, --blue-ink is 7.40:1. */
.deal-kicker {
  color: var(--blue-ink);
}
/*
 * .tool-label sat on a --blue card in --blue: measured 1.0:1 on the live page, i.e. invisible.
 * That is a rendering bug rather than a contrast preference, so it takes a light foreground.
 */
.tool-label {
  color: var(--white);
}
.deal-copy h2 {
  margin: 6px 0 5px;
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.04em;
}
.deal-copy p {
  margin: 0;
  max-width: 600px;
  color: #5e5c4e;
  font-size: 13px;
  line-height: 1.5;
}
.coupon-ticket {
  min-width: 210px;
  padding: 14px 22px;
  border: 2px dashed var(--navy);
  border-radius: 14px;
  background: rgba(255, 255, 255, 0.5);
  color: var(--navy);
  display: grid;
  gap: 2px;
  text-align: left;
  position: relative;
}
.coupon-ticket::before,
.coupon-ticket::after {
  content: "";
  position: absolute;
  top: 50%;
  width: 14px;
  height: 28px;
  background: var(--yellow);
  border: 2px solid var(--navy);
  border-radius: 999px;
  transform: translateY(-50%);
}
.coupon-ticket::before {
  left: -9px;
  border-left: 0;
}
.coupon-ticket::after {
  right: -9px;
  border-right: 0;
}
.coupon-ticket span {
  font-size: 11px;
  letter-spacing: 0.14em;
  font-weight: 900;
}
.coupon-ticket strong {
  font-family: var(--display);
  font-size: 24px;
  letter-spacing: 0.04em;
}
.coupon-ticket b {
  /* Sits on the butter-yellow ticket: --blue is 4.23:1 at 12px, --blue-ink is 7.40:1. */
  color: var(--blue-ink);
  font-size: 12px;
}

.tools-section {
  padding-bottom: 56px;
}
.tools-grid {
  display: grid;
  grid-template-columns: 1.1fr 0.9fr;
  gap: 14px;
}
.calculator-card,
.device-card {
  min-height: 440px;
  border-radius: 25px;
  overflow: hidden;
}
.calculator-card {
  padding: 29px;
  background: var(--cream);
  border: 1px solid #f2df92;
}
.tool-top {
  display: grid;
  gap: 5px;
}
.tool-top span {
  color: var(--blue);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.13em;
  text-transform: uppercase;
}
.tool-top strong {
  font-family: var(--display);
  font-size: 25px;
}
.range-list {
  display: grid;
  gap: 17px;
  margin-top: 27px;
}
.range-list label {
  display: grid;
  gap: 8px;
}
.range-list label > span {
  display: flex;
  justify-content: space-between;
  color: var(--muted);
  font-size: 13px;
  font-weight: 700;
}
.range-list b {
  color: var(--navy);
}
/*
 * Range sliders measured 314x16px on a 390px layout. Dragging a 16px track is hard on a desk and
 * close to impossible on a moving ship, which is the entire audience for this tool. WCAG 2.5.5
 * asks for 44px; the thumb grows and the track gains vertical padding to reach it without changing
 * the visual weight of the line itself.
 */
.range-list input {
  width: 100%;
  accent-color: var(--blue);
  min-height: 44px;
  padding: 14px 0;
  background: transparent;
}
.range-list input::-webkit-slider-thumb {
  width: 28px;
  height: 28px;
}
.range-list input::-moz-range-thumb {
  width: 28px;
  height: 28px;
}
.calculator-result {
  margin-top: 25px;
  padding: 20px;
  border-radius: 18px;
  background: var(--navy);
  color: var(--white);
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 4px 20px;
  align-items: end;
}
.calculator-result span {
  color: var(--mint);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.calculator-result > strong {
  grid-column: 2;
  grid-row: 1 / 3;
  font-family: var(--display);
  font-size: 53px;
  letter-spacing: -0.05em;
}
.calculator-result p {
  margin: 0;
  font-size: 14px;
  font-weight: 700;
}
.calculator-result small {
  grid-column: 1 / -1;
  margin-top: 7px;
  color: #9fb1c3;
  font-size: 11px;
}
.device-card {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  background: var(--blue);
  color: var(--white);
}
.device-art {
  position: relative;
  min-height: 100%;
  display: grid;
  place-items: center;
  overflow: hidden;
  background: var(--mint);
}
.device-art::before,
.device-art::after {
  content: "";
  position: absolute;
  width: 220px;
  height: 220px;
  border: 2px solid var(--blue);
  border-radius: 50%;
}
.device-art::after {
  width: 155px;
  height: 155px;
}
.device-phone {
  position: relative;
  z-index: 2;
  width: 145px;
  height: 275px;
  border: 7px solid var(--navy);
  border-radius: 30px;
  background: var(--white);
  color: var(--navy);
  display: grid;
  place-items: center;
  align-content: center;
  gap: 8px;
  transform: rotate(-5deg);
  box-shadow: 17px 17px 0 rgba(7, 24, 45, 0.16);
}
.device-phone::before {
  content: "";
  position: absolute;
  top: 9px;
  width: 48px;
  height: 10px;
  border-radius: 999px;
  background: var(--navy);
}
.device-phone span {
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 0.13em;
}
.device-phone b {
  width: 67px;
  height: 67px;
  border-radius: 50%;
  background: var(--mint);
  display: grid;
  place-items: center;
  font-size: 28px;
}
.device-phone small {
  font-size: 11px;
  font-weight: 900;
}
.device-spark {
  position: absolute;
  z-index: 3;
  right: 12%;
  top: 18%;
  color: var(--coral);
  font-size: 38px;
  animation: sparkle 3s ease-in-out infinite;
}
.device-copy {
  padding: 38px 28px;
  align-self: center;
}
.device-copy h3 {
  margin: 8px 0 22px;
  font-size: 32px;
  line-height: 1;
  letter-spacing: -0.045em;
}
.device-copy label {
  display: grid;
  gap: 6px;
}
.device-copy label span {
  /* 3.71:1 on --blue, under AA; #e9f1ff is 4.62 */
  color: #e9f1ff;
  font-size: 12px;
  font-weight: 800;
  text-transform: uppercase;
  letter-spacing: 0.08em;
}
.device-copy select {
  width: 100%;
  min-height: 47px;
  padding: 0 12px;
  border: 0;
  border-radius: 12px;
  color: var(--navy);
  background: var(--white);
  font-size: 13px;
  font-weight: 800;
}
.device-status {
  margin-top: 10px;
  padding: 12px;
  border-radius: 12px;
  background: rgba(7, 24, 45, 0.23);
  display: grid;
  gap: 3px;
}
.device-status b {
  color: var(--mint);
  font-size: 13px;
}
.device-status span {
  /* 3.94:1 on --blue, under AA; #e9f1ff is 4.62 */
  color: #e9f1ff;
  font-size: 12px;
  line-height: 1.4;
}
.device-status.unsure b {
  color: var(--yellow);
}
.device-copy > a {
  margin-top: 16px;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  color: var(--white);
  border-bottom: 1px solid currentColor;
  font-size: 13px;
  font-weight: 900;
}

.usage-band {
  width: 100%;
  min-height: 555px;
  margin-top: 36px;
  background: var(--navy);
  color: var(--white);
  display: grid;
  grid-template-columns: 1fr 1fr;
  position: relative;
  overflow: hidden;
}
.usage-copy {
  max-width: 640px;
  width: 100%;
  justify-self: end;
  padding: 78px 70px 65px 24px;
}
.usage-copy h2 {
  margin: 10px 0 14px;
  max-width: 520px;
  font-size: clamp(43px, 5vw, 65px);
  line-height: 0.98;
  letter-spacing: -0.055em;
}
.usage-copy > p {
  max-width: 470px;
  margin: 0;
  color: #b9c7d6;
  font-size: 14px;
  line-height: 1.65;
}
.usage-pills {
  display: flex;
  gap: 7px;
  margin-top: 24px;
}
.usage-pills button {
  padding: 9px 13px;
  border: 1px solid #38506b;
  border-radius: 999px;
  background: transparent;
  color: #c7d4e1;
  font-size: 13px;
  font-weight: 800;
}
.usage-pills button.active {
  background: var(--mint);
  border-color: var(--mint);
  color: var(--navy);
}
.usage-result {
  margin-top: 16px;
  padding: 16px 18px;
  border: 1px solid #334b65;
  border-radius: 17px;
  display: grid;
  gap: 5px;
}
.usage-result span {
  color: var(--mint);
  font-size: 12px;
  font-weight: 900;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.usage-result strong {
  font-size: 15px;
}
.usage-result small {
  color: #9fb1c3;
  font-size: 12px;
}
.usage-visual {
  min-height: 555px;
  position: relative;
  background: var(--blue);
  overflow: hidden;
}
.phone-card {
  position: absolute;
  z-index: 3;
  width: 230px;
  min-height: 395px;
  left: 50%;
  top: 47px;
  transform: translateX(-50%) rotate(4deg);
  padding: 30px 22px;
  border: 7px solid var(--navy);
  border-radius: 38px;
  background: var(--white);
  color: var(--navy);
  box-shadow: 26px 26px 0 rgba(7, 24, 45, 0.25);
  display: grid;
  align-content: start;
  text-align: center;
}
.phone-card::before {
  content: "";
  width: 66px;
  height: 13px;
  margin: -19px auto 22px;
  border-radius: 99px;
  background: var(--navy);
}
.phone-card > span {
  color: var(--muted);
  font-size: 12px;
  text-transform: uppercase;
  font-weight: 900;
  letter-spacing: 0.1em;
}
.phone-card > strong {
  margin-top: 4px;
  font-size: 20px;
  letter-spacing: -0.04em;
}
.data-ring {
  width: 136px;
  height: 136px;
  margin: 25px auto 20px;
  border: 17px solid var(--mint);
  border-left-color: var(--yellow);
  border-radius: 50%;
  display: grid;
  place-items: center;
  transform: rotate(-18deg);
}
.data-ring b {
  font-size: 27px;
  transform: rotate(18deg);
}
.phone-card small {
  font-size: 13px;
  color: var(--muted);
}
.floating-chip {
  position: absolute;
  z-index: 4;
  padding: 10px 13px;
  border: 3px solid var(--navy);
  border-radius: 12px;
  background: var(--yellow);
  color: var(--navy);
  font-size: 13px;
  font-weight: 900;
  box-shadow: 6px 6px 0 var(--navy);
}
.chip-one {
  left: 9%;
  top: 160px;
  transform: rotate(-6deg);
}
.chip-two {
  right: 8%;
  top: 265px;
  background: var(--mint);
  transform: rotate(6deg);
}
.usage-wave {
  position: absolute;
  z-index: 1;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 190px;
  fill: var(--cyan);
  opacity: 0.42;
}

.destinations {
  padding-bottom: 48px;
}
.region-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}
.region-card {
  min-height: 270px;
  position: relative;
  overflow: hidden;
  border-radius: 23px;
  padding: 0 18px 18px;
  display: grid;
  align-content: end;
  border: 1px solid var(--line);
  transition: transform 0.15s ease;
}
.region-card:hover {
  transform: translateY(-4px);
}
.region-card.coral {
  background: #ffdfd8;
}
.region-card.mint {
  background: #d9ffe2;
}
.region-card.blue {
  background: #dce9ff;
}
.region-card.purple {
  background: #e9e2ff;
}
.route-graphic {
  position: absolute;
  inset: 0 0 auto;
  width: 100%;
  height: 145px;
}
.route-land {
  stroke: none;
  fill: rgba(255, 255, 255, 0.55);
}
.route-line {
  fill: none;
  stroke: var(--navy);
  stroke-width: 2;
  stroke-dasharray: 5 5;
  animation: route-flow 11s linear infinite;
}
.route-graphic circle,
.route-boat {
  fill: var(--navy);
  stroke: none;
}
.route-boat {
  animation: ship-bob 4.8s ease-in-out infinite;
  transform-origin: 145px 64px;
}
.region-card > div {
  position: relative;
  z-index: 2;
}
.region-card > div > span {
  color: var(--muted);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.13em;
}
.region-card h3 {
  margin: 5px 0 4px;
  font-size: 22px;
  letter-spacing: -0.04em;
}
.region-card p {
  margin: 0;
  color: var(--muted);
  font-size: 13px;
}
.region-card > .arrow {
  position: absolute;
  z-index: 3;
  right: 17px;
  bottom: 18px;
  width: 22px;
  height: 22px;
}

.ports-section {
  width: 100%;
  padding: 66px 24px;
  background: var(--navy);
  color: var(--white);
}
.ports-inner {
  max-width: var(--max);
  margin: 0 auto;
}
.ports-section .section-heading h2 {
  color: var(--white);
}
.ports-section .split-heading > p {
  color: #aab9c9;
}
.ports-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 10px;
}
.port-card {
  min-height: 162px;
  padding: 18px;
  border: 1px solid #2d435a;
  border-radius: 18px;
  display: grid;
  grid-template-columns: 58px 1fr auto;
  align-items: center;
  gap: 13px;
  position: relative;
  overflow: hidden;
  background: #0b223b;
  transition:
    background 0.15s ease,
    transform 0.15s ease;
}
.port-card:hover {
  background: #113052;
  transform: translateY(-2px);
}
.port-code {
  position: absolute;
  right: 13px;
  top: 11px;
  color: var(--mint);
  font-size: 11px;
  font-weight: 900;
  letter-spacing: 0.12em;
}
.port-glyph {
  width: 58px;
  height: 58px;
  fill: none;
  stroke: var(--mint);
  stroke-width: 2;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.port-card > div:nth-of-type(2) {
  min-width: 0;
}
.port-card span {
  color: #8ea2b7;
  font-size: 11px;
}
.port-card h3 {
  margin: 4px 0;
  font-size: 19px;
}
.port-card p {
  margin: 0;
  color: #aebdcb;
  font-size: 12px;
}
.port-card > .arrow {
  align-self: end;
  color: var(--mint);
}

.lines {
  padding-top: 64px;
}
.lines-panel {
  min-height: 535px;
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: 0.85fr 1.15fr;
  gap: 65px;
  padding: 55px;
  border-radius: 28px;
  background: var(--blue);
  color: var(--white);
}
.lines-intro {
  align-self: center;
  position: relative;
  z-index: 2;
}
.lines-intro h2 {
  margin: 10px 0 17px;
  font-size: clamp(40px, 4.7vw, 59px);
  line-height: 0.98;
  letter-spacing: -0.055em;
}
.lines-intro p {
  margin: 0 0 24px;
  max-width: 430px;
  /* 4.22:1 on --blue, under AA; #e9f1ff is 4.62 */
  color: #e9f1ff;
  font-size: 14px;
  line-height: 1.65;
}
.line-list {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 7px;
  align-content: center;
}
.line-list a {
  min-height: 55px;
  padding: 0 14px;
  display: grid;
  grid-template-columns: 28px 1fr auto;
  align-items: center;
  gap: 10px;
  border: 1px solid rgba(255, 255, 255, 0.23);
  border-radius: 13px;
  background: rgba(7, 24, 45, 0.18);
  transition: background 0.15s ease;
}
.line-list a:hover {
  background: var(--navy);
}
.line-list span {
  color: var(--mint);
  font-size: 12px;
  font-weight: 900;
}
.line-list strong {
  font-size: 13px;
}
.lines-ship {
  position: absolute;
  left: 29%;
  bottom: -20px;
  opacity: 0.11;
  transform: scale(3.4);
}
.lines-ship .mini-ship {
  color: var(--white);
}
.lines-ship .ship-body {
  fill: currentColor;
}

.dot {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  display: inline-block;
}
.dot.mint {
  background: var(--mint);
  border: 1px solid #5ac678;
}
.dot.yellow {
  background: var(--yellow);
}
.dot.purple {
  background: var(--purple);
}
.dot.coral {
  background: var(--coral);
}

.setup-section {
  width: 100%;
  min-height: 620px;
  margin-top: 35px;
  background: var(--foam);
  display: grid;
  grid-template-columns: 1fr 1fr;
}
.setup-art {
  position: relative;
  overflow: hidden;
  background: var(--yellow);
}
.setup-art > svg {
  position: absolute;
  inset: auto 0 0;
  width: 100%;
  height: 230px;
  fill: var(--blue);
}
.lighthouse {
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: 90px;
  width: 100px;
  height: 330px;
  transform: translateX(-50%);
  background: var(--white);
  clip-path: polygon(25% 0, 75% 0, 100% 100%, 0 100%);
}
.lighthouse::before {
  content: "";
  position: absolute;
  left: -18px;
  right: -18px;
  top: 32px;
  height: 38px;
  background: var(--navy);
  border-radius: 6px;
}
.lighthouse::after {
  content: "";
  position: absolute;
  top: -35px;
  left: 18px;
  width: 64px;
  height: 55px;
  background: var(--navy);
  clip-path: polygon(50% 0, 100% 55%, 90% 100%, 10% 100%, 0 55%);
}
.lighthouse span {
  position: absolute;
  left: 30%;
  right: 30%;
  top: 120px;
  height: 18px;
  background: var(--coral);
}
.lighthouse span::after {
  content: "";
  position: absolute;
  left: -12px;
  right: -12px;
  top: 86px;
  height: 18px;
  background: var(--coral);
}
.lighthouse i {
  position: absolute;
  left: 38px;
  bottom: 17px;
  width: 24px;
  height: 45px;
  background: var(--navy);
  border-radius: 20px 20px 0 0;
}
.setup-content {
  max-width: 640px;
  padding: 74px 24px 65px 70px;
}
.setup-content h2 {
  margin: 9px 0 28px;
  max-width: 540px;
  font-size: clamp(40px, 4.7vw, 59px);
  line-height: 1;
  letter-spacing: -0.055em;
}
.setup-content ol {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 19px 24px;
}
.setup-content li {
  display: flex;
  align-items: flex-start;
  gap: 11px;
}
.setup-content li > span {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--navy);
  color: var(--white);
  display: grid;
  place-items: center;
  flex: none;
  font-size: 13px;
  font-weight: 900;
}
.setup-content li strong {
  font-size: 14px;
}
.setup-content li p {
  margin: 4px 0 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
.safety-note {
  margin-top: 25px;
  padding: 13px 16px;
  border-left: 4px solid var(--coral);
  border-radius: 0 10px 10px 0;
  background: var(--white);
  color: var(--muted);
  font-size: 13px;
  line-height: 1.5;
}
.safety-note strong {
  color: var(--navy);
}

.ferry-section {
  padding-top: 65px;
}
.ferry-card {
  min-height: 420px;
  position: relative;
  overflow: hidden;
  display: grid;
  grid-template-columns: 1.05fr 0.75fr;
  gap: 45px;
  padding: 52px;
  border-radius: 28px;
  background: var(--navy);
  color: var(--white);
}
.ferry-copy,
.ferry-routes {
  position: relative;
  z-index: 3;
}
.ferry-copy h2 {
  margin: 9px 0 14px;
  font-size: clamp(40px, 4.7vw, 58px);
  line-height: 0.98;
  letter-spacing: -0.055em;
}
.ferry-copy p {
  max-width: 420px;
  margin: 0 0 25px;
  color: #b9c9d9;
  font-size: 14px;
  line-height: 1.6;
}
.ferry-routes {
  align-self: center;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 8px;
}
.ferry-routes span {
  padding: 13px;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 12px;
  background: rgba(255, 255, 255, 0.06);
  font-size: 13px;
  font-weight: 800;
}
.ferry-routes small {
  grid-column: 1 / -1;
  margin-top: 4px;
  color: #9caec0;
  font-size: 11px;
}
.ferry-art {
  position: absolute;
  z-index: 1;
  right: -20px;
  bottom: -1px;
  width: 53%;
  height: auto;
  fill: none;
  stroke: var(--mint);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: 0.3;
}
.ferry-sun {
  fill: var(--yellow);
  stroke: none;
}
.ferry-body {
  fill: var(--mint);
  stroke: var(--mint);
  animation: ship-bob 4.8s ease-in-out infinite;
  transform-origin: center;
}
.ferry-wave {
  fill: var(--blue);
  stroke: none;
}
.ferry-windows {
  stroke: var(--navy);
  stroke-width: 8;
}

.faq-section {
  padding-top: 38px;
}
/*
 * Enclosed like the other two FAQ patterns on the site (the shared .faq component and the coupon
 * deck's .coupons-faq-list). It had only a top rule, so it read as loose rows rather than as one
 * list — the odd one out of three.
 */










.ocean-finale {
  width: 100%;
  position: relative;
  overflow: hidden;
  /*
   * The 310px of bottom padding here used to reserve room for the ocean scene, which was
   * absolutely positioned at this section's bottom edge. The scene now lives in the footer so
   * every page ends on water, not just the homepage — so this section keeps only the space its
   * own copy needs. Leaving the old padding in place left a 310px band of empty cream.
   */
  padding: 75px 24px 80px;
  background: var(--cream);
  color: var(--navy);
}
.finale-inner {
  max-width: 1120px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr auto;
  align-items: center;
  gap: 70px;
  position: relative;
  z-index: 4;
}
.finale-copy h2 {
  margin: 9px 0 14px;
  font-size: clamp(48px, 6vw, 76px);
  line-height: 0.91;
  letter-spacing: -0.06em;
}
.finale-copy p {
  max-width: 520px;
  margin: 0 0 24px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.6;
}
.boarding-card {
  width: 320px;
  min-height: 190px;
  padding: 24px;
  border: 3px solid var(--navy);
  border-radius: 20px;
  background: var(--yellow);
  transform: rotate(4deg);
  box-shadow: 12px 12px 0 var(--blue);
  display: grid;
  align-content: space-between;
}
.boarding-card > span {
  font-size: 11px;
  letter-spacing: 0.14em;
  font-weight: 900;
}
.boarding-card div {
  display: grid;
}
.boarding-card div b {
  font-family: var(--display);
  font-size: 25px;
  line-height: 1;
}
.boarding-card div small {
  margin-top: 4px;
  font-size: 13px;
}
.boarding-card > strong {
  width: fit-content;
  padding: 7px 10px;
  border-radius: 999px;
  background: var(--navy);
  color: var(--mint);
  font-size: 13px;
  letter-spacing: 0.1em;
}
.boarding-card i {
  font-style: normal;
  font-size: 11px;
  letter-spacing: 0.13em;
  font-weight: 900;
}
/*
 * The ocean band.
 *
 * .footer-ocean is absolutely positioned, and it used to hang off .ocean-finale — a homepage-only
 * section that supplied both the `position: relative` anchor and, crucially, the `overflow: hidden`
 * that clipped the scene's deliberate 160% overhang on small screens.
 *
 * Moving the scene into the shared footer took both away. With no positioned ancestor the `bottom: 0`
 * resolved against the wrong box, and with nothing clipping it the 600px-wide mobile scene stuck
 * 112px past the right edge of a 375px screen — which made EVERY page horizontally scrollable and
 * shifted the whole layout sideways.
 *
 * This wrapper restores both jobs, so the band works anywhere it is dropped.
 */
.footer-ocean-band {
  position: relative;
  overflow: hidden;
  /*
   * F-01. The band held `height: 350px`. The SVG inside is viewBox 1440x340 with
   * preserveAspectRatio="xMidYMax slice" — `slice` means COVER, so it scales until the artwork
   * fills both axes and crops the rest. A 350px-tall box is only 4.24:1 at exactly 1,483px wide;
   * either side of that, something is lost. Measured: at 1,058px the lighthouse lost 108px and the
   * buoy left the frame entirely; at 1,905px the ship's crown sat 90px above the visible area with
   * the mast and signal arcs gone. Nobody sees the whole drawing.
   *
   * Locking the box to the artwork's own ratio removes the drift — which is exactly what the
   * mobile rule below already does with `height: 36vw`. This is that fix, generalised.
   */
  aspect-ratio: 1440 / 340;
  height: auto;
  /* Full-bleed past .site-footer's 24px side padding, so the sea reaches both edges. */
  width: calc(100% + 48px);
  margin: 0 -24px;
  background: var(--cream);
  line-height: 0;
}
.footer-ocean {
  position: absolute;
  z-index: 2;
  left: 0;
  bottom: 0;
  width: 100%;
  /*
   * F-01, second half. Locking the BAND to 1440/340 was necessary and not sufficient: the SVG
   * itself still carried `height: 350px`, so at 1,058px it rendered 350px tall inside a 250px
   * band and `slice` cropped exactly as before — the lighthouse measured at left -108px on the
   * live page, which is the audit's own figure to the pixel.
   *
   * Filling the band is what makes the ratio lock actually take effect.
   */
  height: 100%;
  overflow: visible;
}
.footer-sun {
  fill: var(--yellow);
}
.footer-cloud {
  fill: var(--white);
  opacity: 0.9;
}
.footer-lighthouse {
  fill: var(--white);
  stroke: var(--navy);
  stroke-width: 4;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.footer-lighthouse .light-beam {
  fill: rgba(255, 231, 119, 0.42);
  stroke: none;
  animation: lighthouse-beam 5.5s ease-in-out infinite;
  transform-origin: 160px 104px;
}
.footer-cruise {
  fill: none;
  stroke: var(--navy);
  stroke-width: 5;
  stroke-linecap: round;
  stroke-linejoin: round;
  animation: footer-ship-bob 4.8s ease-in-out infinite;
  transform-origin: 850px 180px;
}
.cruise-hull {
  fill: var(--white);
}
.cruise-deck,
.cruise-top {
  fill: var(--mint);
}
.cruise-windows {
  stroke-width: 7;
}
.cruise-signal {
  stroke: var(--blue);
  animation: signal-pulse 2.8s ease-out infinite;
}
.footer-buoy {
  fill: var(--coral);
  stroke: var(--navy);
  stroke-width: 4;
}
.footer-wave {
  transform-origin: center bottom;
}
.wave-a {
  fill: var(--cyan);
  animation: wave-drift 12s ease-in-out infinite alternate;
}
.wave-b {
  fill: var(--blue);
  animation: wave-drift-back 14s ease-in-out infinite alternate;
}
.wave-c {
  fill: var(--navy);
}

.site-footer {
  width: 100%;
  margin: 0;
  padding: 0 24px 26px;
  background: var(--navy);
  color: var(--white);
}
.footer-main {
  max-width: var(--max);
  margin: 0 auto;
  padding: 61px 0 48px;
  display: grid;
  grid-template-columns: 1.7fr repeat(4, 1fr);
  gap: 48px;
}
.footer-main .brand {
  color: var(--white);
}
.footer-brand p {
  max-width: 310px;
  margin: 15px 0 13px;
  color: #9fb0c1;
  font-size: 14px;
  line-height: 1.6;
}
.footer-checked {
  color: var(--mint);
  font-size: 12px;
}
.footer-main > div:not(.footer-brand) {
  display: grid;
  align-content: start;
  gap: 13px;
}
.footer-main > div > strong {
  margin-bottom: 4px;
  color: var(--mint);
  font-size: 13px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}
.footer-main > div > a:not(.brand) {
  color: #bac7d3;
  font-size: 14px;
}
.footer-main > div > a:hover {
  color: var(--white);
}
/* ----------------------------------------------------------------- guides strip (Phase 79)
 *
 * An UNNUMBERED homepage section, matching the design's own "Ferry finder" block rather than
 * becoming an eleventh numbered step — the 01–10 sequence is deliberate and gaps in it read as a
 * fault. Three cards, one per guide.
 *
 * Built from tokens the design already defines so it cannot drift from the rest of the page, and
 * grid-auto-fit so it stacks cleanly on a phone without a media query.
 */
.guides-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px;
  margin-top: 28px;
}
.guide-card {
  display: block;
  position: relative;
  padding: 26px 26px 58px;
  border: 1px solid rgba(7, 24, 45, 0.1);
  border-radius: 24px;
  background: var(--white, #fff);
  color: inherit;
  text-decoration: none;
  transition:
    transform 0.18s ease,
    box-shadow 0.18s ease;
}
.guide-card:hover,
.guide-card:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 18px 40px rgba(7, 24, 45, 0.1);
}
.guide-card span {
  display: inline-block;
  margin-bottom: 12px;
  font-size: 11px;
  font-weight: 800;
  letter-spacing: 0.1em;
  color: #0b3fa8;
}
.guide-card h3 {
  margin: 0 0 10px;
  font-size: 21px;
  line-height: 1.25;
}
.guide-card p {
  margin: 0;
  font-size: 15px;
  line-height: 1.55;
  color: #4a5a6e;
}
.guide-card .arrow {
  position: absolute;
  bottom: 24px;
  left: 26px;
  width: 22px;
  height: 22px;
}

/*
 * The sitewide trust strip (Phase 78). Sits between the link columns and the legal line.
 *
 * Every item is a link to the page that substantiates the claim, which is what separates this from
 * a row of badges. Wraps rather than scrolls: four short items fit two lines on a 320px screen.
 */
.footer-trust {
  max-width: var(--max);
  margin: 0 auto;
  padding: 18px 0 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px 22px;
  font-size: 13px;
}
.footer-trust a {
  color: #b9c9d9;
  text-decoration: none;
  /* 44px touch target without a 44px-tall visual band. */
  padding: 12px 0;
  margin: -12px 0;
}
.footer-trust a:hover,
.footer-trust a:focus-visible {
  color: var(--white);
  text-decoration: underline;
}

/*
 * F-08, second pass. The audit named 27 footer links at 22px and called them "the only thing
 * keeping the homepage off a perfect accessibility score". The footer half was right and the
 * "only" was not: after fixing those, a live sweep found five more interactive targets under
 * 24x24 — the offer-bar CTA at 18px, both `.text-link` variants at 22px, and the tool link at
 * 19px. None are in the footer, which is why an audit looking at the footer missed them.
 *
 * WCAG 2.2 exempts links inline in a sentence, so the one genuinely inline case is left alone —
 * padding it would break the line box of the paragraph it sits in for no accessibility gain.
 */
.offer-bar a,
.text-link {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
}

/*
 * F-08. Footer nav rows measured 22px tall — under the WCAG 2.2 target-size minimum of 24x24 CSS
 * px, and the only thing keeping the homepage off a perfect accessibility score (Lighthouse 97 on
 * / against 100 on /gigsky). 27 links affected.
 *
 * `inline-flex` + `align-items` rather than a bare min-height: on an inline element min-height has
 * no effect, so the box has to become flex to take one.
 */
.footer-main a,
.footer-bottom a {
  display: inline-flex;
  align-items: center;
  min-height: 24px;
  padding-block: 2px;
}

.footer-bottom {
  max-width: var(--max);
  margin: 0 auto;
  padding-top: 18px;
  border-top: 1px solid #2b4057;
  display: flex;
  justify-content: space-between;
  color: #7f93a8;
  font-size: 13px;
}

@keyframes hero-reveal {
  from {
    opacity: 0;
    filter: blur(8px);
    transform: scale(1.02);
  }
  to {
    opacity: 1;
    filter: blur(0);
    transform: scale(1);
  }
}
@keyframes rise-in {
  from {
    opacity: 0;
    transform: translateY(16px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}
@keyframes route-flow {
  to {
    stroke-dashoffset: -200;
  }
}
@keyframes route-dot {
  50% {
    transform: scale(1.6);
    opacity: 0.55;
  }
}
@keyframes ship-bob {
  50% {
    transform: translateY(-6px) rotate(-1deg);
  }
}
@keyframes footer-ship-bob {
  50% {
    transform: translateY(-7px) rotate(-0.7deg);
  }
}
@keyframes wave-drift {
  to {
    transform: translateX(10px) scaleX(1.01);
  }
}
@keyframes wave-drift-back {
  to {
    transform: translateX(-11px) scaleX(1.012);
  }
}
@keyframes signal-pulse {
  50% {
    opacity: 0.45;
  }
}
@keyframes sparkle {
  50% {
    transform: rotate(20deg) scale(1.25);
    opacity: 0.55;
  }
}
@keyframes lighthouse-beam {
  50% {
    transform: rotate(9deg);
    opacity: 0.55;
  }
}

@media (max-width: 1160px) {
  .hero-panel {
    width: 61%;
    padding-right: 92px;
  }
  .hero-photo {
    left: 45%;
  }
  .finder-grid {
    grid-template-columns: repeat(5, 1fr);
  }
  .sea-toggle {
    grid-column: span 3;
  }
  .search-button {
    grid-column: span 2;
  }
  .plan-row {
    grid-template-columns: 52px minmax(230px, 1.7fr) 1fr 1fr auto;
  }
  /*
   * The price used to be `display: none` here — on a price-comparison site, at every width below
   * 1160px, which is tablets, small laptops, split-screen windows and every phone. A visitor could
   * not compare anything; they could only click out to the provider and find the price there,
   * which is the one place the comparison earns nothing.
   *
   * It moves under the plan name instead of disappearing.
   */
  .plan-price {
    grid-column: 2 / -1;
    grid-row: 2;
    display: flex;
    align-items: baseline;
    gap: 8px;
    margin-top: 6px;
  }
  .region-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .region-card {
    min-height: 240px;
  }
  .footer-main {
    grid-template-columns: 1.6fr repeat(4, 1fr);
    gap: 26px;
  }
}

@media (max-width: 900px) {
  /*
   * The offer bar kept the code but dropped the reason to use it — "Save 10% on selected cruise
   * plans" was the value proposition and it was the part being hidden. Shortened, not removed.
   */
  .offer-bar span:not(.offer-bar-tag) {
    font-size: 12px;
  }

  .plan-spec > span,
  .plan-price > span {
    font-size: 11px;
  }
  .plan-spec strong,
  .plan-price strong {
    font-size: 16px;
  }
  /* The price is the reason the row exists — make it the biggest thing in it on mobile. */
  .plan-price strong {
    font-size: 22px;
  }
  .plan-spec small {
    flex-basis: 100%;
  }
  .site-header {
    height: 65px;
    padding: 0 18px;
  }
  .site-header nav {
    display: none;
    position: absolute;
    top: 64px;
    left: 16px;
    right: 16px;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--white);
    box-shadow: 0 18px 45px rgba(7, 24, 45, 0.15);
  }
  .site-header nav.nav-open {
    display: grid;
  }
  .site-header nav a {
    padding: 12px 10px;
  }
  .site-header nav a::after {
    display: none;
  }
  /*
   * The primary CTA used to vanish here, leaving the mobile header as logo + hamburger with no
   * persistent path into the funnel across a page ~17 phone-screens tall. Kept, compacted.
   */
  .header-cta {
    padding: 0 13px;
    font-size: 13px;
    min-height: 38px;
  }
  .header-cta .arrow {
    display: none;
  }
  .menu-button {
    display: block;
  }
  .hero {
    min-height: 760px;
  }
  .hero-photo {
    inset: 0;
    background-position: 65% center;
  }
  .hero-photo::after {
    background: rgba(7, 24, 45, 0.25);
  }
  .hero-panel {
    width: 73%;
    min-height: 760px;
    padding: 83px 85px 155px 24px;
    background: rgba(7, 24, 45, 0.94);
    clip-path: ellipse(105% 78% at 0 50%);
  }
  .hero h1 {
    font-size: clamp(55px, 8vw, 72px);
  }
  .hero-stamp {
    right: 22px;
  }
  .hero-route {
    width: 65%;
  }
  .hero-location {
    right: 135px;
  }
  .finder-wrap {
    margin-top: -65px;
    padding: 0 16px;
  }
  .finder-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .finder-grid label:nth-child(5) {
    grid-column: span 2;
  }
  .sea-toggle,
  .search-button {
    grid-column: span 1;
  }
  .coverage-library {
    max-width: calc(100% - 32px);
    flex-wrap: wrap;
    border-radius: 18px;
    justify-content: center;
  }
  .section {
    padding: 56px 18px;
  }
  .zone-grid {
    grid-template-columns: 1fr;
  }
  .zone-card {
    min-height: 250px;
    padding-left: 46%;
  }
  .zone-card svg,
  .zone-card .zone-icon {
    position: absolute;
    left: 18px;
    top: 55px;
    width: 40%;
  }
  .zone-card p {
    min-height: 0;
  }
  .plan-row {
    grid-template-columns: 52px 1fr;
    row-gap: 10px;
  }
  /*
   * Data and validity were also hidden here. With the price rule above, a phone user comparing two
   * plans saw the provider name and nothing else — both differentiators gone.
   *
   * Reflowed into label-value pairs rather than hidden. Hiding spec data on the narrow layout is
   * never the right answer on a comparison table; it is the layout most people are using.
   */
  .plan-spec {
    grid-column: 2 / -1;
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 4px 8px;
  }
  .plan-button {
    grid-column: 2 / 4;
    width: fit-content;
  }
  .deal-inner {
    grid-template-columns: 1fr auto;
  }
  .deal-inner .dark-button {
    grid-column: 1 / -1;
    width: fit-content;
  }
  .tools-grid {
    grid-template-columns: 1fr;
  }
  .device-card {
    min-height: 420px;
  }
  .usage-band {
    grid-template-columns: 1fr;
  }
  .usage-copy {
    max-width: none;
    padding: 58px 24px 45px;
  }
  .usage-visual {
    min-height: 500px;
  }
  .ports-grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .lines-panel {
    grid-template-columns: 1fr;
    padding: 42px 30px;
    gap: 25px;
  }
  .setup-section {
    grid-template-columns: 0.75fr 1.25fr;
  }
  .setup-content {
    padding-left: 40px;
  }
  .ferry-card {
    grid-template-columns: 1fr;
  }
  .ferry-routes {
    max-width: 430px;
  }
  .ferry-art {
    width: 70%;
    opacity: 0.15;
  }
  .footer-main {
    grid-template-columns: 1.4fr repeat(2, 1fr);
  }
  .footer-brand {
    grid-row: span 2;
  }
}

@media (max-width: 640px) {
  .offer-bar {
    justify-content: space-between;
    padding: 6px 14px;
    gap: 8px;
  }
  .offer-bar strong {
    font-size: 11px;
  }
  .offer-bar a {
    font-size: 13px;
  }
  .brand {
    font-size: 20px;
  }
  .mark {
    width: 36px;
    height: 36px;
    border-radius: 12px;
  }
  .hero {
    min-height: 830px;
    background: var(--navy);
  }
  .hero-photo {
    inset: 0 0 auto;
    height: 43%;
    background-position: 67% 42%;
  }
  .hero-photo::after {
    background: rgba(7, 24, 45, 0.04);
  }
  .hero-panel {
    position: absolute;
    inset: auto 0 0;
    width: 100%;
    min-height: 65%;
    padding: 78px 18px 140px;
    background: var(--navy);
    /*
     * MOBILE HEADLINE CLIP FIX (2026-08-13).
     *
     * The original `ellipse(92% 78% at 50% 100%)` put the shape's top edge roughly 126px into a
     * 571px panel on a 390px viewport — below where the headline starts. The first line of
     * "Internet that / sails with you." rendered outside the navy fill, over the photograph, and
     * read as though it had been sliced in half.
     *
     * Widening the horizontal radius and raising the vertical one keeps the organic curve at the
     * corners while flattening it across the middle, so the copy always sits on navy. The shape
     * is still visibly curved; it simply no longer crops the text.
     */
    clip-path: ellipse(150% 92% at 50% 100%);
  }
  .hero h1 {
    margin-top: 14px;
    font-size: clamp(47px, 13vw, 58px);
  }
  .hero-panel > p {
    max-width: 440px;
    font-size: 14px;
  }
  .hero-actions {
    align-items: flex-start;
    flex-direction: column;
    gap: 17px;
    margin-top: 22px;
  }
  .hero-proof {
    margin-top: 22px;
  }
  .hero-route {
    top: 10px;
    right: -100px;
    width: 120%;
    height: 260px;
  }
  .hero-stamp {
    width: 76px;
    height: 76px;
    right: 13px;
    top: 32px;
    bottom: auto;
  }
  .hero-location,
  .hero-spark {
    display: none;
  }
  .finder-wrap {
    margin-top: -48px;
  }
  .finder-card {
    padding: 17px;
    border-radius: 21px;
  }
  .journey-tabs {
    width: 100%;
  }
  .journey-tabs button {
    flex: 1;
  }
  /*
   * Stack the heading on a phone instead of setting the note beside it.
   *
   * The note used to be squeezed into a 110px column next to the h2. At 13px that wrapped to four
   * lines, which both crushed "Where are you cruising?" into a narrow column and made the pill
   * taller than the heading it was annotating. Below the heading it reads as one line of context,
   * which is what it is.
   */
  .finder-heading {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  .finder-heading h2 {
    font-size: 21px;
  }
  .finder-note {
    align-self: flex-start;
    line-height: 1.3;
  }
  /*
   * One field per row on a phone.
   *
   * The two-column version left each select about 130px wide, which was survivable at the old 12px
   * but not once form controls went to 16px (below that, iOS zooms the page on focus). At 16px
   * "Royal Caribbean" and "Icon of the Seas" were both cut off mid-word with the dropdown chevron
   * pushed out of the box entirely — the finder is the first thing anyone touches, so it has to be
   * readable before it is compact.
   *
   * NOTE: the old `grid-column: span 2` rules had to go with the second column. Spanning two
   * columns in a one-column grid makes the browser generate an implicit second column, which would
   * have quietly rebuilt the two-column layout this rule exists to remove.
   */
  .finder-grid {
    grid-template-columns: 1fr;
  }
  /*
   * Undo every span from the wider breakpoints. The 900px block still spans label 5 across two
   * columns, and a two-column span inside a one-column grid makes the browser invent an implicit
   * second column — which is exactly how this rule's first attempt ended up at "106px 238px" and
   * clipped "Royal Caribbean" all over again.
   */
  .finder-grid > *,
  .sea-toggle,
  .search-button {
    grid-column: auto;
  }
  /*
   * Repeated at the 900px rule's own specificity. `.finder-grid > *` is (0,1,0) and loses to
   * `.finder-grid label:nth-child(5)` at (0,2,1) no matter how late it appears, so the span
   * survived the reset above and kept inventing the second column.
   */
  .finder-grid label:nth-child(5) {
    grid-column: auto;
  }
  .finder-grid label {
    padding: 9px 12px;
  }
  .search-button {
    min-height: 51px;
  }
  .trust-strip {
    margin-top: 20px;
    padding: 0 16px;
    flex-wrap: wrap;
    justify-content: center;
    gap: 10px 17px;
    font-size: 12px;
  }
  .trust-strip b {
    width: 18px;
    height: 18px;
  }
  .coverage-library {
    justify-content: flex-start;
    padding: 14px 16px;
  }
  .coverage-library > strong {
    width: 100%;
  }
  .section {
    padding: 46px 16px;
  }
  .section-heading {
    margin-bottom: 22px;
  }
  .section-heading h2 {
    font-size: 39px;
  }
  .split-heading {
    display: block;
  }
  .split-heading > p,
  .split-heading > .text-link,
  .result-summary {
    margin-top: 14px;
  }
  .result-summary {
    justify-items: start;
  }
  .zone-card {
    min-height: 315px;
    padding: 18px;
    padding-top: 140px;
  }
  .zone-card svg,
  .zone-card .zone-icon {
    width: 60%;
    top: 28px;
    left: 20%;
  }
  .handoff-card {
    grid-template-columns: 1fr;
    gap: 18px;
    padding: 17px;
  }
  .filter-row {
    overflow-x: auto;
    padding-bottom: 4px;
  }
  .filter-row button {
    flex: none;
  }
  .plan-row {
    grid-template-columns: 48px 1fr;
    gap: 12px;
    padding: 14px;
  }
  .provider-mark {
    width: 46px;
    height: 46px;
  }
  .plan-main h3 {
    font-size: 16px;
  }
  .plan-button {
    grid-column: 1 / 3;
    width: 100%;
    justify-content: center;
  }
  .deal-section {
    padding: 31px 16px;
  }
  .deal-inner {
    grid-template-columns: 1fr;
    gap: 18px;
  }
  .deal-copy h2 {
    font-size: 29px;
  }
  .coupon-ticket {
    width: 100%;
  }
  .deal-inner .dark-button {
    grid-column: auto;
    width: 100%;
  }
  .tools-grid {
    gap: 10px;
  }
  .calculator-card {
    padding: 21px;
  }
  .calculator-result {
    grid-template-columns: 1fr;
  }
  .calculator-result > strong {
    grid-column: 1;
    grid-row: auto;
    font-size: 47px;
  }
  .device-card {
    grid-template-columns: 1fr;
  }
  .device-art {
    min-height: 330px;
  }
  .device-phone {
    transform: rotate(-3deg) scale(0.88);
  }
  .device-copy {
    padding: 30px 21px;
  }
  .usage-band {
    margin-top: 18px;
  }
  .usage-copy {
    padding: 50px 18px 40px;
  }
  .usage-copy h2 {
    font-size: 43px;
  }
  .usage-pills {
    flex-wrap: wrap;
  }
  .usage-result strong {
    font-size: 14px;
  }
  .usage-visual {
    min-height: 450px;
  }
  .phone-card {
    transform: translateX(-50%) rotate(2deg) scale(0.9);
    transform-origin: top;
  }
  .chip-one {
    left: 4%;
  }
  .chip-two {
    right: 3%;
  }
  .region-grid {
    grid-template-columns: 1fr;
  }
  .region-card {
    min-height: 220px;
  }
  .ports-section {
    padding: 48px 16px;
  }
  .ports-grid {
    grid-template-columns: 1fr;
  }
  .port-card {
    min-height: 145px;
  }
  .lines-panel {
    padding: 35px 18px;
    border-radius: 22px;
  }
  .lines-intro h2 {
    font-size: 42px;
  }
  .line-list {
    grid-template-columns: 1fr;
  }
  /*
   * This hid Disney, Virgin Voyages, Cunard and Holland America from phone users with no "view all"
   * anywhere in the module — two of the highest-intent brands in the niche, invisible on the
   * layout most people browse on. The list scrolls now instead of truncating.
   */
  .line-list {
    grid-auto-flow: column;
    grid-auto-columns: minmax(160px, 1fr);
    grid-template-columns: none;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 6px;
  }
  .line-list a {
    scroll-snap-align: start;
  }
  .setup-section {
    grid-template-columns: 1fr;
  }
  .setup-art {
    min-height: 360px;
  }
  .setup-content {
    padding: 48px 18px;
  }
  .setup-content h2 {
    font-size: 41px;
  }
  .setup-content ol {
    grid-template-columns: 1fr;
  }
  .ferry-section {
    padding-top: 45px;
  }
  .ferry-card {
    min-height: 570px;
    padding: 35px 20px;
    border-radius: 22px;
  }
  .ferry-copy h2 {
    font-size: 43px;
  }
  .ferry-art {
    width: 110%;
    opacity: 0.18;
  }


  .ocean-finale {
    padding: 55px 16px 60px;
  }
  .finale-inner {
    grid-template-columns: 1fr;
    gap: 32px;
  }
  .finale-copy h2 {
    font-size: 49px;
  }
  .boarding-card {
    width: min(310px, 94%);
    justify-self: center;
    transform: rotate(2deg);
  }
  /*
   * Mobile framing.
   *
   * The full 1440-wide scene shrunk to a phone would be specks, so the band crops in. Getting that
   * crop to hold still takes care: with preserveAspectRatio="slice" the visible slice depends on
   * the box's ASPECT RATIO, so a fixed pixel height with a percentage width re-frames the picture
   * at every screen size — at 375px it sliced the ship in half.
   *
   * Sizing the height in vw instead makes height and width scale together, so these three numbers
   * frame the same window (viewBox x 300-1250: the whole ship, the sun, and the full wave stack)
   * on every phone from 320px up. The 118%/-15% pair also guarantees the artwork still covers the
   * right edge, so no cream shows through beneath the waves.
   */
  .footer-ocean-band {
    height: 36vw;
    /* .site-footer drops to 18px of side padding at this width, so the bleed has to match. */
    width: calc(100% + 36px);
    margin: 0 -18px;
  }
  .footer-ocean {
    height: 36vw;
    width: 118%;
    left: -15%;
  }
  .site-footer {
    padding: 0 18px 24px;
  }
  .footer-main {
    grid-template-columns: 1fr 1fr;
    gap: 35px 20px;
    padding-top: 48px;
  }
  .footer-brand {
    grid-column: 1 / -1;
    grid-row: auto;
  }
  .footer-bottom {
    display: grid;
    gap: 7px;
  }
}

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

/* Standalone-export accessibility and resilience additions. */
.skip-link {
  position: fixed;
  z-index: 9999;
  top: 10px;
  left: 10px;
  padding: 11px 16px;
  border-radius: 999px;
  background: #fff;
  color: #07182d;
  font-weight: 800;
  transform: translateY(-150%);
  transition: transform 0.15s ease;
}
.skip-link:focus {
  transform: translateY(0);
}
/*
 * Two-tone focus ring.
 *
 * The cyan ring measured 1.70:1 on white and 1.59:1 on the cream tool card — WCAG 2.4.11 requires
 * 3:1, so on light surfaces it was effectively decorative. A single colour cannot pass on both a
 * white page and a navy footer, so this uses the standard two-tone technique: a navy inner ring
 * that carries on light backgrounds (17.8:1 on white) and the cyan outer ring that carries on dark.
 */
:where(a, button, select, input, summary):focus-visible {
  outline: 2px solid var(--navy, #07182d);
  outline-offset: 2px;
  box-shadow: 0 0 0 5px #00d9ff;
  border-radius: 3px;
}
button {
  touch-action: manipulation;
}
.line-show-all {
  display: none;
  width: 100%;
  min-height: 46px;
  margin-top: 4px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 999px;
  background: transparent;
  color: #fff;
  font: 800 12px var(--sans);
  cursor: pointer;
}
svg [class*="ship"],
svg [class*="cruise"],
svg [class*="lighthouse"],
svg [class*="buoy"] {
  transform-box: fill-box;
}
@media (max-width: 640px) {
  /*
   * TOUCH TARGETS AND TYPE FLOOR (16 Aug 2026 audit).
   *
   * 51 interactive elements measured below the 44px WCAG 2.5.5 minimum at 390px — selects at 23px,
   * footer links at 18-19px, filter chips at 31-37px. And 199 text elements were 13px or smaller
   * against only 41 at 16px, on a site whose cruise audience skews 45+. The smallest text was
   * carrying real meaning: fair-use caveats, "Check live before buying", carrier names, the
   * source-check date.
   */
  .finder-grid select,
  .finder-grid label {
    min-height: 44px;
  }
  .filter-chip,
  .sort-tab {
    min-height: 44px;
    display: inline-flex;
    align-items: center;
  }
  .site-footer a {
    display: inline-block;
    padding: 7px 0;
  }
  .text-link {
    display: inline-block;
    padding: 6px 0;
  }
  /* Floor the body copy. 12px stays available for genuine legal fine print only. */
  .plan-main p,
  .card p,
  .lede,
  .prose p,
  .prose li {
    font-size: 15px;
  }
  small,
  .tiny {
    font-size: 13px;
  }

  .line-show-all {
    display: block;
  }
  .lines-panel.lines-expanded .line-list a:nth-child(n + 7) {
    display: grid;
  }
  .lines-panel.lines-expanded .line-show-all {
    display: none;
  }
}
@supports not (overflow-x: clip) {
  html,
  body {
    overflow-x: hidden;
  }
}


/*
 * Empty state for the plan list.
 *
 * The "Port only" filter correctly returns nothing — port-day picks are curated per destination
 * rather than stored as priced plans — so the list needs something to say rather than collapsing
 * to a blank box. Styled as a quiet card so it reads as an explanation, not an error.
 */
.plan-empty {
  border: 1px solid var(--border-blue, #d8e6f8);
  border-radius: 23px;
  background: var(--foam, #f6fbff);
  padding: clamp(1.5rem, 4vw, 2.25rem);
  text-align: left;
}
.plan-empty h3 {
  margin: 0 0 0.5rem;
  font-family: "Bricolage Grotesque", system-ui, sans-serif;
  font-size: 1.15rem;
}
.plan-empty p {
  margin: 0 0 1rem;
  max-width: 62ch;
  color: var(--main-ink, #102642);
}
.plan-empty .plan-button {
  display: inline-flex;
}

/* ---------------- CSS-only mobile menu (site-wide chrome) ---------------- */

/*
 * The prototype toggled the mobile nav with JavaScript. That is fine on the homepage, which ships
 * a bundle anyway, but this header now renders on all 194 pages and the rest of the site is
 * deliberately script-free — shipping JS everywhere just to open a menu would mean relaxing
 * `script-src 'none'` site-wide for one interaction.
 *
 * A hidden checkbox holds the state instead. The label is focusable and toggles on Enter/Space,
 * so it behaves like the button it replaces without a line of script.
 */
/*
 * The menu control.
 *
 * It was a 1x1px checkbox — focusable, but with a target no pointer could hit and a focus ring
 * with nowhere to render. It is now the full size of the visible button and sits exactly on top of
 * it, so the thing keyboard users focus and the thing sighted users tap are the same rectangle.
 *
 * It stays a checkbox rather than becoming a <button aria-expanded>: the menu is deliberately
 * CSS-only so 207 pages ship no JavaScript and keep `script-src 'none'`, and aria-expanded cannot
 * be maintained without script. A checkbox announces its own checked state, which conveys
 * open/closed — different semantics from a disclosure button, but not a silent control.
 */
.nav-toggle {
  position: absolute;
  top: 0;
  right: 14px;
  width: 44px;
  height: 44px;
  margin: 0;
  opacity: 0;
  cursor: pointer;
  z-index: 3;
}

/* Keyboard focus has to be visible on the label, since the input itself is hidden. */
.nav-toggle:focus-visible ~ .site-header .menu-button {
  outline: 2px solid var(--navy, #07182d);
  outline-offset: 3px;
  box-shadow: 0 0 0 5px #00d9ff;
}

@media (max-width: 1200px) {
  /*
   * F-02 — THE HEADER DEAD ZONE.
   *
   * The disclosure nav used to take over at 900px, but the full nav needs about 1,183px to sit on
   * one line: links 768px + gaps, logo 170px, CTA 101px, padding 48px. That left a 283px dead zone
   * from 901 to 1,183px — iPad landscape, 1152x864 laptops, and any half-screen window on a 1440
   * or 1920 display. Measured at 1,073px: the nav box was 106px tall inside a 72px header, with
   * "Cruise lines" on two lines, "How it works" on three, and two links overflowing the header's
   * bottom edge by 8px and 17px.
   *
   * Only the NAV rules are raised to 1,200px. The rest of the 900px block is phone layout — hero
   * heights, grid collapses — and lifting all of it would apply phone styling to an iPad.
   */
  .site-header nav {
    display: none;
    position: absolute;
    top: 64px;
    left: 16px;
    right: 16px;
    padding: 10px;
    border: 1px solid var(--line);
    border-radius: 16px;
    background: var(--white);
    box-shadow: 0 18px 45px rgba(7, 24, 45, 0.15);
  }
  .site-header nav.nav-open,
  .nav-toggle:checked ~ .site-header nav {
    display: grid;
  }
  .site-header nav a {
    padding: 12px 10px;
  }
  .site-header nav a::after {
    display: none;
  }
  .menu-button {
    display: block;
  }
}

@media (max-width: 900px) {
  /*
   * The band still needs the vw treatment below 900px: `aspect-ratio` handles the desktop drift,
   * but the mobile rule also reframes the scene (118%/-15% on .footer-ocean) to keep the ship,
   * sun and lighthouse in view on a narrow screen, which a pure ratio lock would not do.
   */
  .footer-ocean-band {
    aspect-ratio: auto;
  }
  .footer-ocean-band,
  .footer-ocean {
    height: 36vw;
  }

  /*
   * grid, not flex — this must match the design's own open state (`nav.nav-open { display: grid }`).
   * The nav's base rule is `display: flex` with the default row direction, so opening it as a flex
   * container laid all seven links out in a single row: "Ports" was clipped at the screen edge and
   * Ferries, Coupons and How it works were off-screen entirely, with no way to reach them.
   */
  .nav-toggle:checked ~ .site-header nav {
    display: grid;
  }
  /* Turn the two bars into a cross while open, so the control reads as "close". */
  .nav-toggle:checked ~ .site-header .menu-button span:first-child {
    transform: translateY(3px) rotate(45deg);
  }
  .nav-toggle:checked ~ .site-header .menu-button span:last-child {
    transform: translateY(-3px) rotate(-45deg);
  }
}

/*
 * Form controls at 16px.
 *
 * Not a style preference: iOS Safari zooms the entire page when you focus an input smaller than
 * 16px, and it does not zoom back out. The finder is the first thing a visitor touches, so the
 * page was lurching sideways on the very first tap. 16px is the documented threshold.
 */
.finder-grid select,
.device-copy select,
.finder-grid input,
.search-button {
  font-size: 16px;
}

/* ---------------------------------------------------------------------------
   Phone chrome (<=430px).

   At 375px the offer bar wrapped "Get the deal" onto three lines and the header
   CTA broke "Find my plan" across two, because both were sized for a 900px
   layout. Measured on a real 375px viewport.
   --------------------------------------------------------------------------- */
@media (max-width: 430px) {
  .offer-bar {
    gap: 8px;
    padding: 6px 12px;
    font-size: 12px;
  }
  .offer-bar strong {
    padding: 3px 8px;
    font-size: 11px;
    letter-spacing: 0.04em;
  }
  .offer-bar a {
    white-space: nowrap;
    font-size: 12px;
  }
  /* The strapline is the first thing to go when there is genuinely no room —
     the code and the link still carry the offer. */
  .offer-bar > span:not(.offer-bar-tag) {
    display: none;
  }

  .site-header {
    padding: 0 12px;
    gap: 8px;
  }
  .header-cta {
    padding: 0 11px;
    font-size: 12px;
    min-height: 36px;
    white-space: nowrap;
  }
  .brand span:not(.mark) {
    font-size: 17px;
  }
}

/* ==========================================================================
   THE FAQ DECK IS THE SHARED COMPONENT NOW — 14 Sep 2026.

   The site had four FAQ wrappers: `.faq` on 141 pages, plus `.faq-list` here, `.coupons-faq-list`
   on /coupons and `.about-faq-list` on /about — all with the same inner markup and four slightly
   different skins. The markup is unified on `.faq`, and because the homepage loads ONLY this
   stylesheet (it never pulls main.css), the canonical rules have to be copied here or the deck
   renders unstyled. That is exactly what happened on the first attempt.
   ========================================================================== */
/*
 * The canonical rules are written against the main stylesheet's tokens, and home.css has its own
 * palette under different names — it defines --ink and --line but nothing called --radius,
 * --brand, --sp-2 and so on. Without these the ported rules silently fall back to browser defaults,
 * which is why the first attempt produced square corners and the wrong type. Scoped to `.faq` so
 * none of it leaks into the rest of the homepage design system.
 */
.faq {
  --radius: 16px;
  --radius-lg: 24px;
  --sp-2: 8px;
  --sp-3: 16px;
  --brand: #fe41c4;
  --brand-text: #c63399;
  --foreground: var(--ink);
  --muted-strong: var(--muted);
  --font-head: var(--display);
}

.faq {
  /* Rows butt against each other as one list rather than floating as separate cards. */
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: #fff;
}
.faq-section > h2 {
  margin: 0 0 var(--sp-3);
}
.faq details {
  border-bottom: 1px solid var(--line);
}
.faq details:last-of-type {
  border-bottom: 0;
}
.faq summary {
  display: grid;
  grid-template-columns: 45px minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  min-height: 68px;
  padding: 0 var(--sp-3);
  cursor: pointer;
  list-style: none;
}
.faq summary::-webkit-details-marker {
  display: none;
}
.faq summary > span {
  color: var(--brand-text);
  font-size: 12px;
  font-weight: 800;
}
.faq summary > strong {
  font-family: var(--font-head);
  font-weight: 800;
  font-size: 0.95rem;
  letter-spacing: -0.02em;
  color: var(--foreground);
}
.faq summary > b {
  width: 27px;
  height: 27px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 16px;
  font-weight: 500;
  transition: transform 0.2s ease;
}
.faq details[open] summary > b {
  transform: rotate(45deg);
  background: var(--foreground);
  color: #fff;
  border-color: var(--foreground);
}
.faq summary:hover > b {
  border-color: var(--foreground);
}
.faq summary:focus-visible {
  outline: 3px solid var(--brand);
  outline-offset: -3px;
}
.faq details p {
  max-width: 780px;
  margin: -5px 0 20px 59px;
  padding-right: var(--sp-3);
  color: var(--muted-strong);
  font-size: 0.9rem;
  line-height: 1.65;
}
.faq {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(28rem, 1fr));
  gap: var(--sp-2);
  align-items: start;
  /* The group border belongs to each card now, not to the container. */
  border: 0;
  border-radius: 0;
  overflow: visible;
  background: none;
}
.faq details {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: #fff;
}
.faq details:last-of-type {
  border-bottom: 1px solid var(--line);
}
@media (max-width: 560px) {
  .faq summary {
    grid-template-columns: 30px minmax(0, 1fr) auto;
    gap: 10px;
  }
  .faq details p {
    margin-left: 40px;
  }
}
@media (max-width: 560px) {
  .faq {
    /* One column on a phone, and the cards close back up into a single list. */
    grid-template-columns: 1fr;
    gap: 0;
  }
  .faq details {
    border-radius: 0;
    border-bottom: 0;
  }
  .faq details:first-of-type {
    border-start-start-radius: var(--radius);
    border-start-end-radius: var(--radius);
  }
  .faq details:last-of-type {
    border-bottom: 1px solid var(--line);
    border-end-start-radius: var(--radius);
    border-end-end-radius: var(--radius);
  }
}
