/*
 * Public customer site — mobile-first (§1: ~70% of traffic is mobile).
 *
 * Every layout rule below is the phone layout; the media queries only widen
 * it. Written in that order deliberately — v1 was built desktop-first and
 * retrofitted, which is the mistake §1 asks not to repeat.
 *
 * Visual direction follows §8.2: clean, uncluttered, photo-forward,
 * destination-led.
 */

.skip {
  position: absolute;
  left: -9999px;
  background: var(--brand);
  color: #fff;
  padding: .7rem 1rem;
  z-index: 100;
}
.skip:focus { left: .5rem; top: .5rem; }

/* ------------------------------------------------------------------ head */
.site-head {
  position: sticky;
  top: 0;
  z-index: 20;
  display: flex;
  align-items: center;
  gap: .75rem;
  padding: .6rem 1rem;
  background: var(--brand);
  color: #fff;
}

.site-head__brand {
  display: flex;
  align-items: center;
  gap: .55rem;
  color: #fff;
  text-decoration: none;
  font-family: var(--font-head);
  font-size: 1.25rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .04em;
}
.site-head__brand img {
  /* CI p.6: the white-on-ocean-blue lockup is the preferred usage, and p.5
     sets a 30px digital minimum for the master logo. */
  border-radius: 6px;
  background: #fff;
  padding: 2px;
}
.site-head__brand em { font-style: normal; font-weight: 600; opacity: .8; }

.site-nav { display: none; }

/* The switch itself is the shared .lang-switch component in tokens.css, so
   both apps get one control that looks and behaves identically. Only its
   placement is a site concern. */
.site-lang { margin-left: auto; }

/* ------------------------------------------------------------------ hero */
.hero { padding-block: 1.75rem 1rem; }
.hero__eyebrow {
  margin: 0 0 .3rem;
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brand-soft);
}
.hero__lead { margin: 0; max-width: 46ch; color: var(--text-muted); }

/* ----------------------------------------------------------------- cards */
/*
 * One container for everything that must share a left edge.
 *
 * Before this, the hero, the filter bar and the card grid each set their own
 * horizontal padding and only two of them shared the max-width — so at 1280px
 * the hero text began at 56px, the cards at 72px and the filter chips at 16px.
 * The cap and the gutter now live in exactly one rule, which is the only way
 * three separate blocks stay aligned as the page changes.
 */
.page-wrap {
  max-width: 1200px;
  margin-inline: auto;
  /* 1rem read as cramped on a phone. Because hero, filters, year headings and
     cards all share this container, changing it here moves them together and
     they stay aligned. */
  padding-inline: 1.25rem;
}

.trip-grid {
  list-style: none;
  margin: 0;
  padding-block: 1rem 3rem;
  display: grid;
  gap: 1rem;
}

.trip {
  overflow: hidden;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.trip__media {
  aspect-ratio: 16 / 9;
  background:
    linear-gradient(135deg, var(--brand) 0%, var(--brand-mid) 55%, var(--brand-soft) 100%);
  display: grid;
  place-items: center;
  position: relative;
}
.trip__media img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* Most trips have no cover photo yet — the emoji flag on a brand gradient is
   a deliberate, on-brand placeholder rather than a broken image frame. */
.trip__flag { font-size: 3.25rem; line-height: 1; filter: drop-shadow(0 2px 6px rgba(0,0,0,.3)); }

.trip__dates {
  position: absolute;
  left: .75rem;
  bottom: .75rem;
  background: rgba(255,255,255,.94);
  color: var(--brand-dark);
  font-weight: 600;
  font-size: .8125rem;
  padding: .25rem .65rem;
  border-radius: var(--radius-pill);
}

.trip__body { padding: 1rem 1.1rem 1.25rem; }
.trip__route {
  margin: 0 0 .15rem;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--brand-soft);
}
/* Same treatment as the admin's trip headers: condensed *bold* reads as a
   solid block at this size, so 600 with an open line-height and a little
   tracking keeps the CI voice without the density. */
.trip__title {
  font-family: var(--font-head);
  font-size: 1.4rem;
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: .01em;
  color: var(--brand);
  margin: 0 0 .35rem;
}
/* The price on a card, and on the trip hero.
 *
 * MUST STAY ABOVE the max-width:767px block further down. These rules and the
 * mobile overrides have equal specificity, so whichever is written LAST wins.
 * Placed after that block, the mobile card silently rendered the price in dark
 * brand blue on a dark scrim — it did, until a CSSOM sweep caught it. */
