@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/bricolage-700-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/bricolage-700-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ==========================================================================
   What To Do In Malta
   Activity-marketplace layout: search hero, destination rails, a filterable
   things-to-do grid and an A-Z. Photography is our own generated set (see
   docs/compliance.md). No partner markup, copy or branding is reproduced.
   ========================================================================== */

/* Figtree, self-hosted. It used to come from fonts.googleapis.com, which hands
   every EU visitor's IP address to Google before they have consented to
   anything: a Munich court ruled that a GDPR breach in 2022, and this site
   states plainly that GDPR applies to it. Self-hosting removes the transfer
   entirely and drops a render-blocking third-party request with it. */
/* latin-ext */
/* Figtree ships one file per subset covering the whole 400-800 range, so every
   weight below resolves to the same two URLs. They used to point at five
   separately named but byte-identical copies, which cost eight redundant
   requests on the critical path. Do not re-split them. */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/figtree-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(fonts/figtree-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/figtree-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(fonts/figtree-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/figtree-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url(fonts/figtree-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/figtree-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url(fonts/figtree-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
/* latin-ext */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url(fonts/figtree-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
/* latin */
@font-face {
  font-family: 'Figtree';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url(fonts/figtree-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  color-scheme: light;

  --font-display: 'Bricolage Grotesque', Georgia, serif;

  /* Marketplace palette. Deep navy carries every piece of text, one saturated
     blue carries every action, and the page underneath stays pure white with no
     tinted bands. Contrast comes from hairline borders rather than shadow or
     colour, which is what keeps a dense listing grid calm at 59 cards. */
  --primary:      #0d7d8c;
  --primary-deep: #0a616e;
  --primary-ink:  #10323a;
  --secondary:    #4bb3c0;

  /* The accent tokens used to be orange. They now resolve to the action blue so
     every existing rule that referenced them re-tones instead of breaking. */
  --accent:       #0d7d8c;
  --accent-btn:   #0d7d8c;
  --accent-btn-2: #0a616e;
  --accent-soft:  #e6f4f5;

  --bg:           #ffffff;
  --bg-tint:      #f4f9f9;
  --muted:        #e8f1f1;
  --border:       #d3e0e1;
  --border-soft:  #e1ebec;

  --fg:           #10323a;
  --fg-mid:       #546a70;
  --fg-soft:      #5b7077;   /* 4.94:1 on white, 4.68:1 on the tint. #858995 was 3.49:1, under AA. */

  --success:      #0f766e;
  --red:          #c72a3d;
  --wash:         #e9f5f5;

  --r-sm: 8px; --r: 12px; --r-lg: 12px; --r-xl: 16px; --r-pill: 80px;
  /* Cards, the modal and the trust boxes all ask for this. It was used in
     seven rules and never defined, so every one of them computed to 0 and
     rendered square while the reference is rounded. */
  --r-card: 12px;

  /* Cards carry no shadow at all: a 1px border does the separating. The only
     real elevation on the site is a floating panel (search suggestions, sticky
     booking box), which is what --sh-lg is reserved for. */
  --sh-sm: none;
  --sh:    0 1px 2px rgba(26,43,73,.06);
  --sh-lg: 0 0 32px rgba(0,0,0,.06), 0 4px 8px rgba(0,0,0,.16);

  /* One geometric sans for everything, headings included. Figtree is the
     closest freely licensed match to the tall-x-height geometric face the
     large activity marketplaces use, and keeping headings and body in the same
     family is what makes those listing pages read as a product rather than an
     article. */
  --font-h: 'Figtree', system-ui, -apple-system, sans-serif;
  --font-b: 'Figtree', system-ui, -apple-system, sans-serif;

  --container: 1200px;
  --pad: clamp(1.15rem, 4vw, 2.5rem);
  --ease: cubic-bezier(.22,.9,.32,1);
  --hdr-h: 80px;
}

*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scroll-padding-top: calc(var(--hdr-h) + 12px); }
/* Belt and braces on top of the page-wide scroll-padding-top above: every
   section a link on this site actually jumps to (the nav, "See all",
   "Read the full case", a search suggestion) carries its own scroll-margin
   too, so a fragment landing on it can never rest with its heading or its
   first row of chips sitting under the fixed header, regardless of which
   scrolling API got it there. */
#book, #things-to-do, #top10 { scroll-margin-top: calc(var(--hdr-h) + 12px); }

body {
  background: var(--bg); color: var(--fg); font-family: var(--font-b);
  font-size: 1rem; line-height: 1.65; -webkit-font-smoothing: antialiased; overflow-x: hidden;
}

/* height:auto matters more than it looks. Every img carries width and height
   attributes, which is right for layout stability, but those are presentational
   hints that beat aspect-ratio unless height is released. Without this a rule
   asking for 16/10 silently rendered the raw 800x600 instead, taller than wide
   at card widths. */
img, svg { display: block; max-width: 100%; height: auto; }
a { color: inherit; }
h1,h2,h3,h4 {
  font-family: var(--font-h); line-height: 1.2; letter-spacing: -.018em; text-wrap: balance;
}
p { text-wrap: pretty; }
::selection { background: var(--primary); color: #fff; }
:focus-visible { outline: 3px solid var(--primary); outline-offset: 3px; border-radius: 6px; }

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--pad); }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--fg); color: #fff; padding: .85rem 1.35rem; font-weight: 600; border-radius: 0 0 10px 0;
}
.skip:focus { left: 0; }

/* ==========================================================================
   Scroll progress
   ========================================================================== */
.progress {
  position: fixed; top: 0; left: 0; height: 3px; width: 100%; z-index: 100;
  transform: scaleX(0); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--primary), var(--secondary), var(--accent));
}

/* ==========================================================================
   Header
   ========================================================================== */
/* The header is opaque on every page now. It used to float transparently over a
   photographic hero; the hero is a pale wash, so white-on-photo type has nothing
   left to sit on and the bar simply stays white. */
.site-header {
  position: fixed; top: 0; left: 0; right: 0; z-index: 60;
  /* The drop-down panels hang off this. */
  isolation: isolate;
  background: #fff; border-bottom: 1px solid var(--border-soft);
  transition: box-shadow .3s var(--ease);
}
.site-header__inner { display: flex; align-items: center; justify-content: space-between; gap: 1.5rem; min-height: var(--hdr-h); }
.site-header.is-solid { box-shadow: 0 1px 8px rgba(26,43,73,.07); }

/* ---------------------------------------------------------------------------
   The search that docks into the header
   ---------------------------------------------------------------------------
   Ported from whattodoinmalta.com. Once the hero search scrolls away there is
   nothing to search with until you scroll back up, which on a page that is
   mostly one long grid is most of the visit. A compact copy slides into the
   header instead.

   It occupies its space from the start and only fades in, rather than being
   inserted on scroll. Inserting it would reflow the header every time you
   crossed the trigger, and that is a layout shift on the element pinned to the
   top of the screen. */
.hdrsearch {
  position: relative; flex: 1 1 auto; min-width: 0; max-width: 26rem;
  margin-inline: auto;
  display: flex; align-items: center; gap: .55rem;
  background: #fff; border: 1px solid var(--border); border-radius: var(--r-pill);
  padding: .5rem 1.1rem;
  box-shadow: 0 1px 2px rgba(26,43,73,.06);
  opacity: 0; transform: translateY(-8px); pointer-events: none;
  transition: opacity .26s var(--ease), transform .26s var(--ease);
}
.hdrsearch > svg { width: 17px; height: 17px; flex: none; color: var(--fg-soft); }
.hdrsearch input {
  flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: .92rem;
  color: var(--fg); padding: .18rem 0;
}
.hdrsearch input::placeholder { color: var(--fg-soft); }
.hdrsearch input:focus { outline: none; }
.hdrsearch:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px rgba(13,125,140,.14); }

.site-header.is-docked .hdrsearch { opacity: 1; transform: none; pointer-events: auto; }

/* Nothing to dock into on a phone until the brand gives way. Below 900px the
   wordmark hides once the bar is showing, which is enough room without
   removing the logo itself or the way back to the homepage. */
@media (max-width: 899px) {
  .site-header.is-docked .brand__name { display: none; }
  .hdrsearch { max-width: none; }
}
/* On a small phone the wordmark alone is not enough room and the placeholder
   gets cut mid-word. The Contact pill stands down while the bar is showing;
   it is still one tap away in the menu beside it, and searching is the more
   likely thing to want halfway down a grid of seventeen beaches. */
@media (max-width: 560px) {
  .site-header.is-docked .nav__cta { display: none; }
  .hdrsearch { padding-inline: .9rem; }
  /* Holding the space open costs nothing at desktop widths and buys a stable
     header. At 360px it is the difference between the burger fitting and not,
     so here the bar leaves the flow until it is wanted. The shift that causes
     is both tiny and inside the 500ms after a scroll, which is why it does not
     count against CLS. */
  .hdrsearch { display: none; }
  .site-header.is-docked .hdrsearch { display: flex; }
}
@media (prefers-reduced-motion: reduce) {
  .hdrsearch { transition: opacity .01ms; transform: none; }
}

.brand { display: flex; align-items: center; gap: .65rem; text-decoration: none; flex: none; }
.brand__mark { width: 38px; height: 38px; flex: none; border-radius: var(--r-sm); }
.brand__name { font-weight: 800; font-size: 1.02rem; letter-spacing: -.02em; line-height: 1.1; color: var(--fg); }
.brand__name span { display: block; font-weight: 600; font-size: .64rem; letter-spacing: .1em; text-transform: uppercase; margin-top: 2px; color: var(--fg-soft); }

.nav { display: flex; align-items: center; gap: .1rem; }
.nav a {
  padding: .6rem .9rem; border-radius: var(--r-sm);
  font-size: .94rem; font-weight: 600; color: var(--fg); text-decoration: none;
  transition: background .18s var(--ease), color .18s var(--ease);
}
.nav a:not(.nav__cta):hover { background: var(--muted); }
.nav__cta {
  margin-left: .5rem; background: var(--primary); color: #fff !important;
  border-radius: var(--r-pill); padding: .62rem 1.3rem; font-weight: 700;
}
.nav__cta:hover { background: var(--primary-deep); }
@media (max-width: 900px) { .nav a:not(.nav__cta) { display: none; } }
/* Below about 420px the brand, the Contact pill and the burger no longer fit
   the container between them, and the header pushed the whole document 20px
   wider than the screen. It was invisible on the homepage and the guides only
   because a scrolling rail there clips the overflow; on the five plain pages
   (about, contact and the three legal ones) the body itself scrolled sideways.
   Nothing is removed, everything just gives up a little room. */
@media (max-width: 420px) {
  .site-header__inner { gap: .6rem; }
  .brand { min-width: 0; gap: .5rem; }
  .brand__mark { width: 32px; height: 32px; }
  .brand__name { font-size: .92rem; }
  .brand__name span { font-size: .58rem; letter-spacing: .07em; }
  .nav__cta { margin-left: 0; padding-inline: .95rem; }
}

/* ==========================================================================
   Buttons
   ========================================================================== */
/* Flat pills. The gradient fill, the drop shadow, the lift on hover and the
   sweeping shine have all gone: the reference does none of them, and on a page
   this dense they read as decoration competing with the cards. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  min-height: 48px; padding: .8rem 1.7rem; border-radius: var(--r-pill);
  border: 2px solid transparent;
  font-family: var(--font-b); font-weight: 700; font-size: .97rem; text-decoration: none; cursor: pointer;
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.btn--primary { background: var(--primary); border-color: var(--primary); color: #fff; }
.btn--primary:hover { background: var(--primary-deep); border-color: var(--primary-deep); }
.btn--glass { background: #fff; color: var(--primary); border-color: var(--primary); }
.btn--glass:hover { background: var(--accent-soft); }
.btn--ghost { background: #fff; color: var(--primary); border-color: var(--primary); }
.btn--ghost:hover { background: var(--accent-soft); }

/* ==========================================================================
   SEARCH HERO
   ========================================================================== */
