
@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.
 */
.hero-photo {
  position: absolute;
  inset: 0 0 0 43%;
  background: url('/img/cruise-hero.webp') 57% center / cover no-repeat;
  background-image: image-set(
    url('/img/cruise-hero.avif') type('image/avif'),
    url('/img/cruise-hero.webp') type('image/webp')
  );
  animation: hero-reveal 0.55s ease-out both;
}
@media (max-width: 900px) {
  .hero-photo {
    background-image: url('/img/cruise-hero-900.jpg');
    background-image: image-set(
      url('/img/cruise-hero-900.avif') type('image/avif'),
      url('/img/cruise-hero-900.jpg') type('image/jpeg')
    );
  }
}
.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.
 */
.faq-list {
  border: 1px solid var(--line);
  border-radius: 24px;
  overflow: hidden;
  background: var(--white);
}
.faq-list details {
  border-bottom: 1px solid var(--line);
}
.faq-list details:last-of-type {
  border-bottom: 0;
}
.faq-list summary {
  min-height: 68px;
  padding: 0 5px;
  display: grid;
  grid-template-columns: 45px 1fr auto;
  align-items: center;
  gap: 14px;
  cursor: pointer;
  list-style: none;
  color: var(--navy);
  font-size: 14px;
  font-weight: 800;
}
.faq-list summary::-webkit-details-marker {
  display: none;
}
.faq-list summary span {
  color: var(--blue);
  font-size: 12px;
}
.faq-list summary b {
  width: 27px;
  height: 27px;
  border: 1px solid var(--line);
  border-radius: 50%;
  display: grid;
  place-items: center;
  font-size: 16px;
  transition: transform 0.2s ease;
}
.faq-list details[open] summary b {
  transform: rotate(45deg);
  background: var(--navy);
  color: var(--white);
}
.faq-list details p {
  max-width: 780px;
  margin: -5px 0 20px 64px;
  color: var(--muted);
  font-size: 14px;
  line-height: 1.65;
}

.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;
  }
  .faq-list summary {
    min-height: 74px;
    grid-template-columns: 27px 1fr auto;
    font-size: 14px;
  }
  .faq-list details p {
    margin-left: 41px;
  }
  .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;
  }
}