.trip__price {
  margin: 0 0 .35rem;
  font-size: .9375rem;
  font-weight: 700;
  color: var(--brand);
}
.trip-hero__price {
  margin: .2rem 0 0;
  font-size: 1rem;
  font-weight: 700;
  color: var(--accent);
  text-shadow: 0 1px 8px rgba(4, 16, 29, .6);
}

.trip__tagline { margin: 0 0 .85rem; color: var(--text-muted); font-size: .95rem; }
.trip__meta { display: flex; flex-wrap: wrap; gap: .4rem; }

/* ---------------------------------------------------------------- chips */
.chip {
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  white-space: nowrap;
  padding: .4rem .9rem;
  min-height: 40px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-pill);
  background: var(--surface);
  color: var(--text-muted);
  cursor: pointer;
}
.chip.is-active {
  background: var(--brand);
  border-color: var(--brand);
  color: #fff;
}

/* --------------------------------------------------------------- status */
.status { padding: 0 1rem; color: var(--text-muted); }
.status--error { color: var(--danger); font-weight: 600; }

.empty {
  margin: 1rem;
  padding: 2rem 1.25rem;
  text-align: center;
  color: var(--text-muted);
  background: var(--surface);
  border: 1px dashed var(--border-strong);
  border-radius: var(--radius-lg);
}

/* ------------------------------------------------------------------ foot */
.site-foot {
  padding: 1.5rem 1rem 2.5rem;
  border-top: 1px solid var(--border);
  color: var(--text-faint);
  font-size: .875rem;
}