/* A full-bleed photograph, a centred headline and one search bar. This site
   is about water, so it now opens on one, the same way a guide page's own
   .guide-hero does: a photo behind a dark gradient strong enough to hold
   white text at contrast, with the header staying the opaque bar it always
   is rather than trying to float transparently on top. The search bar keeps
   its own opaque white pill regardless of what is behind it, so only the H1
   and the standfirst needed a colour change. */
.hero {
  position: relative; overflow: hidden; isolation: isolate; text-align: center;
  padding-top: calc(var(--hdr-h) + clamp(2.25rem, 5vw, 3.75rem));
  padding-bottom: clamp(2.25rem, 5vw, 3.5rem);
  background: var(--fg);
}
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  /* Same curve as .guide-hero's, tuned against this exact set of photos for
     a 4.5:1 minimum on the small print anywhere in the band. */
  background: linear-gradient(180deg, rgba(4,26,40,.80) 0%, rgba(4,26,40,.55) 45%, rgba(4,26,40,.88) 100%);
}
/* While the hero's suggestion list is open the hero must out-rank anything that
   overlaps its bottom edge. */
.hero.sug-open { z-index: 60; }

.hero__inner { position: relative; max-width: 52rem; margin-inline: auto; color: #fff; }

.hero h1 {
  font-size: clamp(2.1rem, 1.15rem + 3.9vw, 3.1rem); font-weight: 800;
  line-height: 1.14; letter-spacing: -.03em; margin-bottom: .85rem; color: #fff;
  max-width: 20ch; margin-inline: auto;
}

.hero__sub {
  font-size: 1.02rem; line-height: 1.5; color: rgba(255,255,255,.92);
  max-width: 36rem; margin-inline: auto; margin-bottom: 1.5rem;
}
.hero__actions { display: flex; flex-wrap: wrap; gap: .85rem; justify-content: center; }


/* ==========================================================================
   Sections
   ========================================================================== */
/* Tighter vertical rhythm. The reference stacks many short sections rather than
   a few tall ones, so the padding comes down and the H2 comes down with it. */
.section { padding-block: clamp(2.25rem, 4.5vw, 3.25rem); }
.section--tint { background: var(--bg-tint); }

.section__head { display: flex; align-items: baseline; justify-content: space-between; gap: 2rem; flex-wrap: wrap; margin-bottom: 1.15rem; }
.section__head > div { max-width: 46rem; }
/* The uppercase pill kicker is gone: the reference labels a section with its
   heading alone, and the pill was competing with the chips below it. */
.kicker { display: none; }
.section__head h2 { font-size: clamp(1.5rem, 1.2rem + 1.05vw, 1.78rem); font-weight: 800; letter-spacing: -.022em; margin-bottom: .35rem; }
.section__head p { color: var(--fg-mid); font-size: .95rem; }
.section__more {
  font-size: .93rem; font-weight: 700; color: var(--primary); text-decoration: none; white-space: nowrap;
}
.section__more:hover { text-decoration: underline; }

/* ==========================================================================
   FILTERS
   ========================================================================== */
.filters { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.85rem; }
.filter {
  min-height: 44px; display: inline-flex; align-items: center; gap: .45rem;
  padding: .5rem 1.05rem; border-radius: 999px; cursor: pointer;
  border: 1px solid var(--border-soft); background: #fff;
  font: inherit; font-size: .89rem; font-weight: 600; color: var(--fg-mid);
  transition: all .22s var(--ease);
}
.filter:hover { border-color: var(--primary); color: var(--primary-deep); }
.filter[aria-pressed="true"] {
  background: var(--primary-ink); border-color: var(--primary-ink); color: #fff;
  box-shadow: 0 6px 16px rgba(12,74,110,.24);
}
.filter b { font-weight: 700; opacity: .6; font-variant-numeric: tabular-nums; }

/* ==========================================================================
   HERO SEARCH
   ========================================================================== */
/* One long white pill: search field, a divider, the island selector, then the
   blue action. This is the hero's only interactive element by design. */
.searchbar {
  display: flex; align-items: center; gap: 0; margin-inline: auto;
  background: #fff; border: 1px solid transparent; border-radius: var(--r-pill);
  padding: .45rem .45rem .45rem 1.6rem;
  box-shadow: 0 2px 6px rgba(26,43,73,.09), 0 14px 34px rgba(26,43,73,.11);
  max-width: 46rem;
}
.searchbar:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 16%, transparent); }
.searchbar > svg { width: 20px; height: 20px; flex: none; color: var(--fg-soft); margin-right: .6rem; }
.searchbar input {
  flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: 1.02rem;
  color: var(--fg); padding: .95rem .25rem;
}
.searchbar input::placeholder { color: var(--fg-soft); }
.searchbar input:focus { outline: none; }

.searchbar__sep { width: 1px; align-self: stretch; margin: .35rem .7rem; background: var(--border); flex: none; }
.searchbar__where {
  flex: none; border: 0; background: none; font: inherit; font-size: .95rem; font-weight: 600;
  color: var(--fg); padding: .55rem 1.6rem .55rem .35rem; cursor: pointer;
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2363687a' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right .3rem center; background-size: 15px;
}
.searchbar__where:focus { outline: none; }
.searchbar .btn { min-height: 54px; padding-inline: 2rem; font-size: 1.02rem; flex: none; gap: 0; }
@media (max-width: 620px) {
  .searchbar { padding-left: 1rem; }
  .searchbar__sep, .searchbar__where { display: none; }
  .searchbar .btn span { display: none; }
  .searchbar .btn { padding-inline: 1.15rem; min-height: 48px; }
  /* Without this the placeholder is clipped flush against the button and the
     two read as one smudge. The bar is now tall enough that the collision is
     the first thing you see on a phone. */
  .searchbar input { padding-right: .7rem; }
}

/* ==========================================================================
   DIRECTORY, sticky filter rail beside the results
   ========================================================================== */
/* The filters used to be a sticky 252px sidebar. They are now a full-width
   horizontal chip bar above the results, which is how the reference does it and
   which gives the grid the whole container width. The buttons keep their
   .opt / data-k / data-v contract, so the filtering script is untouched. */
.dir { display: block; }