/* ------------------------------------------------- widen for tablet/desktop */
@media (min-width: 768px) {
  .page-wrap { padding-inline: 2rem; }
  .site-head { padding: .7rem 2rem; }
  .site-nav { display: flex; gap: 1.25rem; margin-left: 1.5rem; }
  .site-nav a {
    color: rgba(255,255,255,.82);
    text-decoration: none;
    font-weight: 600;
    padding: .35rem 0;
  }
  .site-nav a.is-current,
  .site-nav a:hover { color: #fff; box-shadow: inset 0 -2px 0 var(--accent); }

  .trip-grid {
    padding: 1.5rem 2rem 4rem;
    grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
    gap: 1.5rem;
  }
  .status, .empty { margin-inline: 2rem; }
}

@media (min-width: 1280px) {
  .hero, .trip-grid, .site-foot { max-width: 1200px; margin-inline: auto; }
}

/* ======================================================================
   Underwater treatment
   ======================================================================
   Pure CSS — no canvas, no library, matching the technique on the brand's
   own trips.padum-diving.com. Only transform and opacity animate, so the
   whole thing stays on the compositor and costs nothing on a phone.
   ====================================================================== */

:root {
  --sea-deep:    #0A1E33;   /* the dark below                     */
  --sea-mid:     #0E2740;   /* the reference page's own base      */
  --sea-shallow: #17466E;   /* light coming through the surface   */
}

body {
  /* Fixed so the water stays put while the page scrolls over it. */
  background:
    linear-gradient(180deg,
      var(--sea-shallow) 0%,
      var(--sea-mid)     42%,
      var(--sea-deep)    100%) fixed;
  color: #EAF3FA;
  min-height: 100dvh;
}

.sea {
  position: fixed;
  inset: 0;
  z-index: 0;
  overflow: hidden;
  pointer-events: none;   /* never intercepts a tap */
}

/* --- caustics: light refracted through a moving surface ---------------- */
.sea__caustic {
  position: absolute;
  display: block;
  /* `screen` makes the stripes add light rather than paint over the page. */
  mix-blend-mode: screen;
}
.sea__caustic--a {
  inset: -25% -25% 25%;
  background: repeating-linear-gradient(104deg,
    rgba(149, 209, 235, .26) 0 3px,
    rgba(149, 209, 235, 0)   3px 92px);
  filter: blur(15px);
  animation: seaCausticA 17s ease-in-out infinite;
}
.sea__caustic--b {
  inset: -25% -25% 40%;
  background: repeating-linear-gradient(76deg,
    rgba(255, 255, 255, .18) 0 2px,
    rgba(255, 255, 255, 0)   2px 132px);
  filter: blur(22px);
  animation: seaCausticB 24s ease-in-out infinite;
}

@keyframes seaCausticA {
  0%, 100% { transform: translate3d(-6%, -2%, 0) rotate(-2deg) scaleY(1);    opacity: .5; }
  50%      { transform: translate3d( 6%,  2%, 0) rotate( 2deg) scaleY(1.12); opacity: .8; }
}
@keyframes seaCausticB {
  0%, 100% { transform: translate3d( 5%,  1%, 0) scaleX(1);    opacity: .35; }
  50%      { transform: translate3d(-5%, -3%, 0) scaleX(1.15); opacity: .65; }
}

/* --- bubbles ----------------------------------------------------------- */
.bubble {
  position: absolute;
  bottom: -24px;
  display: block;
  border-radius: 50%;
  /* Staggered durations and delays that share no common factor, so the
     pattern does not visibly repeat. */
  animation: bubbleRise linear infinite;
}
.bubble--1 { left:  8%; width:  5px; height:  5px; background: rgba(255,255,255,.5);   box-shadow: 0 0 8px rgba(149,209,235,.8); animation-duration: 15s; animation-delay:  0s; }
.bubble--2 { left: 24%; width:  9px; height:  9px; background: rgba(149,209,235,.32);  box-shadow: inset 0 0 6px rgba(255,255,255,.6); animation-duration: 21s; animation-delay:  4s; }
.bubble--3 { left: 41%; width:  4px; height:  4px; background: rgba(255,255,255,.45);  animation-duration: 12s; animation-delay:  7s; }
.bubble--4 { left: 58%; width: 12px; height: 12px; background: rgba(149,209,235,.20);  box-shadow: inset 0 0 8px rgba(255,255,255,.5); animation-duration: 26s; animation-delay:  2s; }
.bubble--5 { left: 72%; width:  6px; height:  6px; background: rgba(149,209,235,.4);   animation-duration: 18s; animation-delay:  9s; }
.bubble--6 { left: 86%; width:  7px; height:  7px; background: rgba(255,255,255,.35);  box-shadow: 0 0 6px rgba(149,209,235,.6); animation-duration: 23s; animation-delay: 12s; }
.bubble--7 { left: 95%; width:  4px; height:  4px; background: rgba(149,209,235,.45);  animation-duration: 14s; animation-delay:  5s; }

@keyframes bubbleRise {
  0%   { transform: translate3d(0, 30px, 0);      opacity: 0; }
  10%  {                                          opacity: .65; }
  90%  {                                          opacity: .3; }
  100% { transform: translate3d(26px, -105vh, 0); opacity: 0; }
}

/*
 * Motion off, water still there.
 *
 * This is a lot of continuous movement, and vestibular sensitivity is real.
 * The gradient and the caustic texture stay — only the animation stops, so
 * the page keeps its character without moving.
 */
@media (prefers-reduced-motion: reduce) {
  .sea__caustic, .bubble { animation: none !important; }
  .bubble { opacity: .4; }
}

/* ------------------------------------------------ content over the water */
/* Everything real sits above .sea, which is z-index 0. */
.site-head, #main, .site-foot, .skip { position: relative; z-index: 1; }

.site-head {
  background: rgba(10, 30, 51, .55);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(149, 209, 235, .18);
}

/* --- hero --------------------------------------------------------------- */
.hero { padding-block: clamp(2rem, 7vw, 4.5rem) clamp(1.5rem, 4vw, 2.5rem); }

.hero__eyebrow {
  display: flex;
  align-items: center;
  gap: .85rem;
  margin: 0 0 .6rem;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .28em;
  text-transform: uppercase;
  color: var(--accent);
}
.hero__rule { width: 34px; height: 2px; background: var(--accent); flex: none; }

.hero__title {
  margin: 0 0 .7rem;
  font-family: var(--font-head);
  font-weight: 700;
  text-transform: uppercase;
  /* Tight leading is right here — the two lines are meant to stack as a
     block, unlike the trip names where it read as density. */
  line-height: .86;
  letter-spacing: .01em;
  font-size: clamp(3rem, 11vw, 7rem);
}
.hero__line { display: block; }
.hero__line--outline {
  color: transparent;
  -webkit-text-stroke: clamp(1.5px, .28vw, 2.5px) rgba(149, 209, 235, .85);
}
/* Thai has no uppercase and its outline stroke renders poorly at this size. */
:lang(th) .hero__title { text-transform: none; line-height: 1.05; }
:lang(th) .hero__line--outline {
  -webkit-text-stroke: 0;
  color: var(--brand-pale);
}

.hero__lead {
  max-width: 34rem;
  margin: 0;
  color: rgba(234, 243, 250, .82);
  font-size: 1.0625rem;
}

/* --- cards lift off the water ------------------------------------------ */
.trip {
  background: var(--surface);
  color: var(--text);
  border: 1px solid rgba(255, 255, 255, .12);
  box-shadow: 0 10px 34px rgba(4, 16, 29, .38);
  cursor: pointer;
  transition: transform .18s ease, box-shadow .18s ease;
}
.trip:hover, .trip:focus-visible {
  transform: translateY(-3px);
  box-shadow: 0 16px 44px rgba(4, 16, 29, .5);
}
.trip:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.status { color: rgba(234, 243, 250, .75); }
.site-foot { color: rgba(234, 243, 250, .55); }

/* --- availability, the reason a customer is scanning this page ---------- */
/* `.trip__spaces` used to render the count as text beside the card title. The
   availability badge replaced it and nothing has emitted these classes since —
   including .trip__spaces--full, which carried the same green-means-full
   inversion fixed below. Deleted rather than corrected: a rule no markup can
   reach is not worth keeping right. */

.trip__more {
  margin-top: .75rem;
  font-size: .8125rem;
  font-weight: 600;
  color: var(--brand-soft);
}

/* ================================================== trip detail overlay */
body.sheet-open { overflow: hidden; }

.sheet-overlay {
  position: fixed;
  inset: 0;
  z-index: 60;
  background: rgba(6, 20, 34, .72);
  backdrop-filter: blur(6px);
  display: flex;
  justify-content: center;
  align-items: flex-end;        /* phones: rises from the bottom */
  animation: sheetFade .18s ease both;
}
@keyframes sheetFade { from { opacity: 0; } to { opacity: 1; } }

.sheet {
  width: 100%;
  max-height: 94dvh;
  display: flex;
  flex-direction: column;
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  box-shadow: 0 -12px 50px rgba(4, 16, 29, .5);
  animation: sheetRise .22s cubic-bezier(.2, .8, .3, 1) both;
}
@keyframes sheetRise { from { transform: translateY(3%); } to { transform: none; } }
.sheet:focus { outline: none; }

.sheet__bar {
  position: sticky;
  top: 0;
  z-index: 1;
  padding: .5rem .75rem;
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.sheet__back {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font: inherit;
  font-weight: 600;
  min-height: 44px;
  padding: .4rem .7rem;
  border: 0;
  border-radius: var(--radius);
  background: transparent;
  color: var(--brand);
  cursor: pointer;
}
.sheet__back:hover { background: var(--brand-wash); }

.sheet__body {
  flex: 1;
  overflow-y: auto;
  padding: 1.1rem 1.15rem calc(1.5rem + env(safe-area-inset-bottom));
  -webkit-overflow-scrolling: touch;
}
.sheet__loading { color: var(--text-muted); font-style: italic; }

.sheet__head { margin-bottom: 1.25rem; }
.sheet__flag { font-size: 2rem; line-height: 1; }
.sheet__route {
  margin: .3rem 0 .1rem;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand-soft);
}
.sheet__title {
  margin: 0 0 .5rem;
  font-family: var(--font-head);
  font-size: clamp(1.6rem, 6vw, 2.2rem);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: .01em;
  color: var(--brand);
}
.sheet__facts {
  display: flex;
  flex-wrap: wrap;
  gap: .2rem .9rem;
  margin: 0 0 .6rem;
  font-size: .9375rem;
  color: var(--text-muted);
}
.sheet__when { font-weight: 600; color: var(--text); }
.sheet__spaces { margin: 0 0 .5rem; font-size: 1.05rem; }
.sheet__tagline { margin: 0; color: var(--text-muted); }

.sheet__section { margin-bottom: 1.4rem; }
.sheet__section h3 {
  margin: 0 0 .45rem;
  font-size: 1rem;
  font-weight: 600;
  color: var(--brand);
  padding-bottom: .3rem;
  border-bottom: 1px solid var(--border);
}
/* Brochure copy is plain text with meaningful line breaks — preserved, never
   parsed as markup. */
.sheet__prose {
  margin: 0;
  font: inherit;
  font-size: .9375rem;
  white-space: pre-wrap;
  word-break: break-word;
  color: var(--text);
}

.sheet__rooms { list-style: none; margin: 0; padding: 0; display: grid; gap: .35rem; }
.sheet__rooms li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: .55rem .75rem;
  border-radius: var(--radius);
  background: var(--brand-wash);
  font-size: .9375rem;
}
.sheet__room-type { font-weight: 600; }
/* Price and availability travel together on the right of a cabin row — the
   two halves of "can I have this one". */
.sheet__room-right { display: flex; align-items: center; gap: .6rem; }
.sheet__room-price { font-weight: 700; white-space: nowrap; }
.sheet__room-note {
  margin: .6rem 0 0;
  font-size: .8125rem;
  color: var(--text-muted);
}

.sheet__cta {
  margin-top: 1.5rem;
  padding: 1rem 1.1rem;
  border-radius: var(--radius-lg);
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-mid) 100%);
  color: #fff;
}
/* Words left, action right. Column below 560px, where a row leaves the heading
   two words wide and the button squeezed against it. */
.sheet__cta {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: .9rem;
}
.sheet__cta h3 { margin: 0 0 .25rem; color: #fff; font-size: 1.05rem; }
.sheet__cta p  { margin: 0; color: rgba(255,255,255,.85); font-size: .9375rem; }
.sheet__cta-text { min-width: 0; }

@media (min-width: 560px) {
  .sheet__cta { flex-direction: row; align-items: center; justify-content: space-between; }
  .btn-line { flex: none; }
}

/* --------------------------------------------------- payment terms table */
/* # · when · how much. An ordered list rather than a <table>: it is three
   fields, and a table on a 375px phone needs horizontal scrolling to say them. */
.pay-terms { list-style: none; margin: 0; padding: 0; display: grid; }
.pay-term {
  display: grid;
  /* Three fields, one row, at every width: number, when, amount. It used to
     carry a fourth (Deposit / Payment 2 / Last Payment) which forced a
     two-row stack on a phone; the number says the same thing in 1.4rem. */
  grid-template-columns: 1.4rem minmax(0, 1fr) auto;
  align-items: baseline;
  gap: .6rem;
  padding: .55rem .1rem;
  border-bottom: 1px solid var(--border);
}
.pay-term:last-child { border-bottom: 0; }
/* A muted figure rather than a filled disc: a column of blue circles down a
   five-installment schedule is decoration the number does not need. */
.pay-term__no {
  font-size: .8125rem;
  font-weight: 700;
  color: var(--text-muted);
}
.pay-term__when { font-size: .9375rem; color: var(--text); }
.pay-term__amount { font-weight: 700; white-space: nowrap; text-align: right; }
/* The balance is the room price, which we do not publish — it reads as an
   invitation to ask, so it must not look like a missing number. */
.pay-term__amount.is-balance {
  font-weight: 600;
  font-size: .8125rem;
  color: var(--brand);
  white-space: normal;
}
.pay-terms__note {
  margin: .6rem 0 0;
  font-size: .8125rem;
  color: var(--text-muted);
}

/* The LINE button, in LINE's own green.
 *
 * This was #067A35 — the brand green darkened until WHITE text passed. That
 * fixed the wrong half: #06C755 with white measures 2.26:1 and fails at every
 * size (16px bold is not "large text"; that starts at 18.66px bold), but the
 * same green with dark ink measures 6.36:1 and passes comfortably. So the
 * brand colour stays and the text changes, which is also what LINE's own
 * guidelines allow. */
.btn-line {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  min-height: 46px;
  padding: .6rem 1.4rem;
  border-radius: var(--radius-pill);
  background: #06C755;
  color: #00320F;
  font-size: 1rem;
  font-weight: 700;
  text-decoration: none;
}
.btn-line:hover { background: #05B34C; }
/* White, not the brand green: the ring sits on the panel's blue gradient, and
   a green ring on green would be invisible exactly when it matters. */
.btn-line:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }

@media (min-width: 768px) {
  .sheet-overlay { align-items: center; padding: 2rem 1rem; }
  .sheet {
    width: min(720px, 100%);
    border-radius: var(--radius-lg);
    max-height: 88dvh;
  }
  .sheet__body { padding: 1.5rem 1.75rem 2rem; }
}

@media (prefers-reduced-motion: reduce) {
  .sheet-overlay, .sheet { animation: none; }
}

/* ===================================================== filters + sections */

/*
 * The bar's background spans the viewport so the blur reaches both edges, but
 * its contents sit in .page-wrap — that is why .filters carries no horizontal
 * padding of its own and .filter-row does the aligning.
 */
.filters {
  position: sticky;
  top: 0;
  z-index: 5;
  padding-block: 10px;
  margin-bottom: .25rem;
  background: rgba(10, 30, 51, .82);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(149, 209, 235, .16);
}

/* One row, always. Groups are separated by rules rather than by wrapping. */
.filter-row {
  display: flex;
  align-items: center;
  gap: 6px;
  overflow-x: auto;
  scrollbar-width: none;
  -webkit-overflow-scrolling: touch;
}
.filter-row::-webkit-scrollbar { display: none; }

.filter-sep {
  flex: none;
  width: 1px;
  height: 20px;
  margin-inline: .35rem;
  background: rgba(149, 209, 235, .32);
}

/* Pushes the route picker to the right edge, level with the last card. */
.filter-row .route-select { margin-left: auto; }

.chip {
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  white-space: nowrap;
  flex: none;
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  min-height: 38px;
  padding: .3rem .8rem;
  border: 1px solid rgba(149, 209, 235, .35);
  border-radius: var(--radius-pill);
  background: transparent;
  color: rgba(234, 243, 250, .88);
  cursor: pointer;
}
.chip:hover { border-color: var(--brand-pale); }
.chip.is-active {
  background: var(--brand-pale);
  border-color: var(--brand-pale);
  color: var(--brand-dark);
}
.chip__count {
  font-size: .6875rem;
  font-weight: 600;
  padding: .05rem .4rem;
  border-radius: var(--radius-pill);
  background: rgba(255, 255, 255, .16);
}
.chip.is-active .chip__count { background: rgba(26, 58, 92, .18); }
.chip:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }

.route-select {
  font: inherit;
  font-size: .8125rem;
  font-weight: 600;
  flex: none;
  min-height: 38px;
  max-width: 15rem;
  padding: .3rem .7rem;
  border: 1px solid rgba(149, 209, 235, .35);
  border-radius: var(--radius-pill);
  background: transparent;
  color: rgba(234, 243, 250, .88);
}
.route-select option { color: var(--text); background: var(--surface); }

.year-head {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: .6rem;
  margin: .75rem 0 -.25rem;
  padding-bottom: .35rem;
  border-bottom: 1px solid rgba(149, 209, 235, .22);
}
.year-head h2 {
  margin: 0;
  font-size: 1.5rem;
  color: #fff;
}
.year-head span { font-size: .8125rem; color: rgba(234, 243, 250, .6); }

.btn-quiet {
  font: inherit;
  font-size: .875rem;
  font-weight: 600;
  min-height: 40px;
  margin-top: .5rem;
  padding: .4rem 1rem;
  border: 1px solid rgba(149, 209, 235, .4);
  border-radius: var(--radius-pill);
  background: transparent;
  color: rgba(234, 243, 250, .9);
  cursor: pointer;
}

/* ================================================== availability badge */
/* On the photo, so it costs the card no height at all. */
.avail {
  position: absolute;
  top: 8px;
  right: 8px;
  z-index: 1;
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .22rem .6rem;
  border-radius: var(--radius-pill);
  font-size: .75rem;
  font-weight: 600;
  line-height: 1.5;
  white-space: nowrap;
  /* Solid fills, not washes: this sits over a photo whose colours are
     unknown, so a tint would be unreadable against a pale cover. */
  box-shadow: 0 1px 6px rgba(4, 16, 29, .35);
}
/* Dark TEXT is what lets these badges be light.
   They sit over a cover photo whose colours are unknown, so the fill has to be
   solid — and a solid fill carrying white text only clears AA once it is quite
   dark (white measures 4.05:1 on --danger, 4.32:1 on --success, both failing).
   Inverting it — a bright tint with its own ink on top — is both lighter to
   look at and higher contrast: 5.30, 4.57 and 5.26. The yellow badge worked
   this way all along; the other two now match it.
   The hairline is what separates a pale badge from a pale photo, so the drop
   shadow is not doing that job alone. A border carries no contrast
   requirement, so it costs nothing. */