.rail {
  display: flex; align-items: center; gap: .55rem; flex-wrap: nowrap;
  overflow-x: auto; scrollbar-width: none; -ms-overflow-style: none;
  padding-bottom: .3rem; margin-bottom: 1.1rem;
  /* On a phone the row scrolls, and the soft right edge is what says so. */
  -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
          mask-image: linear-gradient(90deg, #000 calc(100% - 34px), transparent);
}
.rail::-webkit-scrollbar { display: none; }
/* With ten chips there is no reason to hide any of them on a real screen.
   Wrapping beats scrolling here: a filter you cannot see is a filter nobody
   uses, and the row was being cut off mid-chip with nothing to say so. */
@media (min-width: 900px) {
  .rail {
    flex-wrap: wrap; overflow-x: visible; row-gap: .5rem;
    -webkit-mask-image: none; mask-image: none;
  }
  .rail__search { min-width: 17rem; }
}

.rail__search {
  display: flex; align-items: center; gap: .5rem; background: #fff; flex: none;
  border: 1px solid var(--border); border-radius: var(--r-pill); padding-left: .95rem;
  min-width: 15rem;
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
.rail__search:focus-within { border-color: var(--primary); box-shadow: 0 0 0 3px color-mix(in srgb, var(--primary) 16%, transparent); }
.rail__search svg { width: 16px; height: 16px; color: var(--fg-soft); flex: none; }
.rail__search input { flex: 1; min-width: 0; border: 0; background: none; font: inherit; font-size: .9rem; padding: .62rem .25rem; }
.rail__search input:focus { outline: none; }
.rail__clear {
  border: 0; background: none; cursor: pointer; color: var(--fg-soft);
  font-size: 1.1rem; line-height: 1; padding: .5rem .75rem; border-radius: 50%;
}
.rail__clear:hover { color: var(--primary); background: var(--accent-soft); }

/* The group labels are read by screen readers but the chips speak for
   themselves visually, exactly as they do on the reference. */
.rail__group { display: flex; align-items: center; gap: .45rem; flex: none; }
/* Hidden in flow, NOT with position:absolute. An absolutely positioned label has
   no positioned ancestor here, so its containing block is the viewport: it
   escapes the rail's overflow clip, sits at its static position several hundred
   pixels along the scrolled row, and drags the layout viewport out with it. That
   stretched the fixed header on phones and pushed its Contact button off screen. */
.rail__group h3 {
  width: 1px; height: 1px; margin: 0; padding: 0; border: 0;
  overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.rail__opts { display: flex; gap: .45rem; flex: none; }
.rail__sep { width: 1px; height: 26px; background: var(--border); flex: none; margin-inline: .35rem; }

/* Wrapping .rail alone did not deliver what its comment promises. The chips do
   not sit in the rail, they sit inside .rail__group, and both that and
   .rail__opts are flex: none above, so they kept their intrinsic width and
   pushed past the screen instead of wrapping. Between 900px and about 1180px
   that left the last filter group outside the viewport with no scroll to
   reach it, because the rail had just stopped being a scroll container: the
   filter was not merely hard to see, it was unusable. These have to come
   after the rules they override, not inside the earlier media block, because
   both are single-class selectors and source order is what decides. */
@media (min-width: 900px) {
  .rail__group { flex: 0 1 auto; flex-wrap: wrap; min-width: 0; }
  .rail__opts  { flex: 0 1 auto; flex-wrap: wrap; min-width: 0; }
  /* Once the groups wrap, the divider between them is stranded at the end of a
     row with nothing on its right. The line break already separates them. */
  .rail__sep { display: none; }
}

.opt {
  display: inline-flex; align-items: center; gap: .4rem; white-space: nowrap;
  min-height: 40px; padding: .45rem 1rem; border-radius: var(--r-pill); cursor: pointer;
  border: 1px solid var(--border); background: #fff;
  font: inherit; font-size: .88rem; font-weight: 600; color: var(--fg);
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.opt:hover { background: var(--muted); }
.opt b { font-weight: 600; font-size: .8rem; color: var(--fg-soft); font-variant-numeric: tabular-nums; }
.opt[aria-pressed="true"] { background: var(--fg); border-color: var(--fg); color: #fff; }
.opt[aria-pressed="true"] b { color: rgba(255,255,255,.72); }

.results__bar {
  display: flex; align-items: baseline; justify-content: space-between; gap: 1rem;
  flex-wrap: wrap; padding-bottom: 1.15rem; margin-bottom: 1.6rem;
  border-bottom: 1px solid var(--border-soft);
}
.results__bar p { font-size: .93rem; color: var(--fg-mid); }
.results__bar strong { color: var(--fg); font-variant-numeric: tabular-nums; }
.results__right { display: flex; align-items: baseline; gap: 1rem; flex-wrap: wrap; }
.clear-all {
  border: 0; background: none; cursor: pointer; font: inherit; font-size: .88rem; font-weight: 600;
  color: var(--accent-btn); padding: .35rem .1rem; border-bottom: 1px solid currentColor;
}
.clear-all:hover { color: var(--accent-btn-2); }
/* One attribution line for the whole grid, because the cards themselves now
   follow the reference's rating shape (score, star, count) with no room for a
   partner name in it. */
.results__src {
  font-size: .82rem; line-height: 1.5; color: var(--fg-soft);
  max-width: 62ch; margin: -.35rem 0 1.1rem;
}

/* ==========================================================================
   ATTRACTION CARDS
   ========================================================================== */
/* Four across at desktop, matching the reference grid. */
.cards { display: grid; gap: 1.5rem 1.25rem; grid-template-columns: repeat(auto-fill, minmax(240px,1fr)); }
@media (min-width: 700px)  { .cards { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 1000px) { .cards { grid-template-columns: repeat(3,1fr); } }
@media (min-width: 1240px) { .cards { grid-template-columns: repeat(4,1fr); } }

/* The listing card. Bordered, flat, square-shouldered image on top, and a fixed
   bottom row separated by a hairline. Nothing lifts or glows on hover, because
   twenty of these animating at once is what made the old grid feel restless. */
.ac {
  display: flex; flex-direction: column; overflow: hidden; background: #fff;
  border: 1px solid var(--border); border-radius: var(--r-card);
  transition: border-color .2s var(--ease), box-shadow .2s var(--ease);
}
/* Every card is interactive now, so every card gets the same affordance:
   a guide card navigates, a brief card opens the detail panel.

   Four things move together on hover, at deliberately different speeds so it
   reads as one gesture rather than four twitches: the card lifts quickly, the
   cue pill slides up just behind it, the title takes the action colour, and the
   image keeps pushing in long after the rest has settled. Colour and shadow are
   unconditional; everything that actually moves is behind the motion query. */
.ac:hover, .ac:focus-within {
  border-color: var(--border);
  box-shadow: 0 10px 28px rgba(26,43,73,.14);
}
.ac:hover .ac__body h3, .ac:focus-within .ac__body h3 { color: var(--primary); }
.ac__body h3 { transition: color .2s var(--ease); }
.ac.is-out { display: none; }
article.ac { background: #fff; position: relative; }

/* A transparent target covering the whole card. The card is an <article>, not a
   button, because a button may only contain phrasing content and this one holds
   an image and headings. The label stays in the accessibility tree for screen
   readers while being invisible on screen. */
.ac__hit {
  position: absolute; inset: 0; z-index: 3; cursor: pointer;
  background: none; border: 0; padding: 0;
  font-size: 0; color: transparent;
}
.ac__hit:focus-visible { outline: 3px solid var(--primary); outline-offset: -3px; border-radius: var(--r-card); }

/* Entrance. Deliberately a CSS animation rather than a JS-applied one: an
   animation always runs to completion, so a card can never be left stranded at
   opacity 0 if a script fails. It also re-runs for free when a filter brings a
   card back from display:none, which is exactly when it is wanted.
   --i is the card's index, written by the build; the cap keeps the last card in
   a long grid from waiting on a nineteen-step stagger. */
@media (prefers-reduced-motion: no-preference) {
  .ac {
    animation: acIn .42s var(--ease) backwards;
    animation-delay: calc(min(var(--i, 0), 9) * 32ms);
  }
  @keyframes acIn {
    from { opacity: 0; transform: translateY(12px) scale(.99); }
    to   { opacity: 1; transform: none; }
  }
}

.ac__media { position: relative; aspect-ratio: 3/2; overflow: hidden; background: var(--muted); }
.ac__media img { width: 100%; height: 100%; object-fit: cover; }
/* The cue: a white pill that rises out of the bottom of the image and names
   what the click does, which differs per card. It is decorative reinforcement,
   never the only signal, so it is pointer-transparent and the whole card stays
   the target. */
.ac__cue {
  position: absolute; z-index: 2; left: .6rem; bottom: .6rem; pointer-events: none;
  display: inline-flex; align-items: center; gap: .3rem;
  background: #fff; color: var(--fg);
  font-size: .78rem; font-weight: 700; white-space: nowrap;
  padding: .34rem .5rem .34rem .72rem; border-radius: var(--r-pill);
  box-shadow: 0 2px 10px rgba(26,43,73,.24);
  opacity: 0; transition: opacity .22s var(--ease);
}
.ac__cue svg { width: 13px; height: 13px; }
.ac:hover .ac__cue, .ac:focus-within .ac__cue { opacity: 1; }

@media (prefers-reduced-motion: no-preference) {
  .ac { transition: transform .26s var(--ease), border-color .2s var(--ease), box-shadow .26s var(--ease); }
  .ac:hover, .ac:focus-within { transform: translateY(-4px); }

  /* Slower than the lift on purpose: the image is still settling once the card
     has arrived, which is what stops the whole thing feeling mechanical. */
  .ac__media img { transition: transform .7s var(--ease); }
  .ac:hover .ac__media img, .ac:focus-within .ac__media img { transform: scale(1.07); }

  .ac__cue { transform: translateY(8px); transition: opacity .22s var(--ease), transform .28s var(--ease); }
  .ac:hover .ac__cue, .ac:focus-within .ac__cue { transform: none; }
}

/* The one badge on the image, dark and small, in the reference's top-left slot. */
.ac__badge {
  position: absolute; z-index: 2; left: .6rem; top: .6rem;
  background: var(--fg); color: #fff;
  font-size: .72rem; font-weight: 700; letter-spacing: .01em;
  padding: .28rem .6rem; border-radius: 6px;
  display: inline-flex; align-items: center; gap: .35rem;
}
.ac__badge svg { width: 13px; height: 13px; }

.ac__body { padding: .8rem .85rem .55rem; display: flex; flex-direction: column; gap: .22rem; flex: 1; }
/* Grey location eyebrow above the title, the reference's card hierarchy: it
   sets this uppercase and carries the category beside the place. */
.ac__area {
  font-size: .8rem; font-weight: 500; letter-spacing: 0; color: var(--fg-mid);
}
.ac__body h3 {
  font-size: .99rem; font-weight: 700; letter-spacing: -.012em; line-height: 1.32; color: var(--fg);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ac__body p {
  font-size: .86rem; color: var(--fg-mid); line-height: 1.5;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.ac__meta {
  display: flex; flex-wrap: wrap; gap: .2rem .8rem;
  font-size: .84rem; color: var(--fg-mid);
}
.ac__meta > span { display: inline-flex; align-items: center; gap: .3rem; }
.ac__meta svg { width: 13px; height: 13px; flex: none; }
.ac__go { display: none; }

.no-results { padding: 3.5rem 1rem; text-align: center; }
.no-results p { color: var(--fg-mid); margin-bottom: 1.25rem; }

/* ==========================================================================
   PLAN BAND, wide editorial rows
   ========================================================================== */
.plan { display: grid; gap: 1.4rem; grid-template-columns: 1fr; }
@media (min-width: 860px) { .plan { grid-template-columns: repeat(3,1fr); } }

.plan-card {
  position: relative; overflow: hidden; border-radius: var(--r-lg); min-height: 340px;
  display: flex; align-items: flex-end; color: #fff; text-decoration: none;
  box-shadow: var(--sh); transition: transform .34s var(--ease), box-shadow .34s var(--ease);
}
.plan-card:hover { transform: translateY(-6px); box-shadow: var(--sh-lg); }
.plan-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; transition: transform 1s var(--ease); }
.plan-card:hover img { transform: scale(1.07); }
.plan-card::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(4,26,40,.05) 30%, rgba(4,26,40,.82) 100%);
}
.plan-card__body { position: relative; z-index: 2; padding: 1.7rem 1.5rem 1.8rem; }
.plan-card__n { font-family: var(--font-h); font-size: .78rem; font-weight: 700; letter-spacing: .16em; opacity: .8; }
.plan-card h3 { font-size: 1.28rem; font-weight: 700; margin: .4rem 0 .55rem; line-height: 1.2; }
.plan-card p { font-size: .93rem; color: rgba(255,255,255,.9); }

/* ==========================================================================
   STANDARDS, editorial, oversized ghost numerals
   ========================================================================== */
.standards { display: grid; gap: 0; border-top: 1px solid var(--border-soft); }
.standard {
  display: grid; grid-template-columns: 1fr; gap: .35rem;
  padding-block: 2rem; border-bottom: 1px solid var(--border-soft); position: relative;
}
/* This list lives inside .article, whose 74ch reading measure is right for
   paragraphs and far too narrow for a three column row: the number and the
   name ate it, leaving the reason in a column about ten words wide. It breaks
   out to the container instead, and the photograph goes in the space that
   width buys. */
.article > .standards {
  --bleed: min(calc(100vw - 2 * var(--pad)), calc(var(--container) - 2 * var(--pad)));
  width: var(--bleed);
  margin-inline: calc((100% - var(--bleed)) / 2);
}
.standard__media { display: block; border-radius: var(--r-card); overflow: hidden; box-shadow: var(--sh-sm); }
.standard__media img { width: 100%; aspect-ratio: 4/3; object-fit: cover; background: var(--muted); }
@media (min-width: 820px) {
  .standard { grid-template-columns: 5rem minmax(0,16rem) minmax(0,1fr); gap: .4rem 2rem; align-items: start; }
  /* The numeral and the photograph take a column each and span both rows; the
     name and the reason share the third. Without this the paragraph is a
     fourth grid item and wraps under the numeral, about ten words wide. */
  .standard__n, .standard__media { grid-row: 1 / span 2; }
  .standard h3 { grid-column: 3; grid-row: 1; }
  /* Wide, but not unlimited: on a 1920 screen this column would run past
     1100px and the eye loses the line return. */
  .standard p  { grid-column: 3; grid-row: 2; max-width: 74ch; }
}
@media (max-width: 819px) {
  .standard__media { max-width: 22rem; }
}
.standard__n {
  font-family: var(--font-h); font-size: clamp(2.6rem, 2rem + 1.6vw, 3.6rem);
  font-weight: 700; line-height: .85; letter-spacing: -.05em;
  color: transparent; -webkit-text-stroke: 2px #93cbe8;
  transition: -webkit-text-stroke-color .3s var(--ease);
}
.standard:hover .standard__n { -webkit-text-stroke-color: var(--accent); }
@supports not (-webkit-text-stroke: 2px red) { .standard__n { color: var(--border); } }
.standard h3 { font-size: 1.22rem; font-weight: 600; }
.standard p { color: var(--fg-mid); font-size: .96rem; }

/* ==========================================================================
   TOP 10, compact ranked module
   The homepage's version of the ranking: number, a small photograph, the
   name and one line, not the full argument. The full case for the order
   lives on its own page and this list links to it once, at the top.
   ========================================================================== */
.top10 { list-style: none; margin: 0; padding: 0; border-top: 1px solid var(--border-soft); }
.top10__item {
  display: grid; grid-template-columns: 2.25rem 4.25rem 1fr; gap: .9rem;
  align-items: center; padding-block: .85rem;
  border-bottom: 1px solid var(--border-soft);
  text-decoration: none; color: inherit;
}
.top10__n {
  font-family: var(--font-h); font-size: 1.35rem; font-weight: 700;
  color: var(--fg-soft); letter-spacing: -.03em;
}
.top10__item img {
  width: 100%; aspect-ratio: 1/1; object-fit: cover; border-radius: var(--r-sm);
  background: var(--muted); display: block;
}
.top10__item h3 { font-size: .98rem; font-weight: 700; color: var(--fg); margin: 0 0 .15rem; }
.top10__item p { font-size: .85rem; color: var(--fg-mid); margin: 0; line-height: 1.4; }
.top10__item:hover h3, .top10__item:focus-visible h3 { color: var(--primary); }
@media (max-width: 480px) {
  .top10__item { grid-template-columns: 1.7rem 3.25rem 1fr; gap: .65rem; }
  .top10__n { font-size: 1.1rem; }
}

/* ==========================================================================
   CTA
   ========================================================================== */
.cta { position: relative; overflow: hidden; background: var(--primary-ink); color: #fff; padding-block: clamp(3rem,7vw,4.75rem); }
.cta::before {
  content: ''; position: absolute; inset: -40%;
  background: radial-gradient(40% 50% at 20% 30%, #0e7490 0%, transparent 60%),
              radial-gradient(38% 46% at 80% 70%, #b45309 0%, transparent 58%),
              radial-gradient(44% 48% at 60% 20%, #0369a1 0%, transparent 62%);
  background-size: 200% 200%; filter: blur(40px); opacity: .85;
  animation: mesh 16s ease-in-out infinite alternate;
}
@keyframes mesh {
  0%   { background-position: 0% 0%, 100% 0%, 60% 100%; transform: scale(1) }
  100% { background-position: 30% 40%, 70% 30%, 20% 60%; transform: scale(1.08) }
}
.cta__inner { position: relative; z-index: 1; display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 2rem; }
.cta h2 { font-size: clamp(1.6rem,1.25rem + 1.6vw,2.3rem); font-weight: 700; margin-bottom: .7rem; }
.cta p { color: #d5eaf5; max-width: 52ch; }
.cta strong { color: #fff; }

/* ==========================================================================
   FOOTER
   ========================================================================== */
/* Deep navy footer, the reference's closing block. */
.site-footer { background: var(--fg); color: rgba(255,255,255,.78); padding-block: 3rem 1.75rem; }

.footer-cols { display: grid; grid-template-columns: 1fr; gap: 2.25rem; padding-bottom: 2.25rem; }
@media (min-width: 620px) { .footer-cols { grid-template-columns: repeat(3,1fr); } }
@media (min-width: 920px) { .footer-cols { grid-template-columns: 1.8fr 1fr 1fr 1fr; } }
.footer-brand .brand__name { color: #fff; }
.footer-brand .brand__name span { color: rgba(255,255,255,.6); }
.footer-brand p { color: rgba(255,255,255,.65); font-size: .89rem; max-width: 34ch; margin-top: 1rem; }
.footer-col h2 { font-size: .95rem; font-weight: 700; text-transform: none; letter-spacing: 0; color: #fff; margin-bottom: .9rem; }
.footer-col ul { list-style: none; padding: 0; display: grid; gap: .55rem; }
.footer-col a { font-size: .89rem; color: rgba(255,255,255,.72); text-decoration: underline; text-underline-offset: 3px; text-decoration-color: rgba(255,255,255,.28); transition: color .2s var(--ease); }
.footer-col a:hover { color: #fff; text-decoration-color: #fff; }
/* ---------------------------------------------------------------------------
   Consent
   ---------------------------------------------------------------------------
   Bottom-anchored rather than a full-screen interstitial: the page has to stay
   readable while the question is open, because a banner that blocks the content
   pressures the answer, and a pressured yes is not consent. Accept and Decline
   are deliberately the same size, the same height and the same weight. Do not
   make Accept the bigger button.
   --------------------------------------------------------------------------- */
.consent {
  position: fixed; z-index: 90; left: 0; right: 0; bottom: 0;
  background: #fff; border-top: 1px solid var(--border);
  box-shadow: 0 -6px 28px rgba(26,43,73,.13);
  padding: 1.1rem var(--pad) 1.2rem;
}
.consent[hidden] { display: none; }
.consent__inner {
  width: 100%; max-width: var(--container); margin-inline: auto;
  display: flex; align-items: center; justify-content: space-between; gap: 1.5rem 2rem;
  flex-wrap: wrap;
}
/* Without a basis the copy takes the whole row and shoulders the buttons onto
   a line of their own even on a wide screen. */
.consent__inner > div:first-child { flex: 1 1 32rem; min-width: 0; }
.consent__title { font-size: 1rem; font-weight: 700; margin-bottom: .3rem; }
.consent p { font-size: .87rem; line-height: 1.55; color: var(--fg-mid); max-width: 68ch; }
.consent p a { color: var(--primary); text-underline-offset: 3px; }
.consent__acts { display: flex; gap: .6rem; flex: none; }
.consent__acts .btn { min-height: 44px; padding-inline: 1.6rem; flex: 1; }
@media (max-width: 620px) {
  .consent__inner { flex-direction: column; align-items: stretch; }
  /* The basis above is a width. Once the row becomes a column it is read as a
     height instead, which stretched the banner to 622px on a phone. */
  .consent__inner > div:first-child { flex: 0 1 auto; }
  .consent__acts .btn { flex: 1; padding-inline: 1rem; }
}

/* The withdraw route. A button, not a link, because it opens a dialog rather
   than navigating, but it has to read as part of the footer sentence. */
.footer-bottom__link {
  background: none; border: 0; font: inherit; cursor: pointer;
  color: rgba(255,255,255,.72); text-decoration: underline; text-underline-offset: 3px;
  text-decoration-color: rgba(255,255,255,.28);
  /* The one standalone control on the site that fell under the 24px minimum
     touch size, at 94x22. Inline links inside prose are the accepted exception
     to that rule; a button that opens a dialog is not. */
  padding: .15rem 0; min-height: 24px;
}
.footer-bottom__link:hover { color: #fff; text-decoration-color: #fff; }

.footer-bottom {
  border-top: 1px solid rgba(255,255,255,.16); padding-top: 1.5rem;
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  font-size: .84rem; color: rgba(255,255,255,.55);
}

/* ==========================================================================
   HORIZONTAL RAIL, the reference's core section pattern: a heading, a row of
   tiles that scrolls sideways, and a circular arrow on the right edge.
   ========================================================================== */
.hrail-wrap { position: relative; }
.hrail {
  display: grid; grid-auto-flow: column; gap: 1rem;
  grid-auto-columns: minmax(148px, 1fr);
  overflow-x: auto; scroll-snap-type: x proximity; scroll-behavior: smooth;
  scrollbar-width: none; -ms-overflow-style: none; padding-bottom: .25rem;
}
.hrail::-webkit-scrollbar { display: none; }
.hrail > * { scroll-snap-align: start; }
@media (min-width: 700px)  { .hrail { grid-auto-columns: minmax(190px, 1fr); } }
/* Fixed track widths, not minmax(0, …). A zero minimum lets the tracks shrink to
   fit the container, which defeats the whole point: the rail is meant to size
   six tiles and let the rest overflow into the scroll. */
@media (min-width: 1000px) { .hrail--six { grid-auto-columns: calc((100% - 5rem) / 6); } }
/* A card rail shows four, the same as the results grid below it. */
.hrail--four { grid-auto-columns: minmax(250px, 1fr); }
@media (min-width: 1240px) { .hrail--four { grid-auto-columns: calc((100% - 3.75rem) / 4); } }

.hrail__nav {
  position: absolute; top: 50%; z-index: 5;
  width: 40px; height: 40px; border-radius: 50%; cursor: pointer;
  background: #fff; border: 1px solid var(--border); color: var(--primary);
  box-shadow: var(--sh-lg);
  display: none; align-items: center; justify-content: center;
  transition: background .18s var(--ease);
}
.hrail__nav:hover { background: var(--accent-soft); }
.hrail__nav svg { width: 18px; height: 18px; }
.hrail__nav--prev { left: -20px; transform: translateY(-50%) rotate(180deg); }
.hrail__nav--next { right: -20px; transform: translateY(-50%); }
.hrail__nav[hidden] { display: none !important; }
@media (min-width: 1000px) { .hrail__nav { display: flex; } }

/* Square destination tile: image, caption, nothing else. */
.dt { display: block; text-decoration: none; }
/* height:auto is load-bearing. The img carries width/height attributes for CLS,
   and an explicit height beats aspect-ratio, so without this the tiles keep the
   source 4:3 instead of cropping to the square the rail is built on. */
.dt img {
  width: 100%; height: auto; aspect-ratio: 1/1; object-fit: cover;
  border-radius: var(--r-sm); background: var(--muted); display: block;
  transition: filter .2s var(--ease);
}
.dt:hover img { filter: brightness(.94); }
.dt b { display: block; margin-top: .6rem; font-size: .95rem; font-weight: 700; color: var(--fg); letter-spacing: -.01em; }
.dt i { display: block; font-style: normal; font-size: .82rem; color: var(--fg-mid); margin-top: .1rem; }

/* ==========================================================================
   TRUST ROW. Three claims, each of which has to be literally true: this site
   holds no reviews, no ratings of its own and no invented prices, so none of
   these boxes may imply otherwise.
   ========================================================================== */
.trust { display: grid; gap: 1rem; grid-template-columns: 1fr; }
@media (min-width: 800px) { .trust { grid-template-columns: repeat(3,1fr); } }
.trust__box {
  border: 1px solid var(--border); border-radius: var(--r-card);
  padding: 1.6rem 1.4rem; text-align: center;
}
.trust__ic {
  width: 46px; height: 46px; margin: 0 auto .85rem; border-radius: var(--r-sm);
  background: var(--accent-soft); color: var(--primary);
  display: flex; align-items: center; justify-content: center;
}
.trust__ic svg { width: 23px; height: 23px; }
.trust__box h3 { font-size: 1rem; font-weight: 700; margin-bottom: .4rem; color: var(--fg); }
.trust__box p { font-size: .88rem; color: var(--fg-mid); line-height: 1.5; }
/* Also doubles as the homepage's practical strip: a handful of short links
   into the pages that actually answer a logistics question, so the box
   itself becomes the click target rather than a link buried in its text. */
a.trust__box {
  display: block; text-decoration: none; color: inherit;
  transition: border-color .2s var(--ease), transform .2s var(--ease);
}
a.trust__box:hover, a.trust__box:focus-visible { border-color: var(--primary); transform: translateY(-2px); }

/* ==========================================================================
   Reveal. The reference animates nothing on scroll, and with sections this
   short the fade was firing constantly, so it is now a no-op that still leaves
   the markup and the no-JS path intact.
   ========================================================================== */
.js .reveal { opacity: 1; transform: none; }

/* ==========================================================================
   Article / legal pages
   ========================================================================== */
.page-head { border-bottom: 1px solid var(--border-soft); background: var(--bg-tint); padding-block: calc(var(--hdr-h) + 2rem) clamp(2rem,4vw,2.75rem); }
.page-head h1 { font-size: clamp(2rem,1.4rem + 2.4vw,3rem); font-weight: 700; }
.page-head p { color: var(--fg-soft); font-size: .9rem; font-weight: 600; margin-top: .65rem; }
.article { max-width: 74ch; margin-inline: auto; padding-block: clamp(2.5rem,5vw,3.75rem) clamp(3rem,7vw,4.5rem); }

/* The 74ch measure is right for prose and wrong for a card grid. Squeezed into
   it, the at-a-glance cards cramp their titles onto three lines and a 1200px
   page renders as a narrow column with dead space either side, which is the
   thing that reads as broken on a wide screen. So blocks that are not prose
   pull back out to the container width.

   Done with margins rather than by making .article a grid: grid would stop the
   prose margins collapsing and silently re-space every paragraph across the
   seven pages that use this class. */
.article > .wide,
.article > .glance,
.article > .duo {
  --bleed: min(calc(100vw - 2 * var(--pad)), calc(var(--container) - 2 * var(--pad)));
  width: var(--bleed);
  margin-inline: calc((100% - var(--bleed)) / 2);
}
/* Already inside a bled-out block, so it must not bleed a second time. */
.article > .wide > .glance,
.article > .wide > .duo { width: auto; margin-inline: 0; }
.article h2 { font-size: 1.34rem; font-weight: 600; margin-top: 2.5rem; margin-bottom: .75rem; }
.article p { color: var(--fg-mid); }
.article p + p { margin-top: .95rem; }
.article ul { margin: .95rem 0 0; padding-left: 1.2rem; color: var(--fg-mid); }
.article li { margin-bottom: .55rem; }
.article a { color: var(--primary-deep); font-weight: 600; }
.callout {
  background: linear-gradient(135deg, var(--muted), #fff); border: 1px solid var(--border);
  border-left: 4px solid var(--primary); border-radius: var(--r); padding: 1.2rem 1.35rem; margin-top: 1.35rem;
}
.callout p { color: var(--fg); }
.breadcrumb { font-size: .86rem; color: var(--fg-soft); margin-bottom: .85rem; }
.breadcrumb a { color: var(--primary-deep); text-decoration: none; font-weight: 600; }
.notfound { text-align: center; padding-block: calc(var(--hdr-h) + 4rem) clamp(4rem,10vw,7rem); }
.notfound h1 { font-size: clamp(2.1rem,1.5rem + 2.8vw,3.2rem); font-weight: 700; margin-bottom: 1rem; }
.notfound p { color: var(--fg-mid); max-width: 48ch; margin: 0 auto 2.25rem; }

/* pages without a hero need the solid header from the start */
.no-hero .site-header { position: sticky; background: rgba(255,255,255,.93); backdrop-filter: saturate(180%) blur(16px); border-bottom-color: var(--border-soft); }
.no-hero .brand__name { color: var(--fg); }
.no-hero .nav a { color: var(--fg-mid); }
.no-hero .nav a.nav__cta { color: #fff !important; }
.no-hero .page-head { padding-top: 2.5rem; }


/* ==========================================================================
   GUIDE PAGES
   ========================================================================== */
.guide-hero { position: relative; overflow: hidden; isolation: isolate; }
.guide-hero__media { position: absolute; inset: 0; z-index: -2; }
.guide-hero__media img { width: 100%; height: 100%; object-fit: cover; }
.guide-hero::before {
  content: ''; position: absolute; inset: 0; z-index: -1;
  /* The mid-stop used to thin to .26, which is exactly where the breadcrumb and
     chips sit. Over a dark photo that was fine; over Blue Lagoon's turquoise it
     measured 3.43:1 and 2.84:1 against a 4.5 requirement. Held darker through
     the middle so the small text passes on any image, bright ones included. */
  background: linear-gradient(180deg, rgba(4,26,40,.80) 0%, rgba(4,26,40,.55) 45%, rgba(4,26,40,.88) 100%);
}
.guide-hero__inner { color: #fff; padding-block: calc(var(--hdr-h) + 3.5rem) clamp(2.5rem,6vw,4rem); max-width: 48rem; }
.guide-hero h1 { font-size: clamp(2.1rem,1.4rem + 3.2vw,3.5rem); font-weight: 700; margin-bottom: .9rem; }
.guide-hero__sub { font-size: clamp(1rem,.97rem + .3vw,1.15rem); color: rgba(255,255,255,.93); }
.guide-hero__chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-bottom: 1.4rem; }
.gchip {
  display: inline-flex; align-items: center; gap: .4rem;
  /* Dark, not light. A white tint under white text is contrast working against
     itself, which is how the chips measured 2.84:1. */
  background: rgba(4,26,40,.5); border: 1px solid rgba(255,255,255,.34);
  backdrop-filter: blur(8px); padding: .35rem .8rem; border-radius: 999px;
  font-size: .8rem; font-weight: 600;
}
.gchip svg { width: 14px; height: 14px; }

.guide-layout { display: grid; grid-template-columns: 1fr; gap: 2.5rem; align-items: start; padding-block: clamp(2.5rem,6vw,4rem); }
@media (min-width: 1000px) { .guide-layout { grid-template-columns: minmax(0,1fr) 300px; gap: 3.5rem; } }

.guide-body { max-width: 68ch; }
.guide-body > * + * { margin-top: 1.15rem; }
.guide-body h2 {
  font-size: clamp(1.35rem,1.15rem + .8vw,1.7rem); font-weight: 700;
  margin-top: 2.75rem; padding-top: 1.5rem; border-top: 1px solid var(--border-soft);
}
.guide-body h3 { font-size: 1.12rem; font-weight: 600; margin-top: 1.9rem; }
.guide-body p, .guide-body li { color: var(--fg-mid); }
.guide-body ul, .guide-body ol { padding-left: 1.25rem; }
.guide-body li { margin-bottom: .5rem; }
.guide-body a { color: var(--primary-deep); font-weight: 600; }
.guide-body strong { color: var(--fg); }

.verdict {
  border-left: 4px solid var(--accent); background: linear-gradient(135deg, var(--accent-soft), #fff);
  border-radius: var(--r); padding: 1.25rem 1.4rem;
}
.verdict h2 { margin: 0 0 .5rem; padding: 0; border: 0; font-size: 1.1rem; }
.verdict p { color: var(--fg); }

.factbox {
  background: #fff; border: 1px solid var(--border-soft); border-radius: var(--r-lg);
  padding: 1.35rem 1.4rem; box-shadow: var(--sh-sm);
}
@media (min-width: 1000px) { .factbox { position: sticky; top: calc(var(--hdr-h) + 1.25rem); } }
.factbox h2 { font-size: .78rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: var(--fg-soft); margin-bottom: 1rem; }
.factbox dl { display: grid; gap: .85rem; margin: 0; }
.factbox dt { font-size: .74rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase; color: var(--fg-soft); }
.factbox dd { margin: .15rem 0 0; font-size: .93rem; color: var(--fg); font-weight: 500; }
.factbox__note { margin-top: 1.15rem; padding-top: 1.15rem; border-top: 1px solid var(--border-soft); font-size: .82rem; color: var(--fg-soft); }

.faq { border-top: 1px solid var(--border-soft); }
.faq details { border-bottom: 1px solid var(--border-soft); }
.faq summary {
  cursor: pointer; padding: 1.05rem 2rem 1.05rem 0; font-weight: 600; font-size: 1rem;
  list-style: none; position: relative;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  font-size: 1.4rem; font-weight: 400; color: var(--primary-deep); line-height: 1;
}
.faq details[open] summary::after { content: '\2212'; }
.faq summary:hover { color: var(--primary-deep); }
.faq details p { color: var(--fg-mid); padding-bottom: 1.1rem; font-size: .95rem; }

.nearby { display: grid; gap: 1.25rem; grid-template-columns: repeat(auto-fill,minmax(230px,1fr)); margin-top: 1.25rem; }
.nearby a {
  display: flex; gap: .85rem; align-items: center; padding: .8rem; border-radius: var(--r);
  border: 1px solid var(--border-soft); text-decoration: none; background: #fff;
  transition: border-color .2s var(--ease), transform .2s var(--ease);
}
.nearby a:hover { border-color: var(--primary); transform: translateY(-2px); }
.nearby img { width: 64px; height: 48px; object-fit: cover; border-radius: 8px; flex: none; }
.nearby b { display: block; font-size: .92rem; font-weight: 600; color: var(--fg); }
.nearby span { font-size: .8rem; color: var(--fg-soft); }

/* Inbound internal links, generated per guide by tools/build.py. Sits outside the
   two-column guide layout so it spans the full measure, which is what stops three
   tiles being squeezed into the 68ch article column. */
.related { padding-block: 0 clamp(2.5rem,6vw,4rem); }
.related h2 { font-size: 1.15rem; margin: 0 0 .25rem; letter-spacing: -.01em; }
.related .nearby a { align-items: flex-start; }
.related .nearby img { margin-top: .15rem; }
/* The contextual link back to the directory. Reads as a sentence rather than a
   fourth tile, because it goes somewhere different from the three above it. */
.related__all { margin: .9rem 0 0; color: var(--muted, #5b6470); font-size: .95rem; }
.related__all a { color: inherit; text-decoration: underline; text-underline-offset: .18em; }
.related__all a:hover, .related__all a:focus-visible { color: var(--ink, #16202b); }

.updated { font-size: .84rem; color: var(--fg-soft); margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid var(--border-soft); }

.ac__go { color: var(--primary-deep); font-weight: 700; }
a.ac { text-decoration: none; color: inherit; }

/* generic page intro for about / contact / plan */
.page-intro { padding-block: calc(var(--hdr-h) + 2.5rem) clamp(2rem,4vw,3rem); background: var(--bg-tint); border-bottom: 1px solid var(--border-soft); }
.page-intro h1 { font-size: clamp(2rem,1.4rem + 2.6vw,3.1rem); font-weight: 700; margin-bottom: .8rem; }
.page-intro p { color: var(--fg-mid); font-size: 1.05rem; max-width: 56ch; }


/* ==========================================================================
   SEARCH SUGGESTIONS (typeahead)
   ========================================================================== */
.sug-wrap { position: relative; flex: 1; min-width: 0; display: flex; align-items: center; gap: .5rem; }

.sug {
  position: absolute; z-index: 70; top: calc(100% + .6rem); left: 0; right: 0;
  background: #fff; border: 1px solid var(--border-soft); border-radius: 14px;
  box-shadow: 0 16px 44px rgba(12,36,52,.18); overflow: hidden;
  max-height: min(60vh, 25rem); overflow-y: auto; padding: .3rem;
  text-align: left;
}
.sug[hidden] { display: none; }

.sug__head {
  font-size: .68rem; font-weight: 700; letter-spacing: .11em; text-transform: uppercase;
  color: var(--fg-soft); padding: .6rem .75rem .4rem;
}

.sug__item {
  display: flex; align-items: center; gap: .7rem; width: 100%;
  padding: .55rem .75rem; border-radius: 10px; cursor: pointer;
  border: 0; background: none; font: inherit; text-align: left; color: inherit;
  text-decoration: none;
}
.sug__item:hover, .sug__item.is-active { background: var(--bg-tint); }
.sug__item.is-active { outline: 2px solid var(--primary); outline-offset: -2px; }

.sug__ico {
  width: 34px; height: 34px; flex: none; border-radius: 9px; display: grid; place-items: center;
  background: var(--muted); color: var(--primary-deep);
}
.sug__ico svg { width: 17px; height: 17px; }
.sug__txt { min-width: 0; flex: 1; }
.sug__name { display: block; font-size: .94rem; font-weight: 600; color: var(--fg); line-height: 1.3; }
.sug__name mark { background: none; color: var(--accent-btn); font-weight: 700; }
.sug__meta { display: block; font-size: .79rem; color: var(--fg-soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sug__tag {
  flex: none; font-size: .68rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--accent-btn); background: var(--accent-soft); padding: .2rem .5rem; border-radius: 999px;
}
.sug__none { padding: 1rem .85rem; font-size: .9rem; color: var(--fg-mid); }
.sug__all {
  display: block; width: 100%; padding: .7rem .75rem; margin-top: .2rem;
  border: 0; border-top: 1px solid var(--border-soft); background: none; cursor: pointer;
  font: inherit; font-size: .87rem; font-weight: 600; color: var(--primary-deep); text-align: left;
}
.sug__all:hover { background: var(--bg-tint); }

/* the hero bar is on a dark image, so its dropdown needs to sit above the scrim */
.searchbar { position: relative; }
.searchbar .sug { box-shadow: 0 22px 60px rgba(2,18,28,.42); }
.searchbar input::-webkit-search-cancel-button,
.rail__search input::-webkit-search-cancel-button { display: none; }

/* a card jumped to from a suggestion gets a brief ring so it is findable */
@keyframes flash { 0%,100% { box-shadow: var(--sh); } 35% { box-shadow: 0 0 0 4px var(--primary), var(--sh-lg); } }
.ac.is-target, .ix__row.is-target { animation: flash 1.6s var(--ease) 1; }
.ix__row.is-target .ix__name { color: var(--primary-deep); }

/* ==========================================================================
   Reduced motion
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; }
  .js .reveal { opacity: 1; transform: none; }
}

/* ---------------------------------------------------------------------------
   Booking block. Rendered by tools/build.py from data/partner-products.json,
   and only when tools/affiliate.py has tracking configured. The disclosure sits
   inside the block so it always precedes the first partner link.
   --------------------------------------------------------------------------- */
.book {
  margin: 2.25rem 0; padding: 1.35rem 1.4rem;
  background: var(--bg-tint); border: 1px solid var(--border-soft);
  border-radius: var(--r-lg);
}
.book h2 { margin: 0 0 .35rem; padding: 0; border: 0; font-size: 1.1rem; }
.book__disclosure {
  margin: 0 0 1rem; font-size: .84rem; line-height: 1.55; color: var(--fg-soft);
}
.book__disclosure a { color: var(--primary-deep); }
/* Each option is a product card, not a line of prose: the partner's own photo,
   the title, the rating with its count, then price and a call to action over a
   hairline. The whole card is one anchor, so a click anywhere on it is the same
   tracked link. */
.book__list { list-style: none; margin: 0; padding: 0; display: grid; gap: .75rem; }
.book__item { margin: 0; }
.book__card {
  display: block; text-decoration: none; color: inherit; background: #fff;
  border: 1px solid var(--border); border-radius: var(--r-card); overflow: hidden;
  transition: border-color .18s var(--ease), box-shadow .18s var(--ease);
}
.book__card:hover, .book__card:focus-visible {
  border-color: var(--fg-soft); box-shadow: 0 2px 10px rgba(26,43,73,.09);
}
.book__img {
  width: 100%; height: auto; aspect-ratio: 16/9; object-fit: cover;
  background: var(--muted); display: block;
}
.book__body { display: block; padding: .7rem .8rem .55rem; }
.book__name {
  font-weight: 700; font-size: .92rem; line-height: 1.35; color: var(--fg);
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical; overflow: hidden;
}
.book__meta { display: flex; align-items: baseline; gap: .45rem; margin-top: .3rem; font-size: .8rem; }
/* The count is never separated from the score, so one review always reads as
   one review rather than as a verdict. */
.book__rate { font-weight: 700; color: var(--fg); display: inline-flex; align-items: baseline; gap: .22rem; }
.book__rate::before { content: '\2605'; font-size: .78rem; }
.book__rate i { font-style: normal; font-weight: 500; color: var(--fg-mid); }
.book__by { color: var(--fg-mid); }
.book__foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: .2rem .5rem;
  /* Wraps rather than clips: in the 300px guide sidebar the price and the call
     to action cannot share a line, and nowrap silently cut the CTA in half. */
  flex-wrap: wrap;
  padding: .55rem .8rem .7rem; border-top: 1px solid var(--border-soft);
}
.book__price { font-weight: 800; font-size: .95rem; color: var(--fg); white-space: nowrap; }
.book__price b { font-weight: 500; font-size: .78rem; color: var(--fg-mid); }
.book__price i { font-style: normal; font-weight: 500; font-size: .72rem; color: var(--fg-soft); }
.book__cta { font-size: .82rem; font-weight: 700; color: var(--primary); white-space: nowrap; }
.book__cta::after { content: ' \203A'; }
.book__card:hover .book__cta { text-decoration: underline; }
.book__more, .book__note {
  margin: .9rem 0 0; font-size: .8rem; line-height: 1.55; color: var(--fg-soft);
}

/* "Tours available" badge on an attraction card. */
.ac__book {
  font-weight: 650; color: var(--success);
}

/* ---------------------------------------------------------------------------
   Plan your trip: on-page nav, trip-length comparison, season table
   --------------------------------------------------------------------------- */
.toc {
  background: var(--bg-tint); border: 1px solid var(--border-soft); border-radius: var(--r);
  padding: 1.1rem 1.3rem; margin-bottom: 2rem;
}
.toc h2 {
  font-size: .74rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
  color: var(--fg-soft); margin: 0 0 .6rem;
}
.toc ol { margin: 0; padding-left: 1.1rem; display: grid; gap: .3rem; }
.toc li { color: var(--fg-soft); margin: 0; }
.toc a { color: var(--primary-deep); font-weight: 600; }

.triplen {
  display: grid; gap: .9rem; margin-top: 1.15rem;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
}
.triplen__item {
  background: #fff; border: 1px solid var(--border-soft); border-radius: var(--r);
  padding: 1rem 1.1rem; box-shadow: var(--sh-sm);
}
.triplen__item--pick { border-color: var(--primary); box-shadow: var(--sh); }
.triplen__item b { display: block; font-size: 1.02rem; color: var(--fg); margin-bottom: .4rem; }
.triplen__item b span {
  display: block; font-size: .72rem; font-weight: 700; letter-spacing: .05em;
  text-transform: uppercase; color: var(--primary-deep); margin-top: .2rem;
}
.triplen__item p { margin: 0; font-size: .9rem; line-height: 1.55; }

/* Wide content must scroll in its own box, never the page body. */
.tablewrap { overflow-x: auto; margin-top: 1.15rem; -webkit-overflow-scrolling: touch; }
.ptable { width: 100%; border-collapse: collapse; min-width: 30rem; }
.ptable th {
  text-align: left; padding: .6rem .75rem .6rem 0; border-bottom: 2px solid var(--fg);
  font-size: .78rem; font-weight: 700; letter-spacing: .06em; text-transform: uppercase;
}
.ptable td { padding: .8rem .75rem .8rem 0; border-bottom: 1px solid var(--border-soft); color: var(--fg-mid); }
.ptable tbody tr:last-child td { border-bottom: 0; }
.ptable td:first-child { font-weight: 650; color: var(--fg); white-space: nowrap; }

/* Factual summary drawn from operator listings. Facts only, their wording is
   never reproduced, and partner ratings are attributed rather than marked up. */
.bookfacts {
  margin: 2.25rem 0 1rem; padding: 1.2rem 1.35rem;
  border: 1px solid var(--border-soft); border-left: 4px solid var(--primary);
  border-radius: var(--r); background: #fff;
}
.bookfacts h2 { margin: 0 0 .7rem; padding: 0; border: 0; font-size: 1.06rem; }
.bookfacts ul { margin: 0; padding-left: 1.15rem; display: grid; gap: .4rem; }
.bookfacts li { color: var(--fg-mid); font-size: .93rem; line-height: 1.5; margin: 0; }
.bookfacts b { color: var(--fg); }
.bookfacts__src { margin: .9rem 0 0; font-size: .79rem; color: var(--fg-soft); line-height: 1.5; }

/* ---------------------------------------------------------------------------
   Guide sidebar: the booking CTA sits above the fact box and both track the
   reader down the page, so the way to book is always one glance away.
   --------------------------------------------------------------------------- */
.guide-side { display: grid; gap: 1.25rem; align-items: start; }
@media (min-width: 1000px) {
  .guide-side {
    position: sticky; top: calc(var(--hdr-h) + 1.25rem);
    /* A sticky column taller than the screen pins its top and hides its own
       foot: there is no way to scroll to the last booking option, because the
       column never moves. Capping it to the viewport and letting it scroll
       inside itself is what makes the whole list reachable. */
    max-height: calc(100vh - var(--hdr-h) - 2.5rem);
    overflow-y: auto; overscroll-behavior: contain;
    scrollbar-width: none; -ms-overflow-style: none;
  }
  .guide-side::-webkit-scrollbar { display: none; }
  /* The column is sticky as a whole now, so the inner box must not be. */
  .factbox { position: static; }
}

/* Sidebar variant of the booking block: narrower, stacked, no thumbnails, so a
   300px column stays readable. */
.book--side { margin: 0; padding: 1.15rem 1.2rem; }
.book--side h2 { font-size: 1rem; }
.book--side .book__disclosure { font-size: .78rem; margin-bottom: .8rem; }
/* The sidebar used to hide the product photo, which left three lines of grey
   text that read as prose rather than as something you can book. The image is
   the thing that makes the card look bookable, so it stays. */
.book--side .book__meta { font-size: .78rem; }
.book--side .book__note, .book--side .book__more { font-size: .74rem; }

/* ---------------------------------------------------------------------------
   Commercial line on an attraction card. Values come from
   data/partner-products.json only. The rating carries the partner's name so it
   can never read as a review this site hosts.
   --------------------------------------------------------------------------- */
/* The bottom row is the same shape on all 59 cards: something on the left,
   something right-aligned on the right, over one hairline. Only 14 attractions
   have partner products, so the other 45 fill the identical slots with facts we
   actually hold (how long to allow, when to go) rather than an invented price or
   an empty gap. Nothing here is ever fabricated, and a rating always names the
   partner it came from. */
.ac__offer {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: .4rem .6rem;
  padding: .35rem .85rem .9rem;
  margin-top: auto; min-height: 34px;
}
.ac__price { font-weight: 800; font-size: 1rem; color: var(--fg); margin-left: auto; white-space: nowrap; }
.ac__price b { font-weight: 400; font-size: .82rem; color: var(--fg-mid); margin-right: .15rem; }
.ac__rate { font-size: .86rem; color: var(--fg); display: inline-flex; align-items: center; gap: .22rem; }
.ac__rate b { font-weight: 700; }
.ac__star { width: 13px; height: 13px; flex: none; fill: var(--fg); }
.ac__rate i { font-style: normal; font-weight: 400; color: var(--fg-mid); font-size: .82rem;
  font-variant-numeric: tabular-nums; }
/* The editorial equivalent, same slots, same weights. */
.ac__fact { font-size: .86rem; font-weight: 700; color: var(--fg); }
.ac__fact--r { margin-left: auto; font-size: .82rem; font-weight: 500; color: var(--fg-mid); text-align: right; }
.ac__offer { row-gap: .45rem; }
.ac__body { flex: 1 1 auto; }

/* Commercial chips in a guide hero: price and rating belong beside the title,
   which is the standard anatomy for an activity page. */
.gchip--price { font-weight: 700; background: rgba(4,26,40,.62); }
.gchip--free { background: rgba(4,60,48,.62); border-color: rgba(167,243,208,.55); }

/* Price on an A-Z row, the list-view equivalent of the card's commercial line. */
.ix__price {
  font-size: .8rem; font-weight: 700; color: var(--fg); margin-top: .12rem;
}

/* Filter matched places we cover but have no photograph of yet. */
.cards-empty {
  grid-column: 1 / -1; margin: .5rem 0 0; padding: 1.5rem 1.25rem;
  border: 1px dashed var(--border); border-radius: var(--r-card);
  text-align: center; font-size: .9rem; color: var(--fg-mid);
}


/* ==========================================================================
   DETAIL PANEL, for attractions with no written guide yet
   ========================================================================== */
/* The source blocks are in the document for crawlers, not for readers. */
.det-src[hidden] { display: none; }

.modal {
  /* margin:auto is what centres a native dialog, and the global `* { margin: 0 }`
     reset above wipes it, which pinned the panel to the top-left corner. */
  margin: auto;
  width: min(620px, calc(100vw - 2rem)); max-height: min(88vh, 880px);
  padding: 0; border: 0; border-radius: var(--r-card);
  background: #fff; color: var(--fg);
  /* Clip to the rounded box. The close button used to hang outside the corner,
     which is most of what made the panel look like a cut-off fragment rather
     than a finished sheet. */
  overflow: hidden;
  box-shadow: var(--sh-lg);
}
.modal::backdrop { background: rgba(26,43,73,.55); }
@media (prefers-reduced-motion: no-preference) {
  .modal[open] { animation: modalIn .28s var(--ease); }
  .modal[open]::backdrop { animation: fadeIn .28s var(--ease); }
  @keyframes modalIn { from { opacity: 0; transform: translateY(14px) scale(.985); } to { opacity: 1; transform: none; } }
  @keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
}
.modal__body {
  max-height: min(88vh, 880px); overflow-y: auto; overscroll-behavior: contain;
  /* The bar itself is chrome the panel does not need; the fade below is what
     tells you there is more, and it goes away once there is not. */
  scrollbar-width: none; -ms-overflow-style: none;
}
.modal__body::-webkit-scrollbar { display: none; }

/* Fade at the foot of the sheet, so a mid-sentence edge reads as "keep going"
   rather than as a rendering fault. Removed the moment you reach the end, or
   when the content was never long enough to scroll. */
.modal::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 56px;
  background: linear-gradient(180deg, rgba(255,255,255,0), #fff 86%);
  pointer-events: none; transition: opacity .2s var(--ease);
}
.modal.is-end::after { opacity: 0; }

/* Inside the sheet, over the image, where it cannot be mistaken for page furniture. */
.modal__close {
  position: absolute; top: .7rem; right: .7rem; z-index: 4;
  width: 36px; height: 36px; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,.94); border: 0; color: var(--fg);
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 2px 10px rgba(26,43,73,.28);
  transition: background .18s var(--ease);
}
.modal__close:hover { background: #fff; }
.modal__close svg { width: 17px; height: 17px; }

.det__img { width: 100%; height: auto; aspect-ratio: 2.4/1; object-fit: cover; display: block; }
.det { padding-bottom: 1.4rem; }
.det > *:not(.det__img) { margin-inline: 1.4rem; }
.det__eyebrow { margin-top: 1.1rem; font-size: .84rem; color: var(--fg-mid); }
.det h2 { font-size: 1.5rem; font-weight: 800; letter-spacing: -.022em; margin-top: .15rem; }
.det__meta { margin-top: .35rem; font-size: .9rem; font-weight: 600; color: var(--fg); }
.det__sum { margin-top: .8rem; color: var(--fg-mid); line-height: 1.6; }
.det .book { margin-top: 1.3rem; }
.det__note {
  margin-top: 1.1rem; padding-top: .9rem; border-top: 1px solid var(--border-soft);
  font-size: .84rem; color: var(--fg-soft);
}

/* In narrow contexts, the detail panel and the guide sidebar, booking options
   become rows rather than banners. A 16:9 photo per product made each option
   278px tall, which pushed the sidebar to 2016px in a 900px viewport: sticky
   pinned its top and the last option simply could not be reached. At row size
   the whole column fits the screen. */
.det .book, .book--side { background: none; border: 0; padding: 0; }
.det .book { margin-top: 1.2rem; }
.det .book h2, .book--side h2 { font-size: .95rem; }
.det .book__card, .book--side .book__card {
  display: grid; grid-template-columns: 104px minmax(0, 1fr); grid-template-rows: auto auto;
}
.det .book__img, .book--side .book__img {
  grid-row: 1 / 3; width: 104px; height: 100%; aspect-ratio: auto;
  min-height: 92px; border-radius: 0;
}
.det .book__body, .book--side .book__body { padding: .6rem .8rem .3rem; }
.det .book__name, .book--side .book__name { font-size: .88rem; }
.det .book__foot, .book--side .book__foot { border-top: 0; padding: 0 .8rem .6rem; min-height: 0; }
/* Not every partner listing publishes a picture. The two-column rule above
   reserves 104px for one, so when it is absent the title lands in the image
   slot and wraps inside 104px with the rest of the row empty beside it. A card
   with nothing to put there gets one column instead. Ported from
   whattodoinmalta.com: an explicit class rather than :has(), which is the
   same fix with no dependency on :has() support. */
.det .book__card--noimg, .book--side .book__card--noimg { grid-template-columns: minmax(0, 1fr); }

/* ==========================================================================
   MOBILE BOOKING BAR
   On desktop the booking column is sticky and sits 11% down the page. On a
   phone it stacks below the article, which put Blue Lagoon's first bookable
   option 6208px down an 8803px page. This carries the real cheapest price and
   a jump to the options, and gets out of the way once they are on screen.
   ========================================================================== */
.bookbar { display: none; }
@media (max-width: 999px) {
  .bookbar {
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
    display: flex; align-items: center; justify-content: space-between; gap: 1rem;
    padding: .7rem 1rem calc(.7rem + env(safe-area-inset-bottom));
    background: #fff; border-top: 1px solid var(--border);
    box-shadow: 0 -2px 16px rgba(26,43,73,.12);
    transition: transform .28s var(--ease);
  }
  /* Hidden once the booking options are visible, so it never covers them. */
  .bookbar.is-gone { transform: translateY(110%); }
  .bookbar__price { font-weight: 800; font-size: 1.05rem; color: var(--fg); }
  .bookbar__price b { font-weight: 500; font-size: .8rem; color: var(--fg-mid); }
  .bookbar__price i { display: block; font-style: normal; font-weight: 500; font-size: .76rem; color: var(--fg-soft); }
  .bookbar .btn { min-height: 44px; padding-inline: 1.4rem; }
  /* Clear the bar so it never sits on top of the last of the page. */
  .site-footer { padding-bottom: 5.5rem; }
}
@media (prefers-reduced-motion: reduce) {
  .bookbar { transition: none; }
  .bookbar.is-gone { display: none; }
}

/* ==========================================================================
   Tap targets. Footer and breadcrumb links rendered 18px tall, under the 24px
   minimum, which on a phone means a link between two other links with almost
   no margin for a thumb. The text size is unchanged; only the target grows.
   ========================================================================== */
@media (max-width: 900px) {
  .footer-col a, .footer-col li > a { display: inline-block; padding-block: .35rem; }
  .footer-col ul { gap: .3rem; }
  .breadcrumb a { display: inline-block; padding-block: .3rem; }
  .ix__name a { display: inline-block; padding-block: .2rem; }
}

/* ==========================================================================
   MAIN NAV LINKS
   Plain links sized for this site: seventeen beaches across three islands,
   not a fifty-nine-place directory across three, so there is nothing here to
   put behind a mega menu. Same breakpoint the dropdown buttons used to hide
   at, so the burger still picks up exactly where these leave off.
   ========================================================================== */
.nav__link {
  padding: .6rem .9rem; border-radius: var(--r-sm);
  font-size: .94rem; font-weight: 600; color: var(--fg); text-decoration: none;
  display: inline-flex; align-items: center;
  transition: background .18s var(--ease);
}
.nav__link:hover, .nav__link:focus-visible { background: var(--muted); }
@media (max-width: 1100px) { .nav__link { display: none; } }

/* ==========================================================================
   FAVOURITES
   A heart on each card, kept in the browser. No account, nothing sent
   anywhere, and nothing that pretends this site takes bookings.
   ========================================================================== */
.nav__fav {
  border: 1px solid var(--border); background: #fff; cursor: pointer; font: inherit;
  display: inline-flex; align-items: center; gap: .35rem;
  padding: .5rem .85rem; margin-left: .4rem; border-radius: var(--r-pill);
  font-size: .9rem; font-weight: 700; color: var(--fg);
  transition: background .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
.nav__fav svg { width: 16px; height: 16px; }
.nav__fav:hover { background: var(--muted); }
.nav__fav[aria-pressed="true"] { background: var(--fg); border-color: var(--fg); color: #fff; }
.nav__fav.is-empty { display: none; }

/* The heart sits opposite the category badge, as it does on the reference. */
.ac__fav {
  position: absolute; z-index: 4; right: .55rem; top: .55rem;
  width: 32px; height: 32px; border-radius: 50%; cursor: pointer;
  background: rgba(255,255,255,.92); border: 0; color: var(--fg);
  display: flex; align-items: center; justify-content: center; padding: 0;
  box-shadow: 0 1px 6px rgba(26,43,73,.25);
  transition: background .16s var(--ease), transform .16s var(--ease);
}
.ac__fav svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 2; }
.ac__fav:hover { background: #fff; }
.ac__fav[aria-pressed="true"] { color: var(--red); }
.ac__fav[aria-pressed="true"] svg { fill: var(--red); stroke: var(--red); }
@media (prefers-reduced-motion: no-preference) {
  .ac__fav[aria-pressed="true"] { animation: favPop .3s var(--ease); }
  @keyframes favPop { 0% { transform: scale(1); } 45% { transform: scale(1.28); } 100% { transform: scale(1); } }
}
/* While the saved filter is on, everything unsaved is out of the way. */
.ac.is-unsaved { display: none; }

.saved-empty {
  grid-column: 1 / -1; margin: .5rem 0 0; padding: 1.75rem 1.25rem;
  border: 1px dashed var(--border); border-radius: var(--r-card);
  text-align: center; font-size: .92rem; color: var(--fg-mid);
}

/* ==========================================================================
   Grouped search suggestions
   ========================================================================== */
.sug__group {
  font-size: .7rem; font-weight: 700; letter-spacing: .09em; text-transform: uppercase;
  color: var(--fg-soft); padding: .6rem .85rem .3rem;
}
.sug__group:not(:first-child) { border-top: 1px solid var(--border-soft); margin-top: .25rem; }

/* ==========================================================================
   MOBILE DRAWER
   Below 1100px the nav links are hidden, which left a phone with no way to
   the pages they carry. The drawer is the same short list again, in a panel
   a burger button opens.
   ========================================================================== */
.nav__burger {
  display: none; border: 1px solid var(--border); background: #fff; cursor: pointer;
  width: 42px; height: 42px; border-radius: var(--r-sm); margin-left: .4rem;
  align-items: center; justify-content: center; color: var(--fg); padding: 0;
}
.nav__burger svg { width: 20px; height: 20px; }
.nav__burger:hover { background: var(--muted); }
@media (max-width: 1100px) { .nav__burger { display: inline-flex; } }

.drawer { position: fixed; inset: 0; z-index: 80; }
.drawer[hidden] { display: none; }
.drawer::before {
  content: ''; position: absolute; inset: 0; background: rgba(26,43,73,.5);
}
.drawer__panel {
  position: absolute; top: 0; right: 0; bottom: 0;
  width: min(380px, 88vw); background: #fff;
  padding: 1.1rem 1.15rem calc(1.5rem + env(safe-area-inset-bottom));
  overflow-y: auto; overscroll-behavior: contain;
  box-shadow: -8px 0 28px rgba(26,43,73,.18);
}
@media (prefers-reduced-motion: no-preference) {
  .drawer::before { animation: fadeIn .2s var(--ease); }
  .drawer__panel { animation: drawerIn .26s var(--ease); }
  @keyframes drawerIn { from { transform: translateX(100%); } to { transform: none; } }
}
.drawer__close {
  border: 0; background: none; cursor: pointer; color: var(--fg);
  width: 40px; height: 40px; border-radius: 50%; margin-left: auto; display: block;
}
.drawer__close:hover { background: var(--muted); }
.drawer__close svg { width: 19px; height: 19px; }

.drawer__links { display: grid; gap: .1rem; margin-bottom: .9rem; }
.drawer__links a {
  display: block; padding: .8rem .6rem; border-radius: var(--r-sm);
  font-size: 1.02rem; font-weight: 700; color: var(--fg); text-decoration: none;
}
.drawer__links a:hover { background: var(--muted); }

/* Options past the fold. Every one is in the document, so they are crawlable
   and every link can earn; the button only decides what is on screen first. */
.book__item.is-folded { display: none; }
.book.is-open .book__item.is-folded { display: block; }
.book__more {
  display: flex; align-items: center; justify-content: center; gap: .4rem;
  width: 100%; margin-top: .75rem; padding: .7rem 1rem;
  border: 1px solid var(--primary); border-radius: var(--r-pill);
  background: #fff; color: var(--primary); cursor: pointer;
  font: inherit; font-size: .88rem; font-weight: 700;
  transition: background .18s var(--ease);
}
.book__more:hover { background: var(--accent-soft); }
.book__more svg { width: 15px; height: 15px; transition: transform .2s var(--ease); }
.book.is-open .book__more svg { transform: rotate(180deg); }

/* A product whose price the partner would not give us. The slot still exists so
   the cards line up, but it says what is true instead of "from" and a gap.

   The colour was --muted, which is a near-white surface token (#eef2f7) and not
   a text token: on the white card it measured about 1.1:1, so the line was
   legible only as a smear. --fg-soft is the quietest colour on the site that
   still passes AA on white, which is what this line needs to be, because on
   Popeye Village it is the ONLY thing the single booking card can say about
   price. */
.book__price--none { font-weight: 600; color: var(--fg-soft); font-size: .82rem; }

/* The search suggestion's thumbnail. Same footprint as the icon it replaces so
   the row height does not move, and the same 4:3 the cards use. */
.sug__thumb {
  width: 46px; height: 35px; flex: none; border-radius: 8px;
  object-fit: cover; background: var(--muted);
}


/* Display face. Headings and the wordmark only: the body face keeps
   its job, which is staying legible at 15px across a long article. */
h1, h2, .brand__name > :first-child, .hero h1, .ac__area + h3 {
  font-family: var(--font-display);
  letter-spacing: -0.015em;
}
.brand__name { font-family: var(--font-display); }

/* ==========================================================================
   TOP 10 TEASER, homepage
   The old compact list is gone. What is left on the homepage is three
   .plan-card tiles (an existing, previously unused component: full-bleed
   photo, gradient scrim, bottom-anchored text) plus one link through to the
   full countdown. Staggered on first paint the same way the card grid
   already is, using the same keyframe.
   ========================================================================== */
.top10__more { display: flex; width: fit-content; margin: 1.85rem auto 0; }
.top10__more svg { width: 17px; height: 17px; }
@media (prefers-reduced-motion: no-preference) {
  .plan-card { animation: acIn .5s var(--ease) backwards; animation-delay: calc(min(var(--i,0), 6) * 90ms); }
}

/* ==========================================================================
   RANKED COUNTDOWN, best-beaches-in-malta-ranked.html
   Ten large entries, editorial rather than a list with pictures bolted on:
   a full-width photograph, a rank badge overlaid on it in the reference's
   own dark-glass chip style, a short "best for" line, the reason the entry
   sits where it does, and a cue through to the guide. Odd and even entries
   swap sides at desktop width so ten rows never read as ten identical ones.
   ========================================================================== */
.ranked { list-style: none; margin: 2.5rem 0 0; padding: 0; display: grid; gap: 0; }
.rentry {
  padding-block: clamp(2.25rem, 5vw, 3.5rem); border-bottom: 1px solid var(--border-soft);
}
.rentry:first-child { padding-top: 0; }
.rentry:last-child { border-bottom: 0; padding-bottom: 0; }
.rentry__link {
  display: grid; gap: 1.5rem; grid-template-columns: 1fr; text-decoration: none; color: inherit;
}
@media (min-width: 860px) {
  .rentry__link { grid-template-columns: minmax(0,1.15fr) minmax(0,1fr); gap: 3rem; align-items: start; }
  .rentry__media { order: 1; }
  .rentry__body { order: 2; }
  .rentry:nth-child(even) .rentry__media { order: 2; }
  .rentry:nth-child(even) .rentry__body { order: 1; }
}

.rentry__media { position: relative; isolation: isolate; }
.rentry__media img {
  /* Was 4/3, which stood taller than the text beside it and left a block of
     empty page under every entry. A wider crop puts the two columns closer to
     the same height without shrinking the photograph. */
  width: 100%; aspect-ratio: 16/10; object-fit: cover; background: var(--muted);
  border-radius: var(--r-xl); box-shadow: var(--sh-lg);
}
@media (prefers-reduced-motion: no-preference) {
  .rentry__media img { transition: transform .8s var(--ease); }
  .rentry__link:hover .rentry__media img, .rentry__link:focus-visible .rentry__media img { transform: scale(1.045); }
}

/* Same dark, blurred glass the guide-hero chips use, just bigger: the one
   badge every entry needs to be legible on. */
.rentry__rank {
  position: absolute; left: 1rem; top: 1rem; z-index: 2;
  font-family: var(--font-h); font-size: clamp(1.5rem, 1.15rem + 1.2vw, 2.15rem);
  font-weight: 800; letter-spacing: -.03em; color: #fff; line-height: 1;
  background: rgba(4,26,40,.55); backdrop-filter: blur(8px);
  border: 1px solid rgba(255,255,255,.34); border-radius: 999px; padding: .5rem .95rem;
}

/* Extra photographs, only where tools/build.py's gallery_variants() found
   them on disk. Absent for most entries today and that is expected: they
   fill in as a separate job finishes generating them, with no template
   change needed here. */
.rentry__gallery { position: absolute; right: .85rem; bottom: .85rem; z-index: 2; display: flex; gap: .4rem; }
.rentry__gallery img {
  width: 44px; height: 44px; aspect-ratio: 1/1; object-fit: cover; flex: none;
  border-radius: 10px; border: 2px solid rgba(255,255,255,.85); box-shadow: 0 2px 8px rgba(4,26,40,.35);
}

.rentry__body { max-width: 46rem; }
.rentry__eyebrow {
  font-size: .82rem; font-weight: 700; letter-spacing: .04em; text-transform: uppercase;
  color: var(--fg-soft); margin-bottom: .55rem;
}
.rentry__body h2 { font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2.05rem); margin-bottom: .6rem; }
.rentry__link:hover h2, .rentry__link:focus-visible h2 { color: var(--primary-deep); }
.rentry__best {
  display: inline-flex; align-items: center; font-size: .84rem; font-weight: 700;
  color: var(--primary-deep); background: var(--accent-soft); border-radius: 999px;
  padding: .32rem .9rem; margin-bottom: .9rem;
}
.rentry__why { color: var(--fg-mid); line-height: 1.65; }
.rentry__cta {
  display: inline-flex; align-items: center; gap: .4rem; margin-top: 1.2rem;
  font-weight: 700; font-size: .93rem; color: var(--primary-deep);
}
.rentry__cta svg { width: 16px; height: 16px; }
@media (prefers-reduced-motion: no-preference) {
  .rentry__cta svg { transition: transform .2s var(--ease); }
  .rentry__link:hover .rentry__cta svg, .rentry__link:focus-visible .rentry__cta svg { transform: translateX(3px); }
  .rentry { animation: acIn .5s var(--ease) backwards; animation-delay: calc(min(var(--i,0), 9) * 70ms); }
}

/* ==========================================================================
   BUS PAGE, at-a-glance verdicts
   A small grid of cards answering "can I get there without a car" before
   any of the reasoning, plus the same tier headings restyled as bordered
   panels further down so the full, unabridged argument reads as a set of
   cards rather than one long grey column.
   ========================================================================== */
.glance { display: grid; gap: 1rem; grid-template-columns: 1fr; margin-top: 1.75rem; }
@media (min-width: 620px)  { .glance { grid-template-columns: repeat(2,1fr); } }
@media (min-width: 980px)  { .glance { grid-template-columns: repeat(3,1fr); } }
.glance__card {
  display: flex; gap: .95rem; align-items: center; padding: .9rem; text-decoration: none; color: inherit;
  border: 1px solid var(--border); border-radius: var(--r-card); background: #fff;
  transition: border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.glance__card:hover, .glance__card:focus-visible { border-color: var(--primary); transform: translateY(-3px); box-shadow: var(--sh-lg); }
.glance__card img {
  width: 64px; height: 64px; flex: none; object-fit: cover; border-radius: var(--r-sm); background: var(--muted);
}
.glance__card h3 { font-size: .96rem; font-weight: 700; color: var(--fg); margin-bottom: .3rem; line-height: 1.25; }
.glance__pill {
  display: inline-flex; align-items: center; gap: .3rem;
  font-size: .74rem; font-weight: 700; letter-spacing: .01em;
  padding: .2rem .55rem; border-radius: 999px; margin-bottom: .35rem;
}
.glance__pill svg { width: 12px; height: 12px; }
.glance__card p { font-size: .82rem; color: var(--fg-mid); line-height: 1.4; margin: 0; }
.glance__pill--go   { background: rgba(15,118,110,.12); color: var(--success); }
.glance__pill--part { background: var(--accent-soft); color: var(--primary-deep); }
.glance__pill--no   { background: rgba(199,42,61,.1); color: var(--red); }
@media (prefers-reduced-motion: no-preference) {
  .glance__card { animation: acIn .4s var(--ease) backwards; animation-delay: calc(min(var(--i,0), 9) * 45ms); }
}

/* The five tier sections, unchanged text, in a bordered card with a left
   accent bar in the same three colours as the glance pills above, so a
   reader who scrolled straight past the grid still sees the verdict before
   the paragraph. */
.tier {
  border: 1px solid var(--border-soft); border-left-width: 4px; border-radius: var(--r-card);
  padding: 1.5rem 1.6rem; margin-top: 1.5rem; background: var(--bg-tint);
}
.tier--go   { border-left-color: var(--success); }
.tier--part { border-left-color: var(--primary); }
.tier--no   { border-left-color: var(--red); }
.tier h2 { margin-top: 0; padding-top: 0; border-top: 0; }
.tier > p:first-of-type { margin-top: 0; }

/* Housekeeping pair: parking and the pre-trip checklist, side by side once
   there is room, unchanged text in a card each rather than back to back
   paragraphs. */
.duo { display: grid; gap: 1.25rem; grid-template-columns: 1fr; margin-top: 1.5rem; }
@media (min-width: 780px) { .duo { grid-template-columns: repeat(2,1fr); } }
.duo > div {
  border: 1px solid var(--border-soft); border-radius: var(--r-card); padding: 1.4rem 1.5rem; background: #fff;
}
.duo h2 { font-size: 1.15rem; margin-top: 0; padding-top: 0; border-top: 0; }


/* Sits where a price would sit, on the cards that have nothing to sell. A grid
   where some cards carry a price and others carry nothing reads as broken data,
   so each of those cards says plainly why instead of leaving a gap. Deliberately
   quieter than a price: it is information, not an offer. */
.ac__free {
  font-size: .78rem; font-weight: 700; letter-spacing: .01em;
  padding: .18rem .5rem; border-radius: 999px;
  background: var(--muted); color: var(--fg-mid); white-space: nowrap;
}


/* The container was a flat 1200px, so a 1920 screen showed a strip of content
   with 360px of dead gutter either side and a text column frozen at 499px
   however much room there was. Widened in two steps on large screens: every
   grid, rail and two-column layout takes the extra room, while prose keeps its
   own measure through .article, which is capped separately and is the thing
   that actually has to stay readable. */
@media (min-width: 1360px) { :root { --container: 1290px; } }
@media (min-width: 1500px) { :root { --container: 1380px; } }
@media (min-width: 1750px) { :root { --container: 1520px; } }