.avail          { border: 1px solid rgba(27, 39, 51, .18); }
.avail--full    { background: var(--danger-tint);  color: var(--danger-ink); }
.avail--limited { background: var(--accent);       color: var(--accent-ink); }
.avail--open    { background: var(--success-tint); color: var(--success-ink); }
.avail__icon { font-size: .8125rem; line-height: 1; }

.pill__icon { font-size: .8125rem; line-height: 1; }

/* The card is a link now; strip the anchor styling and keep the layout. */
.trip__link {
  display: block;
  color: inherit;
  text-decoration: none;
}
.trip__link:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.trip__media { position: relative; }

/* ======================================================= the trip page */
/*
 * Horizontal padding comes from .page-wrap, which this element also carries.
 * Restating it here would win on source order and silently pin the page to a
 * different gutter than the rest of the site — which is exactly what it did.
 *
 * The narrower max-width IS deliberate: a single column of brochure text
 * reads better at 52rem than at the list page's 1200px.
 */
.trip-page {
  max-width: 52rem;
  margin-inline: auto;
  padding-block: 1rem 3rem;
}
.trip-page__back {
  display: inline-block;
  margin-bottom: .85rem;
  font-size: .875rem;
  font-weight: 600;
  color: rgba(234, 243, 250, .85);
  text-decoration: none;
}
.trip-page__back:hover { color: #fff; }

/*
 * No horizontal padding, on purpose.
 *
 * The hero photo is a direct child and must reach both card edges; padding
 * here left 32px of white down each side of it. Body content gets its inset
 * from its own margin-inline instead, which also means that inset is applied
 * once rather than added to this — sections were sitting at 64px.
 *
 * overflow: hidden is what clips the photo to the rounded top corners.
 */
.trip-page__body {
  background: var(--surface);
  color: var(--text);
  border-radius: var(--radius-lg);
  padding-block: 0 1.75rem;
  overflow: hidden;
  box-shadow: 0 10px 34px rgba(4, 16, 29, .38);
}
.trip-page .sheet__avail { margin: 0 0 .7rem; }
/* In the page body the badge is inline, not floating over a photo. */
.trip-page .avail { position: static; box-shadow: none; }

@media (min-width: 768px) {
  .trip-page__body { padding-block: 0 2.25rem; }
}

/* ================================================== compact mobile card */
/*
 * Phone only — the desktop grid is deliberately untouched.
 *
 * At full height only 1.5 cards fitted on a 375px screen, so a customer had
 * to scroll past almost nothing to see almost nothing. The photo and the
 * tagline are the two tallest blocks; the tagline now lives on the trip page,
 * which every card links to.
 */
@media (max-width: 767px) {
  /* PHOTO-FIRST CARD. The picture was a 72px strip, which read as a thumbnail
     rather than a photograph. It is now the card, with the text over it on the
     same scrim the trip hero already uses — so the list and the trip page
     finally look like one site.

     One grid cell, two children stacked in it: no markup change, and the
     desktop card above is untouched. */
  .trip__link {
    display: grid;
    /* minmax(0, 1fr), NOT the default auto column: an auto track sizes to
       max-content, so the unwrapped title stretched the column to 395px on a
       375px screen and the photo overflowed the card, clipping the price. */
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: "card";
  }
  .trip__media,
  .trip__body { grid-area: card; }

  .trip__media { width: 100%; }
  /* Taken out of flow so the photo's OWN ratio cannot size the grid row. In
     flow, a 1567x1045 cover made the row 3:2 and every card a different height
     depending on its photo — aspect-ratio only wins once the img stops
     contributing intrinsic height. Same trick as .trip-hero__img. */
  .trip__media img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
  }
  .trip__flag { font-size: 2.5rem; }

  .trip__body {
    align-self: end;
    z-index: 1;
    padding: 2.5rem .8rem .7rem;
    /* Bottom-up, so the title sits on the opaque end and the top of the photo
       stays clear. Same ramp as .trip-hero__scrim. */
    background: linear-gradient(
      to top,
      rgba(4, 16, 29, .92) 0%,
      rgba(4, 16, 29, .74) 42%,
      rgba(4, 16, 29, .26) 78%,
      rgba(4, 16, 29, 0) 100%);
  }
  .trip__tagline { display: none; }

  /* The route line goes: the title and the destination pill already say where
     the trip is, and two lines over a photo read better than three. */
  .trip__route { display: none; }

  .trip__title {
    font-size: 1.05rem;
    line-height: 1.2;
    margin-bottom: .2rem;
    color: #fff;
    text-shadow: 0 2px 12px rgba(4, 16, 29, .6);
  }
  /* Smaller than the title on purpose — the trip is the headline, the price is
     the answer to the next question. */
  .trip__price {
    margin: 0;
    font-size: .8125rem;
    color: var(--accent);
    text-shadow: 0 1px 8px rgba(4, 16, 29, .65);
  }

  /* Dives and boat, on their own row under the price.
     Sharing the price's line overflowed 3 of the 22 trips at 375px — Palau's
     dive_count alone is "18 Dives (incl. 1 night dive)" — so they get a row.
     It costs no card height: the body and the photo share one grid cell, and
     at 115px the body is still far shorter than the 187px photo. */
  .trip__meta {
    margin-top: .3rem;
    flex-wrap: nowrap;
    gap: .3rem;
    min-width: 0;
  }
  /* dives, boat, destination — destination is the longest of the three and is
     on the trip page anyway. */
  .trip__meta .pill:nth-child(n+3) { display: none; }

  /* Over a photo, not on the card's own surface: --brand-wash and the other
     pill fills are light blocks with dark text and read as stickers here.
     White at 17% behaves like glass on any cover. */
  .trip__meta .pill {
    font-size: .6875rem;
    padding: .12em .55em;
    background: rgba(255, 255, 255, .17);
    color: #fff;
    text-shadow: 0 1px 6px rgba(4, 16, 29, .55);
    min-width: 0;
  }
  /* dive_count is free text typed per trip, so today's fit is not a guarantee.
     The dive pill gives way first — its wording is the part that varies. */
  .trip__meta .pill { overflow: hidden; }
  .trip__meta .pill:first-child { flex-shrink: 3; }
  .trip__meta .pill span:not(.pill__icon) {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }
  .trip__meta .pill__icon { flex: none; }

  /* "View trip" would push the scrim halfway up the photo, and the whole card
     is the link anyway. */
  .trip__more { display: none; }

  /* Top-left, opposite the availability badge: at the bottom it collided with
     the title now that the body is an overlay. */
  .trip__dates {
    top: 6px;
    left: 6px;
    bottom: auto;
    font-size: .6875rem;
    padding: .18rem .5rem;
  }

  .avail { top: 6px; right: 6px; font-size: .6875rem; padding: .18rem .5rem; }

  .filters { padding-block: 8px; }
  .year-head { margin: .5rem 0 -.35rem; }
  .year-head h2 { font-size: 1.25rem; }
}

/* ============================================ bullets in the trip detail */
/* Brochure prose (.prose-list / .prose-note) now lives in css/tokens.css,
   because the admin renders the same fields through the same /shared/prose.js.
 */

/* =================================================== trip page hero */
.trip-hero {
  position: relative;
  isolation: isolate;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  overflow: hidden;
  /* A band on a phone, a hero on a desktop — never the whole first screen. */
  min-height: clamp(150px, 34vw, 280px);
  display: flex;
  align-items: flex-end;
  /* Same gradient the card uses behind its emoji, so a trip with no photo
     gets the identical layout rather than a different one. */
  background: linear-gradient(135deg, var(--brand) 0%, var(--brand-mid) 55%, var(--brand-soft) 100%);
}
.trip-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
}
/*
 * The scrim is what makes overlaid text safe. The photo could be a bright
 * surface shot or a dark wreck shot, so the text cannot rely on the image
 * being dark — this guarantees a floor to contrast against.
 */
.trip-hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(
    to top,
    rgba(4, 16, 29, .88) 0%,
    rgba(4, 16, 29, .70) 34%,
    rgba(4, 16, 29, .28) 68%,
    rgba(4, 16, 29, .12) 100%);
}
.trip-hero__overlay { padding: 1rem 1.25rem 1.1rem; width: 100%; }
.trip-hero__route {
  display: flex;
  align-items: center;
  gap: .4rem;
  margin: 0 0 .25rem;
  font-size: .75rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brand-pale);
}
.trip-hero__flag { font-size: 1.1rem; letter-spacing: normal; }
.trip-hero__title {
  margin: 0 0 .3rem;
  font-family: var(--font-head);
  font-size: clamp(1.5rem, 5.5vw, 2.4rem);
  font-weight: 600;
  line-height: 1.15;
  letter-spacing: .01em;
  color: #fff;
  text-shadow: 0 2px 14px rgba(4, 16, 29, .55);
}
.trip-hero__when {
  margin: 0;
  font-size: .9375rem;
  font-weight: 600;
  color: #fff;
  text-shadow: 0 1px 8px rgba(4, 16, 29, .6);
}
/* The badge floats over the hero, top-right, as it does on the card. */
.trip-hero > .avail { position: absolute; top: .75rem; right: .75rem; box-shadow: 0 1px 6px rgba(4,16,29,.4); }

/* The hero is flush to the card edges, so the body padding starts below it. */
.trip-page__body > .sheet__head { padding: 1.1rem 1.25rem 0; margin-bottom: 1.1rem; }
.trip-page__body > .sheet__section,
.trip-page__body > .sheet__cta { margin-inline: 1.25rem; }

/* Room rows carry a badge now rather than a bare count, and the row's wash
   has to agree with the badge sitting inside it.
 *
 * These were inverted: full was green and nearly-full was red, the opposite of
 * .avail--full / .avail--limited above and of the convention trip-bits.js
 * documents — so a sold-out cabin rendered as a green stripe with a red badge
 * on it. Red means full, amber means hurry, green means room: the same reading
 * a customer already brings from every hotel and airline. */
.sheet__rooms li.is-full    { background: var(--danger-wash);  color: var(--danger-ink); }
.sheet__rooms li.is-limited { background: var(--accent-wash);  color: var(--accent-ink); }
.sheet__rooms li.is-open    { background: var(--success-wash); color: var(--success-ink); }
.sheet__rooms .avail { position: static; box-shadow: none; }

/* Emoji ahead of the title, when the photo has taken the media block. */
.trip__title-flag { margin-right: .35rem; }

@media (min-width: 768px) {
  /* The row is already one line at every width now that the label is gone —
     only the breathing room changes. */
  .pay-term { padding: .45rem .1rem; }

  .trip-hero__overlay { padding: 1.5rem 2rem 1.6rem; }
  .trip-page__body > .sheet__head { padding: 1.6rem 2rem 0; }
  .trip-page__body > .sheet__section,
  .trip-page__body > .sheet__cta { margin-inline: 2rem; }
}
