/* ============================================================================
   theme.css — the site-wide design system.

   THE THREE COLOURS, AND THE RATIO THEY ARE USED IN
     Midnight Navy    #101B2D   ~60%  page ground, header, footer, overlays,
                                      headings, the dark half of every band
     Powder Blue      #B9D5E8   ~30%  content sections, cards, inputs, chips
     Sunflower Yellow #F5C542   ~10%  the primary CTA, the selected indicator,
                                      and small marks. Nothing else.

   Everything else in this file is a derivative of those three, chosen so the
   pairing it is actually used in clears WCAG 2.2 AA. Measured, not guessed:

     white            on navy    17.3:1      navy   on powder  11.3:1
     powder           on navy    11.3:1      navy   on yellow  10.6:1
     yellow           on navy    10.6:1
     #2C3F57 (text-2) on powder   7.0:1      #6F5400 on powder  4.7:1
     #3A4F69 (text-3) on powder   5.5:1      #5F85A3 border on tint 3.4:1

   THE ONE HARD RULE
   Sunflower Yellow against white is 1.6:1 and against Powder Blue is 1.06:1 —
   invisible. So yellow is a FILL that carries navy text, or a mark on navy.
   It is never a text or icon colour on a light surface; where the palette
   wants a gold tone in light type, --gold (#6F5400) carries it instead.

   This whole file is scoped to body. The other pages keep the
   site's existing palette, because this redesign covers the homepage only.
   ========================================================================= */
:root {
  /* ---- The three, verbatim ---------------------------------------------- */
  --navy: #101b2d;
  --powder: #b9d5e8;
  --sun: #f5c542;

  /* ---- Navy family: one step lighter each, for layered dark surfaces ---- */
  --navy-900: #101b2d;
  --navy-800: #1b2c45;
  --navy-700: #27405f;
  --navy-600: #35547a;

  /* ---- Powder family: tints above the base, for page and cards ---------- */
  --powder-400: #9cc2dc;
  --powder-300: #b9d5e8; /* the base */
  --powder-200: #d7e6f0;
  --powder-100: #e8f1f7;

  /* ---- Yellow family --------------------------------------------------- */
  --sun-400: #e0ad28; /* pressed/hover fill    */
  --sun-300: #f5c542; /* the base              */
  --sun-200: #ffda65; /* hover lift on navy    */

  /* ---- Semantic surfaces ------------------------------------------------ */
  --surface-0: #e8f1f7; /* page                             */
  --surface-1: #ffffff; /* card                             */
  --surface-2: #b9d5e8; /* the powder band — the 30% colour */
  --surface-3: #d7e6f0; /* input, chip, inactive tab        */
  --surface-bar: #101b2d;
  --surface-sunk: #101b2d;

  /* ---- Text ------------------------------------------------------------- */
  --text-1: #101b2d;
  --text-2: #2c3f57;
  --text-3: #3a4f69;
  --on-dark-1: #ffffff;
  --on-dark-2: #d7e6f0;

  /* ---- Accents ---------------------------------------------------------- */
  --accent: #101b2d;
  --accent-quiet: #1b2c45;
  --accent-bright: #f5c542;
  --accent-glow: rgb(245 197 66 / 22%);
  /* Text on an --accent background. --accent is Midnight Navy, so this is
     white: 17.3:1. It was navy, on the reasoning that the primary button is
     a yellow fill carrying navy text — but that button sets its own colours
     a few rules below, and the twelve OTHER things that pair --on-accent
     with an --accent background were all rendering navy on navy at 1:1.
     Every pressed tab on the site was invisible. */
  --on-accent: #ffffff;
  --gold: #6f5400;      /* the gold tone where it must be TEXT on light */
  --gold-300: #f5c542;
  --rule: #f5c542;
  --star: #6f5400;

  --line: #a8c6da;        /* decorative separators                        */
  --line-strong: #5f85a3; /* control borders — 3.4:1 on the page tint     */
  --line-hair: rgb(16 27 45 / 12%);

  --focus: #101b2d; /* navy ring on light; navy areas re-point it to yellow */
  --glass: rgb(232 241 247 / 94%);
  --glass-line: rgb(16 27 45 / 12%);

  --shadow-1: 0 1px 5px rgb(16 27 45 / 12%);
  --shadow-2: 0 2px 10px rgb(16 27 45 / 14%), 0 1px 3px rgb(16 27 45 / 10%);
  --shadow-3: 0 10px 34px rgb(16 27 45 / 16%), 0 2px 8px rgb(16 27 45 / 10%);
  --shadow-card: 0 14px 44px rgb(16 27 45 / 18%);
  --shadow-glow: 0 6px 22px rgb(245 197 66 / 30%);

  /* ---- Season legend ----------------------------------------------------
     The one place that steps outside the three colours, and on purpose: a
     four-key seasonal legend drawn in navy, powder and yellow would read as
     one key in four shades. These are muted to sit beside the palette rather
     than fight it, and they are never the only carrier of meaning — every
     month also states its season in words. */
  --season-dry: #648e6b;
  --season-green: #87b8d5;
  --season-rains: #cf7c34;
  --season-short: #e0a333;

}

body {
  background: var(--surface-0);
  color: var(--text-1);
}

/* On any navy ground the focus ring flips to yellow, which is 10.6:1 there
   and would be invisible on the light tints. */
body.band-navy,
body.hero-a,
body.site-header,
body.utility-bar,
body.site-footer,
body#founder,
body.visa-panel,
body.feature { --focus: #f5c542; }

[hidden] { display: none !important; }
.utility-bar,
.site-header,
.drawer { background: var(--navy-900); color: #fff; }
.utility-bar { border-color: rgb(255 255 255 / 14%); }
.utility-bar a,
.utility-clock,
.utility-rating { color: var(--powder-200); }
.site-header { border-color: rgb(255 255 255 / 16%); }
.nav-link { color: var(--powder-200); }
.nav-link:hover,
.nav-link[aria-current='page'] { color: var(--gold-300); }
.header-cta,
.btn-primary { background: var(--gold-300); border-color: var(--gold-300); color: var(--navy-900); }
.header-cta:hover,
.btn-primary:hover { background: var(--sun-200); border-color: var(--sun-200); color: var(--navy-900); }

/* Every .btn carries a `::before` sheet that wipes across it on hover and on
   focus, filled with `--btn-fill`. The component sheet sets that to
   `--accent-quiet`, which was right when the accent was green: a dark fill
   under white text.

   When the palette became navy and gold, this rule repainted the primary
   button gold with navy text — but left the wipe navy. So the moment anyone
   hovered or tabbed to "Plan your journey", "Send to a planner" or the
   consent bar's "Yes, count it", a navy sheet slid over the gold and left
   navy text on navy: 1.1:1, on every primary button on all ninety-four
   pages, and at the exact moment a keyboard user arrives at the control.
   The focus ring stayed visible, so it read as an empty pill.

   The wipe is now the lighter gold the hover state was already going to,
   which is what the rule above intended all along. `--btn-fg` is pinned too,
   because the component sheet flips it to white on hover and focus and white
   on gold is 1.8:1 — the same failure in the other direction. */
.btn-primary {
  --btn-fill: var(--sun-200);
  --btn-fg: var(--navy-900);
}
.btn-primary:hover,
.btn-primary:focus-visible {
  --btn-fg: var(--navy-900);
  color: var(--navy-900);
  border-color: var(--sun-200);
}
/* The mobile menu button.

   This said `color: #fff` and nothing else, carried over from when the rule
   lived in the homepage sheet. .chrome-btn gives it `background:
   var(--surface-1)` — white — so the hamburger was white on white: the only
   navigation control a phone has, invisible on all ninety-four pages.

   A ghost control instead, matching the navy header it sits in rather than
   punching a white disc through it. The expanded state inverts so the close
   icon is unmistakable. */
.menu-btn {
  background: transparent;
  border-color: rgb(255 255 255 / 38%);
  color: var(--on-dark-1);
}
.menu-btn:hover,
.menu-btn:focus-visible {
  background: rgb(255 255 255 / 12%);
  border-color: var(--sun-300);
  color: var(--sun-300);
}
.menu-btn[aria-expanded='true'] {
  background: var(--sun-300);
  border-color: var(--sun-300);
  color: var(--navy-900);
}
.menu-btn:focus-visible { outline: 3px solid var(--sun-300); outline-offset: 2px; }
.site-footer { background: var(--navy-900); }
.section.band-alt { background: var(--surface-2); }
.section.band { background: var(--surface-0); }
/* Headings take the ink of the band they sit on.

   The first rule was the only one here, which painted every section title
   Midnight Navy — including the titles of the bands that ARE Midnight Navy.
   "The Guide to Tanzania" and the founder's heading rendered navy-on-navy at
   1:1 and were invisible; the short gold rule under them was the only sign
   that a heading was there at all. */
.sec-title,
.eyebrow { color: var(--navy-900); }

.band-navy .sec-title,
.band-navy h3,
.cta-band .sec-title,
#founder .sec-title { color: var(--on-dark-1); }

.band-navy .sec-sub,
.cta-band .sec-sub { color: var(--on-dark-2); }

.band-navy .eyebrow,
.cta-band .eyebrow,
#founder .eyebrow { color: var(--sun-300); }


/* ---------------------------------------------------------------------------
   The wordmark on dark ground

   components.css sets `.logo-dark { display: none }` globally for a white
   header. This header is Midnight Navy, so the dark-ground mark is the right
   one here and the light-ground one has to go.

   The footer rule is a bug fix, not a design change: the footer has always
   been dark and has always used `.logo-dark`, so the global rule hid the
   footer wordmark on every page of the site. Fixed here for the homepage
   only, to stay inside this brief; the same two lines belong in
   components.css for the rest of the site. TODO-BENNY.
   ------------------------------------------------------------------------- */
.site-header .logo-light,
.drawer .logo-light { display: none; }
.site-header .logo-dark,
.drawer .logo-dark,
.site-footer .logo-dark { display: block; }
/* The dark-ground wordmark already sets "PRIVATE SAFARIS" under "MONTERO",
   so the separate .brand-sub repeated it beside itself on wide screens. The
   light-ground file does not carry that line, which is why the rest of the
   site still needs the element. */
.site-header .brand-sub { display: none; }


/* The section standfirst inherited a grey from the base sheet that lands at
   4.37:1 on Powder Blue — just under AA for text this size. --text-2 is the
   token measured for this background and gives 7.0:1. */
.sec-sub { color: var(--text-2); }


/* The currency selector in the utility bar.

   It inherited --text-2, which is a dark navy meant for light surfaces, and
   the utility bar is now Midnight Navy — about 1.4:1, effectively invisible.
   axe did not catch it because it does not evaluate a <select>'s own text
   the way it evaluates a text node. The dropdown list itself is painted by
   the operating system, so the options are given an explicit dark-on-light
   pair rather than being left to inherit into a native menu. */
.utility-bar select,
.utility-bar #cur {
  color: var(--powder-200);
  background-color: transparent;
  border-color: rgb(255 255 255 / 28%);
}
.utility-bar select option {
  color: var(--navy-900);
  background-color: #ffffff;
}
.utility-bar select:focus-visible {
  outline: 3px solid var(--sun-300);
  outline-offset: 2px;
}


/* ---------------------------------------------------------------------------
   The sticky journey bar

   It paints itself with --surface-bar, which also dresses the thin utility
   bar at the top of every page. That token went Midnight Navy with the rest
   of the theme, so this bar turned navy while its text stayed dark and the
   price became unreadable on it.

   Rather than split the token, the bar is finished as a navy bar on purpose:
   it now matches the header it mirrors, and the one thing on it that matters
   — the price and the action — is the brightest thing on it.
   ------------------------------------------------------------------------- */
.pkg-bar {
  background: var(--navy-900);
  border-top: 1px solid rgb(255 255 255 / 14%);
  box-shadow: 0 -8px 28px rgb(16 27 45 / 28%);
  color: var(--on-dark-1);
}
.pkg-bar .pb-name { color: #fff; font-weight: 750; }
.pkg-bar .pb-dur { color: var(--powder-200); }
.pkg-bar .pb-price { color: var(--powder-200); }
.pkg-bar .pb-price b { color: var(--sun-300); font-size: 1.05em; }
.pkg-bar .btn-primary {
  background: var(--sun-300);
  border-color: var(--sun-300);
  color: var(--navy-900);
}
.pkg-bar .btn-primary:hover,
.pkg-bar .btn-primary:focus-visible {
  background: var(--sun-200);
  border-color: var(--sun-200);
}
.pkg-bar :focus-visible { outline-color: var(--sun-300); }


/* ---------------------------------------------------------------------------
   Two inherited-colour traps the new palette exposed
   ------------------------------------------------------------------------- */

/* A .notice carries its own pale background, but inside a navy band it also
   inherited `.band-navy p { color: var(--on-dark-2) }` — pale text on a pale
   panel, 1.3:1. The panel is light wherever it sits, so its text is dark
   wherever it sits. */
.band-navy .notice,
.band-navy .notice p,
.band-navy .notice b,
.band-navy .notice span,
.cta-band .notice,
.cta-band .notice p { color: var(--text-2); }
.band-navy .notice b,
.cta-band .notice b { color: var(--text-1); }

/* The footer is Midnight Navy and .btn-ghost takes --btn-fg: var(--text-1),
   which is also Midnight Navy — the newsletter "Subscribe" button rendered
   as an empty outline with invisible text on all ninety-four pages. Ghost
   buttons on any dark ground now carry light type. */
.site-footer .btn-ghost,
.band-navy .btn-ghost,
.cta-band .btn-ghost,
.hero-a .btn-ghost,
.ap-out .btn-ghost,
.btn-ghost.btn-on-dark {
  color: var(--on-dark-1);
  border-color: rgb(255 255 255 / 45%);
}
.ap-out .btn-ghost:hover,
.ap-out .btn-ghost:focus-visible,
.site-footer .btn-ghost:hover,
.site-footer .btn-ghost:focus-visible,
.band-navy .btn-ghost:hover,
.band-navy .btn-ghost:focus-visible,
.cta-band .btn-ghost:hover,
.cta-band .btn-ghost:focus-visible,
.hero-a .btn-ghost:hover,
.hero-a .btn-ghost:focus-visible,
.btn-ghost.btn-on-dark:hover,
.btn-ghost.btn-on-dark:focus-visible {
  color: var(--navy-900);
  border-color: var(--sun-300);
  background: var(--sun-300);
}
.ap-out .btn-ghost::before,
.site-footer .btn-ghost::before,
.band-navy .btn-ghost::before,
.cta-band .btn-ghost::before,
.hero-a .btn-ghost::before { background: var(--sun-300); }


/* The "UNVERIFIED" state label on a credential badge. It hardcoded a warm
   grey pair from the old palette at 4.15:1 — under AA for text this small,
   and this is the label that tells a reader a credential is NOT held, which
   is the last thing on the site that should be hard to read. Palette tones
   instead, at 8.4:1. */
.bdg-state {
  background: var(--powder-200);
  color: var(--text-2);
}
.bdg[data-state='verified'] .bdg-state {
  background: var(--accent);
  color: var(--on-accent);
}


/* ---------------------------------------------------------------------------
   Small category labels sitting on a photograph

   Both of these were a gold tone — #f0c46a on the journey hero, --gold on a
   card. Gold is a fill colour in this palette, not a text colour, and over
   an unpredictable photograph it is worse still: measured from the rendered
   pixels the hero eyebrow ran between 2.6:1 and 5.1:1 depending purely on
   which photograph was behind it, and the card label at 3.1:1. Both are
   small uppercase type, which needs 4.5:1.

   The gold stays where it works: the short rule under a section heading, and
   the filled buttons.
   A shadow alone was not enough: it lifted the worst case from 2.6:1 only to
   3.8:1, because a glow spread over a bright photograph still leaves the
   type sitting on that photograph. These get a ground of their own instead —
   a small translucent navy chip, which is the same device the duration pill
   on a card already uses, so it reads as deliberate rather than patched. The
   contrast is then a property of the chip, not of whichever photograph the
   journey happens to use.
   ------------------------------------------------------------------------- */
.jhero-eyebrow,
.tour-over .tour-cat,
.jcard-media + .jcard-text .jcard-tag {
  /* block + fit-content, NOT inline-block: these sit directly above a
     heading, and inline-block let the chip share a line with it. */
  display: block;
  width: fit-content;
  max-width: 100%;
  padding: 0.22em 0.62em;
  border-radius: var(--r-pill, 999px);
  background: rgb(16 27 45 / 72%);
  color: #ffffff;
  text-shadow: none;
  backdrop-filter: blur(3px);
}


/* ---------------------------------------------------------------------------
   "The detail" — the reference accordion on a journey page

   Three full-width sections (inclusions, practical detail, personalisation)
   folded into one band of collapsed <details>. Reuses the .faq accordion the
   day-by-day and the questions already use, so the page has one disclosure
   idiom rather than three.
   ------------------------------------------------------------------------- */
.measure-wide {
  width: min(100% - (var(--gutter) * 2), 64rem);
  margin-inline: auto;
}
.jref > .faq + .faq { margin-top: 0.6rem; }
.jref .faq-a { padding-top: 0.25rem; }
.jref .two-col { gap: clamp(1rem, 3vw, 2.5rem); }
.jref-h {
  margin: 0 0 0.75rem;
  font-size: var(--t-base);
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--text-1);
}
.jref-p {
  margin: 0 0 1rem;
  max-width: 62ch;
  color: var(--text-2);
  font-size: var(--t-sm);
  line-height: 1.65;
}
.jref .certs,
.jref .checks { margin-top: 0; }


/* ---------------------------------------------------------------------------
   Photography credits

   Forty-two credits, each rendered as a card with a full-width 16:9
   photograph, came to nineteen thousand pixels — twenty-three phone screens
   for nine hundred words. A credits page is a reference list that somebody
   scans for one filename; the photograph only has to be big enough to
   recognise.

   So: a fixed thumbnail beside the text, and two columns once there is room.
   Same content, same images, about a fifth of the height.
   ------------------------------------------------------------------------- */
.credit-grid {
  grid-template-columns: 1fr;
  gap: 0.5rem;
}
@media (width >= 48rem) {
  .credit-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (width >= 86rem) {
  .credit-grid { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.credit-item {
  grid-template-columns: 5rem minmax(0, 1fr);
  gap: 0.75rem;
  align-items: start;
  padding: 0.6rem;
}
.credit-item .media {
  inline-size: 5rem;
  block-size: 3.5rem;
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-s);
}
.credit-item .media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
}
.credit-item figcaption { min-inline-size: 0; line-height: 1.45; }
.credit-item b {
  display: block;
  overflow-wrap: anywhere;
  margin-bottom: 0.15rem;
}


/* ---------------------------------------------------------------------------
   Journey cards on a phone

   .tour is locked to aspect-ratio 3/4. On a 375px screen that makes every
   card 457px tall whatever is in it, and the middle of the card is empty —
   the title sits at the top, the price at the bottom, and a third of the
   photograph in between does nothing. Thirty-two of them came to twenty-two
   thousand pixels.

   On a narrow screen the card is sized by its content instead, with a floor
   so the photograph still reads. The 3/4 portrait stays on wider screens,
   where cards sit side by side and a consistent ratio is what makes the grid
   look like a grid.
   ------------------------------------------------------------------------- */
@media (width < 44rem) {
  .tour {
    aspect-ratio: auto;
    min-block-size: 19rem;
  }
  .tour .tour-body > p {
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    overflow: hidden;
  }
}


/* The filter panel on a phone: six groups of pills, each wrapping to two or
   three lines, ran about a screen and a half before the first journey. The
   pills are kept wrapped rather than put into horizontal scrollers — a
   scroller hides options, and this is the page where somebody filters for
   step-free travel — but the spacing is tightened. Touch targets stay at
   44px. */
@media (width < 44rem) {
  .filter-grid { gap: 0.55rem; }
  .filter-row { gap: 0.3rem; }
  .filter-legend { margin-bottom: 0.15rem; font-size: 0.68rem; }
  .filter-row .tabs { gap: 0.3rem; }
  .filter-row .tab {
    min-height: 44px;
    padding-inline: 0.8rem;
    font-size: 0.8rem;
  }
}


/* ---------------------------------------------------------------------------
   The inner-page header

   .page-head carried an "aurora": three big blurred circles tinted with
   --accent, --sp-6 and --gold, blended with mix-blend-mode over the page.
   Under the old green palette that was a soft wash. With --accent now navy
   and --gold a dark brown-gold, screen-blended over a pale page, it came out
   as a muddy grey gradient that read as an unfinished image placeholder on
   every one of the ninety inner pages.

   The band is Midnight Navy instead. It continues the header above it, gives
   each page a proper anchor instead of pale-on-pale, and matches the way the
   homepage hero and the footer already sit. The aurora stays, but tinted to
   the palette and turned down, so it is a slow movement in the navy rather
   than a wash of its own.
   ------------------------------------------------------------------------- */
.page-head {
  background: var(--navy-900);
  color: var(--on-dark-1);
  border-bottom: 0;
}
.page-head .sec-title,
.page-head h1 { color: var(--on-dark-1); }
.page-head .lede { color: var(--powder-200); }
.page-head .crumbs,
.page-head .crumbs li { color: var(--powder-400); }
.page-head .crumbs a { color: var(--powder-200); }
.page-head .crumbs a:hover { color: var(--sun-300); }
.page-head .eyebrow { color: var(--sun-300); }
.page-head :focus-visible { outline-color: var(--sun-300); }

/* Palette tints, and much quieter — on a dark ground these read as depth
   rather than as a gradient someone forgot to replace. */
.page-head .aurora { --aurora-op: 0.5; }
.page-head .aurora i { mix-blend-mode: screen; opacity: 0.2; filter: blur(110px); }
:root[data-theme='light'] .page-head .aurora i { mix-blend-mode: screen; opacity: 0.2; }
.page-head .aurora i:nth-child(1) { background: #2f6f9e; }
.page-head .aurora i:nth-child(2) { background: #1d3a5c; }
.page-head .aurora i:nth-child(3) { background: var(--sun-300); opacity: 0.1; }


/* ---------------------------------------------------------------------------
   The mobile drawer

   The drawer gets its Midnight Navy ground from the chrome rule at the top
   of this file, but its link colour came from the old light-header palette,
   so every navigation label in it rendered navy on navy. It is the whole
   navigation on a phone and it was unreadable.

   The contrast sweep did not catch this, because the drawer is closed when a
   page loads and the sweep only scans what is painted. tools/sweep-contrast
   now opens it. Anything else that is hidden at load — a dialog, a popover —
   needs the same treatment before it can be trusted as checked.
   ------------------------------------------------------------------------- */
.drawer { color: var(--on-dark-1); }
.drawer .drawer-link {
  color: var(--on-dark-1);
  border-color: rgb(255 255 255 / 20%);
}
.drawer .drawer-link:hover,
.drawer .drawer-link:focus-visible { color: var(--sun-300); }
.drawer .drawer-link[aria-current='page'] { color: var(--sun-300); }
.drawer .drawer-link::after,
.drawer .drawer-link > span:last-child { color: var(--powder-400); }
.drawer .drawer-note,
.drawer .drawer-note a { color: var(--powder-200); }
.drawer .drawer-note a:hover { color: var(--sun-300); }
.drawer :focus-visible { outline: 3px solid var(--sun-300); outline-offset: 2px; }


/* The drawer reserves a header-height row at the top of itself, which only
   makes sense if the header shows through it — but the drawer is z-index 400
   against the header's 200, and its background is opaque, so it covered the
   header and with it the close button. The drawer could be opened and then
   only dismissed with Escape or by following a link.

   The header is lifted above the overlay while the drawer is open, so the
   same button that opened it closes it. Scoped with :has() to that state
   only, so the header does not start sitting on top of other overlays. */
.site-header:has(.menu-btn[aria-expanded='true']) {
  z-index: calc(var(--z-overlay) + 1);
}


/* ---------------------------------------------------------------------------
   The safari catalogue grid

   The cards read as scattered, and it was not the photographs — it was that
   every text block inside them was a different height. A one-line title sat
   where another card's two-line title ended, the route ran to one or two
   lines depending on how many parks it names, and the blurbs truncated at
   whatever point they happened to reach. Nothing lined up across a row, so
   the eye had no horizontal rhythm to follow.

   The fix is to give every card the same internal geometry: the title always
   occupies two lines, the route always one, the blurb always two. Short ones
   leave white space rather than pulling everything above them upward. Three
   to a row instead of four, so each has room to be read.
   ------------------------------------------------------------------------- */
#journey-list.tours {
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 20rem), 1fr));
  gap: clamp(1rem, 2vw, 1.5rem);
}
@media (width >= 76rem) {
  #journey-list.tours { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

#journey-list .tour-over h2 {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 2.4em;
  font-size: 1.12rem;
  line-height: 1.2;
}
#journey-list .tour-over > p {
  display: -webkit-box;
  -webkit-line-clamp: 1;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 1.45em;
}
#journey-list .tour-body > p {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 3.1em;
}

/* A lighter veil than the homepage rail uses. These cards carry less text,
   and at four hundred pixels wide the photograph is most of what tells a
   reader whether a journey is for them — it should still look like a
   photograph. Measured, not guessed: see tools/measure-contrast.py. */
#journey-list .tour > .tour-media::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(180deg,
      rgb(13 22 37 / 82%) 0%,
      rgb(13 22 37 / 46%) 30%,
      rgb(13 22 37 / 40%) 50%,
      rgb(13 22 37 / 80%) 78%,
      rgb(13 22 37 / 93%) 100%);
}

/* The save control was a plain circle floating on the photograph. */
#journey-list .save-btn {
  background: rgb(16 27 45 / 55%);
  border: 1px solid rgb(255 255 255 / 30%);
  color: #fff;
  backdrop-filter: blur(4px);
}
#journey-list .save-btn:hover,
#journey-list .save-btn:focus-visible {
  background: var(--sun-300);
  border-color: var(--sun-300);
  color: var(--navy-900);
}

/* "View more" */
.more-wrap {
  display: grid;
  justify-items: center;
  gap: 0.6rem;
  margin-top: clamp(1.5rem, 4vw, 2.5rem);
}
.more-wrap[hidden] { display: none; }
.more-count { opacity: 0.75; font-weight: 600; }
.more-note {
  margin: 0;
  color: var(--text-3);
  font-size: var(--t-xs);
}


/* ===========================================================================
   THE ITINERARY

   A timeline that reads like a table. Each day is a row on a rail; the
   summary carries day, title, place, overnight and meals in fixed columns,
   so they line up down the page and can be compared without opening
   anything. The narrative is behind the disclosure.

   The column headings above the rows are decorative — every row repeats
   them as .itin-k labels, which is what a narrow screen shows and what a
   screen reader reads.
   ========================================================================= */
.itin-head,
.itin-day > summary {
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1.5fr) minmax(0, 1fr) minmax(0, 1fr) 7.5rem 1.5rem;
  gap: 0.75rem 1rem;
  align-items: center;
}
.itin-head {
  margin: 0 0 0.5rem;
  padding: 0 1.1rem 0.6rem 1.1rem;
  border-bottom: 1px solid var(--line);
  color: var(--text-3);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
/* The headings must sit on exactly the same columns as the rows. An
   earlier version spanned the first heading across columns 1-2, which put
   every label one column right of the content it described. */
.itin-head > :nth-child(1) { grid-column: 1; }
.itin-head > :nth-child(2) { grid-column: 2; }
.itin-head > :nth-child(3) { grid-column: 3; }
.itin-head > :nth-child(4) { grid-column: 4; }
.itin-head > :nth-child(5) { grid-column: 5; }

.itin {
  position: relative;
  margin: 0;
  padding: 0;
  list-style: none;
}
/* The rail. It stops short at both ends so it reads as a journey with a
   beginning and an end rather than a line running off the section. */
.itin::before {
  content: '';
  position: absolute;
  inset-block: 2.2rem;
  inset-inline-start: 2.72rem;
  inline-size: 2px;
  background: linear-gradient(180deg,
    transparent, var(--powder-400) 6%, var(--powder-400) 94%, transparent);
}
.itin-row { position: relative; }
.itin-row + .itin-row { margin-top: 0.5rem; }

.itin-day {
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-1);
  transition: border-color 180ms ease, box-shadow 180ms ease;
}
.itin-day[open] {
  border-color: var(--powder-400);
  box-shadow: var(--shadow-2);
}
.itin-day > summary {
  padding: 0.9rem 1.1rem;
  cursor: pointer;
  list-style: none;
}
.itin-day > summary::-webkit-details-marker { display: none; }
.itin-day > summary:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: -3px;
  border-radius: var(--r-m);
}

/* The node sits on the rail, so it needs the card's own background behind
   it to punch a hole in the line. */
.itin-node {
  position: absolute;
  inset-block-start: 1.05rem;
  inset-inline-start: -0.22rem;
  z-index: 1;
  inline-size: 2rem;
  block-size: 2rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 2px solid var(--surface-1);
  background: var(--navy-900);
  color: #fff;
  font-size: 0.78rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
}
.itin-day[open] .itin-node { background: var(--sun-300); color: var(--navy-900); }
.itin-day-n { visibility: hidden; }

.itin-cell { min-inline-size: 0; font-size: var(--t-sm); color: var(--text-2); }
.itin-k { display: none; }
.itin-title {
  color: var(--text-1);
  font-size: var(--t-base);
  font-weight: 750;
  line-height: 1.3;
}
.itin-meals .meals { display: inline-flex; gap: 0.25rem; }
.itin-day .meal {
  display: grid;
  place-items: center;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  border-radius: 50%;
  background: var(--powder-200);
  color: var(--navy-900);
  font-size: 0.68rem;
  font-weight: 800;
}
.itin-day .meal abbr { text-decoration: none; }
.itin-day .meal-none {
  inline-size: auto;
  block-size: auto;
  padding: 0.1rem 0.45rem;
  border-radius: 999px;
  background: transparent;
  border: 1px dashed var(--line-strong);
  color: var(--text-3);
  font-weight: 650;
}
/* package.css pins `.day > summary::after` to grid-column 3 for the old
   three-column accordion. This summary has six columns, so that rule put
   the marker in the middle of the row and shoved the meal chips off the
   edge of the card. The marker belongs in the last column. */
.itin-day > summary::after {
  content: '+';
  grid-column: 6;
  grid-row: 1;
  justify-self: end;
  color: var(--navy-900);
  font-size: 1.15rem;
  line-height: 1;
}
.itin-day[open] > summary::after { content: '\2212'; }

.itin-body {
  padding: 0 1.1rem 1.15rem calc(1.1rem + 3.25rem + 1rem);
}
.itin-body > p {
  margin: 0;
  max-width: 68ch;
  color: var(--text-2);
  font-size: var(--t-sm);
  line-height: 1.75;
}

@media (width < 60rem) {
  .itin-head { display: none; }
  .itin::before { inset-inline-start: 1.32rem; }
  .itin-day > summary {
    grid-template-columns: minmax(0, 1fr) 1.5rem;
    padding-inline-start: 3.1rem;
    gap: 0.35rem 0.75rem;
  }
  .itin-node { inset-inline-start: 0.35rem; inset-block-start: 0.95rem; }
  .itin-cell { grid-column: 1; }
  .itin-day-n {
    visibility: visible;
    order: -1;
    color: var(--text-3);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: var(--track-wider);
    text-transform: uppercase;
  }
  .itin-day-n .itin-k { display: inline; margin-inline-end: 0.3rem; }
  .itin-k {
    display: inline;
    margin-inline-end: 0.35rem;
    color: var(--text-3);
    font-size: 0.68rem;
    font-weight: 800;
    letter-spacing: var(--track-wider);
    text-transform: uppercase;
  }
  .itin-day > summary::after { grid-column: 2; grid-row: 1; align-self: start; }
  .itin-body { padding-inline-start: 3.1rem; }
}

/* ===========================================================================
   THE PLACE GALLERY
   ========================================================================= */
.gal {
  display: grid;
  /* Two up on a phone. One full-width column per photograph added about two
     and a half screens of scrolling to a page that is already long, and
     these are thumbnails into a lightbox rather than the main event — they
     only need to be big enough to recognise and to tap. */
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(0.5rem, 1.5vw, 1rem);
}
@media (width >= 44rem) {
  .gal { grid-template-columns: repeat(auto-fit, minmax(min(100%, 17rem), 1fr)); }
}
/* Capped at three. A four-wide grid left the six-image galleries as a row
   of four and a row of two, which reads as a mistake; three gives 3+3 for
   six and 3+2 for five. */
@media (width >= 64rem) {
  .gal { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}
.gal-item {
  display: grid;
  gap: 0;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  overflow: hidden;
  background: var(--surface-1);
  text-align: start;
  font: inherit;
  cursor: zoom-in;
  transition: border-color 180ms ease, box-shadow 180ms ease, translate 180ms ease;
}
.gal-item:hover,
.gal-item:focus-visible {
  border-color: var(--powder-400);
  box-shadow: var(--shadow-2);
  translate: 0 -2px;
}
.gal-item:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.gal-media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
}
/* <picture> is an inline box by default and does not stretch, so the img's
   block-size: 100% resolved against auto and every photograph sat at its own
   aspect ratio in the top of the tile with the placeholder tint showing
   underneath. The picture has to be a block that fills the tile first. */
.gal-media picture {
  display: block;
  inline-size: 100%;
  block-size: 100%;
}
.gal-media img {
  inline-size: 100%;
  block-size: 100%;
  object-fit: cover;
  transition: scale 600ms cubic-bezier(.2, .8, .2, 1);
}
.gal-item:hover .gal-media img,
.gal-item:focus-visible .gal-media img { scale: 1.05; }
.gal-cap {
  display: grid;
  gap: 0.15rem;
  padding: 0.7rem 0.85rem 0.85rem;
}

.gal-cap b { color: var(--text-1); font-size: var(--t-sm); }
/* Two lines always, so tiles in a row are the same height whether the
   description runs to one line or three. */
.gal-cap span {
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
  min-block-size: 2.9em;
  color: var(--text-3);
  font-size: var(--t-xs);
  line-height: 1.45;
}

.gal-note {
  display: flex;
  gap: 0.6rem;
  max-width: 76ch;
  margin: 1.5rem auto 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--sun-300);
  border-radius: var(--r-s);
  background: var(--powder-100);
  color: var(--text-2);
  font-size: var(--t-xs);
  line-height: 1.65;
}
.gal-note > svg {
  flex: none;
  inline-size: 1.05rem;
  block-size: 1.05rem;
  margin-top: 0.12rem;
  color: var(--gold);
}

/* The lightbox. A native <dialog>, so Escape and the top layer are free. */
.gal-box {
  inline-size: min(68rem, calc(100vw - 2rem));
  max-block-size: min(92vh, 56rem);
  padding: 0;
  border: 0;
  border-radius: var(--r-m);
  background: var(--navy-900);
  color: var(--on-dark-1);
  overflow: hidden;
}
.gal-box::backdrop { background: rgb(8 14 24 / 82%); backdrop-filter: blur(5px); }
.gal-box-fig { display: grid; margin: 0; }
.gal-box img {
  inline-size: 100%;
  max-block-size: 74vh;
  object-fit: contain;
  background: #0b1422;
}
.gal-box figcaption {
  display: grid;
  gap: 0.2rem;
  padding: 0.9rem 1.1rem;
  border-top: 1px solid rgb(255 255 255 / 12%);
}
.gal-box figcaption b { color: #fff; }
.gal-box figcaption span { color: var(--powder-200); font-size: var(--t-sm); }
.gal-box-bar {
  position: absolute;
  inset: 0.6rem 0.6rem auto auto;
  display: flex;
  gap: 0.4rem;
}
.gal-nav,
.gal-close {
  inline-size: 44px;
  block-size: 44px;
  display: grid;
  place-items: center;
  border: 1px solid rgb(255 255 255 / 32%);
  border-radius: 50%;
  background: rgb(16 27 45 / 72%);
  color: #fff;
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.gal-nav:hover, .gal-close:hover,
.gal-nav:focus-visible, .gal-close:focus-visible {
  background: var(--sun-300);
  border-color: var(--sun-300);
  color: var(--navy-900);
}
.gal-nav svg, .gal-close svg { inline-size: 1.1rem; block-size: 1.1rem; }
.gal-prev { position: absolute; inset: 50% auto auto 0.6rem; translate: 0 -50%; }
.gal-next { position: absolute; inset: 50% 0.6rem auto auto; translate: 0 -50%; }

@media (prefers-reduced-motion: reduce) {
  .gal-item, .gal-media img, .itin-day { transition: none; }
  .gal-item:hover .gal-media img { scale: 1; }
  .gal-item:hover { translate: none; }
}


/* The "How to read this page" intro on the safari catalogue.
   A heading beside its prose, and a tighter band: the old version was a
   narrow centred column with a hidden heading, floating in a tall empty
   section with a large gap before the filters. */
.section-intro { padding-block: clamp(1.75rem, 4vw, 3rem); }
.intro-split {
  display: grid;
  gap: clamp(0.75rem, 3vw, 3rem);
  align-items: start;
}
@media (width >= 60rem) {
  .intro-split { grid-template-columns: minmax(0, 15rem) minmax(0, 1fr); }
}
.intro-h {
  margin: 0;
  color: var(--text-1);
  font-size: var(--t-lg);
  line-height: 1.2;
  letter-spacing: -0.01em;
}
.intro-body { display: grid; gap: 0.85rem; max-width: 68ch; }
.intro-body p { margin: 0; color: var(--text-2); line-height: 1.7; }


/* At two up on a phone the description would crowd a 170px column, so only
   the place name is shown; the full description is in the lightbox and in
   the image's alt text either way.

   This has to come after the `.gal-cap span { display: -webkit-box }` rule
   above rather than next to the rest of the gallery's mobile styles — same
   specificity, so the later rule wins, and placed earlier it did nothing. */
@media (width < 44rem) {
  .gal-cap { padding: 0.5rem 0.6rem 0.65rem; }
  .gal-cap span { display: none; }
  .gal-cap b { font-size: var(--t-xs); }
  .gal-media { aspect-ratio: 1 / 1; }
}


/* ===========================================================================
   THE JOURNEY PAGE LAYOUT

   One scrolling column against one left edge, and a price panel that stays
   put beside it. Before this only the opening section was in the two-column
   grid, so the left edge moved after the first screen and the price went out
   of sight for the rest of the page.

   The sections inside the column keep their own rhythm, but their banded
   backgrounds become panels rather than full-bleed bands — a full-bleed band
   inside a column is just a wide box with nothing either side of it.
   ========================================================================= */
.jlayout { align-items: start; }
.jmain { min-inline-size: 0; }

/* The inner .shell of each section must not re-centre or re-constrain:
   the column is already the measure. */
.jmain .section > .shell,
.jmain .section > .shell-text {
  inline-size: 100%;
  max-inline-size: none;
  margin-inline: 0;
}
.jmain .section {
  padding-block: clamp(1.5rem, 3.2vw, 2.5rem);
  /* The SAME inline padding on every section, banded or not. Only the
     banded ones had it, so their text sat ~28px right of everything else
     and the column had two left edges — which is the misalignment that
     made this page feel scattered in the first place. */
  padding-inline: clamp(1rem, 2.5vw, 1.75rem);
}
.jmain .section-lede { padding-block-start: clamp(1.25rem, 2.5vw, 2rem); }
.jmain .section-lede .lede { max-width: 68ch; }
.jmain .section-lede p + p { margin-top: 0.7rem; }

/* Banded sections become panels inside the column. */
.jmain .section.band,
.jmain .section.band-navy { border-radius: var(--r-m); }
.jmain .section.band { background: var(--surface-2); }
.jmain .section.band-navy { background: var(--navy-900); }
.jmain .section + .section { margin-block-start: 0.5rem; }

/* Section headings in a column are left-aligned: a centred heading over a
   left-aligned column looks like a mistake. */
.jmain .sec-head-c,
.jmain .sec-head-c.has-sub { text-align: start; }
.jmain .sec-head-c .sec-title::after { margin-inline: 0; }
.jmain .sec-sub { margin-inline: 0; }
.jmain .center { text-align: start; margin-inline: 0; }

.jside { min-inline-size: 0; }
@media (width >= 64rem) {
  .jside {
    position: sticky;
    inset-block-start: calc(var(--header-h, 4.5rem) + 1.25rem);
  }
}
/* On a phone the aside stacks, and the price belongs near the top rather
   than after fourteen screens of itinerary.

   align-items: stretch is not optional here. .booking-layout sets
   align-items: start, which on a COLUMN flex container is the cross axis —
   horizontal — so both children shrank to their content width and the
   content column measured zero pixels wide. */
@media (width < 64rem) {
  .jlayout {
    display: flex;
    flex-direction: column;
    align-items: stretch;
  }
  .jmain,
  .jside { inline-size: 100%; }
  .jside { order: -1; }
}


/* The sections inside the column are laid out against the COLUMN, not the
   window. .two-col and the itinerary both switch on a viewport media query,
   which was right when they were full width and wrong now: at 1440px the
   window says "wide" while the column is only about 820px, so Highlights
   and Route were squeezed into two cramped halves and the route table was
   cut off by the price panel.

   A container query asks the right question. */
.jmain { container-type: inline-size; container-name: jcol; }

@container jcol (width < 58rem) {
  .two-col,
  .two-col-media { grid-template-columns: 1fr; }
  .itin-head { display: none; }
  .itin-day > summary {
    grid-template-columns: minmax(0, 1fr) 1.5rem;
    padding-inline-start: 3.1rem;
    gap: 0.3rem 0.75rem;
  }
  .itin::before { inset-inline-start: 1.32rem; }
  .itin-node { inset-inline-start: 0.35rem; inset-block-start: 0.95rem; }
  .itin-cell { grid-column: 1; }
  .itin-day-n { visibility: visible; order: -1; }
  .itin-day-n .itin-k,
  .itin-k { display: inline; margin-inline-end: 0.35rem; color: var(--text-3);
            font-size: 0.68rem; font-weight: 800;
            letter-spacing: var(--track-wider); text-transform: uppercase; }
  .itin-day > summary::after { grid-column: 2; grid-row: 1; align-self: start; }
  .itin-body { padding-inline-start: 3.1rem; }
  .gal { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* A wide table in a column scrolls rather than being clipped by the price
   panel; say so, because a scroller nobody notices is a table with its
   right-hand column missing. */
.jmain .matrix-scroll { overflow-x: auto; }
.jmain .matrix-scroll:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

/* Highlights read as a list again. */
.jmain .legend-note { padding-inline-start: 1.15rem; }
.jmain .legend-note li { margin-block: 0.35rem; line-height: 1.6; }


/* The real route map, and its pins. */
.rm-osm {
  block-size: clamp(20rem, 42vw, 27rem);
  overflow: hidden;
  border-radius: var(--r-s);
  background: #0b1422;
}
.rm-osm[hidden] { display: none; }
.rm-osm .maplibregl-ctrl-attrib {
  color: var(--navy-900);
  background: rgb(248 251 253 / 92%);
}
.rm-pin {
  display: flex;
  align-items: center;
  gap: 0.3rem;
  cursor: default;
}
.rm-pin-n {
  display: grid;
  place-items: center;
  inline-size: 1.5rem;
  block-size: 1.5rem;
  padding-inline: 0.2rem;
  border: 2px solid #fff;
  border-radius: 999px;
  background: var(--navy-900);
  color: #fff;
  font: 800 0.68rem/1 var(--font-ui);
  font-variant-numeric: tabular-nums;
  box-shadow: 0 2px 7px rgb(10 20 35 / 45%);
}
.rm-pin-l {
  padding: 0.12rem 0.4rem;
  border-radius: 4px;
  background: rgb(16 27 45 / 82%);
  color: #fff;
  font: 700 0.68rem/1.25 var(--font-ui);
  white-space: nowrap;
  backdrop-filter: blur(3px);
}
.rm-note {
  margin: 0.6rem 0 0;
  color: var(--text-3);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.rm-note[hidden] { display: none; }


/* ---------------------------------------------------------------------------
   "Where you would sleep this night"

   The accommodation standards that fit a given night, under that day in the
   itinerary. Standards, not named properties — see the note in the markup
   and _stay_cards() in tools/package_ui.py.
   ------------------------------------------------------------------------- */
.stayopts {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.so-h {
  margin: 0 0 0.3rem;
  font-size: var(--t-sm);
  font-weight: 800;
  letter-spacing: 0.01em;
  color: var(--text-1);
}
.so-note {
  margin: 0 0 0.85rem;
  max-width: 70ch;
  color: var(--text-3);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.so-list {
  display: grid;
  gap: 0.6rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
.so {
  display: grid;
  grid-template-columns: 8.5rem minmax(0, 1fr);
  gap: 0.9rem;
  align-items: start;
  padding: 0.6rem;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--surface-1);
}
.so-media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: 5px;
}
.so-media picture { display: block; inline-size: 100%; block-size: 100%; }
.so-media img { inline-size: 100%; block-size: 100%; object-fit: cover; }

/* The standard with no usable photograph says so rather than borrowing one. */
.so-nophoto {
  display: grid;
  place-items: center;
  align-content: center;
  gap: 0.3rem;
  padding: 0.4rem;
  border: 1px dashed var(--line-strong);
  background: var(--powder-100);
  color: var(--text-3);
  text-align: center;
  font-size: 0.64rem;
  line-height: 1.3;
}
.so-nophoto svg { inline-size: 1.1rem; block-size: 1.1rem; color: var(--gold); }

.so-text { display: grid; gap: 0.25rem; min-inline-size: 0; }
.so-text > b { color: var(--text-1); font-size: var(--t-sm); }
.so-rooms { color: var(--text-2); font-size: var(--t-xs); line-height: 1.55; }
.so-acc { color: var(--text-3); font-size: var(--t-xs); line-height: 1.55; }
.so-acc b { color: var(--text-2); }

@container jcol (width < 34rem) {
  .so { grid-template-columns: 5.5rem minmax(0, 1fr); gap: 0.7rem; }
}


/* The compact per-night card: thumbnail, name, room line. The full
   specification lives once in the Stay section rather than thirteen times
   down the itinerary. */
.so { grid-template-columns: 5.5rem minmax(0, 1fr); gap: 0.75rem; align-items: center; }
.so-list { grid-template-columns: repeat(auto-fit, minmax(min(100%, 19rem), 1fr)); }
.so-note a { color: var(--navy-900); font-weight: 700; }


/* The route map was being squeezed into the left half of a two-column block
   that itself sits inside the content column: 428px wide on a desktop and
   264px on a phone, which is not a map, it is a stamp. Inside the column the
   map takes the full width and the ordered list of stops sits under it. */
.jmain .rm-wrap { grid-template-columns: 1fr; gap: 1rem; }
.jmain .rm-osm { block-size: clamp(19rem, 48vw, 30rem); }
.jmain .rm-list { margin-top: 0.25rem; }
.jmain .rm-steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: 0.15rem 1.25rem;
}


/* .rm-figure carries 21.6px of padding on each side. Inside a 341px column
   on a phone that is 43px of the map's width spent on nothing, so it goes
   nearly edge to edge there and keeps the padding where there is room. */
@container jcol (width < 34rem) {
  .rm-figure { padding-inline: 0.35rem; }
  .jmain .rm-osm { block-size: clamp(17rem, 62vw, 22rem); }
}


/* ---------------------------------------------------------------------------
   The in-page section nav follows the header

   .jump sticks at a fixed offset of --header-h. The header hides on scroll
   down by translating itself off the top, so the section nav was left
   floating with an empty header-height gap above it, and then jumped back
   down when the header returned.

   It now takes the header's place while the header is away: the same
   position, and the same transition so the two move as one strip rather
   than one sliding and the other snapping.
   ------------------------------------------------------------------------- */
.jump {
  transition: inset-block-start var(--d-base, 260ms) var(--e-soft, ease);
}
body:has(.site-header[data-hidden='true']) .jump {
  inset-block-start: 0;
}

/* Reduced motion: still move, just do not animate it. */
@media (prefers-reduced-motion: reduce) {
  .jump { transition: none; }
}

/* An anchor jumped to from the section nav must clear BOTH bars, or the
   heading lands underneath them. */
.jmain [id] { scroll-margin-block-start: calc(var(--header-h, 4.5rem) + 4rem); }


/* ---------------------------------------------------------------------------
   Experience page opening

   Was a full-width photograph about 450px tall with three paragraphs
   underneath — 7.8 desktop screens for 777 words, and no structure for the
   eye to hold on to. The photograph sits beside the prose now and is held
   to one shape, so a panorama and a near-square image open the same way.
   ------------------------------------------------------------------------- */
.xp-intro {
  display: grid;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  align-items: start;
}
@media (width >= 60rem) {
  .xp-intro { grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.1fr); }
}
.xp-media {
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  border-radius: var(--r-m);
  margin: 0;
}
.xp-media picture { display: block; inline-size: 100%; block-size: 100%; }
.xp-media img { inline-size: 100%; block-size: 100%; object-fit: cover; }
@media (width >= 60rem) {
  /* Sticks while the prose scrolls past it, which is what makes the two
     columns read as one block rather than two lists of different lengths. */
  .xp-media { position: sticky; inset-block-start: calc(var(--header-h, 4.5rem) + 1.5rem); }
}
.xp-text { display: grid; gap: 0.9rem; max-width: 62ch; }
.xp-text p { margin: 0; line-height: 1.75; color: var(--text-2); }
.xp-lede {
  font-size: var(--t-md);
  line-height: 1.65 !important;
  color: var(--text-1) !important;
  font-weight: 450;
}


/* ===========================================================================
   THE MONTH CALENDAR

   Modelled on the reference layout — a strip of month pills coloured by
   season, a key, then a detail panel with the month's notes beside four
   stat tiles — in this site's palette rather than the reference's oranges.

   The season colours are the same four used by the homepage legend and are
   the one place the palette is deliberately left: four seasons drawn in
   navy, powder and yellow would be one season in four shades. They are
   never the only carrier of meaning — every pill's season is also written
   in the panel below it.
   ========================================================================= */
.cal { display: grid; gap: 0.9rem; }

.cal-months {
  display: grid;
  grid-template-columns: repeat(6, minmax(0, 1fr));
  gap: 0.3rem;
  padding: 0.3rem;
  border-radius: 999px;
  background: var(--powder-200);
}
@media (width >= 48rem) {
  .cal-months { grid-template-columns: repeat(12, minmax(0, 1fr)); }
}
.cal-pill {
  min-block-size: 44px;
  padding: 0.4rem 0.2rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-2);
  font: 800 var(--t-xs)/1 var(--font-ui);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease;
}
.cal-pill:hover { background: rgb(255 255 255 / 60%); }
.cal-pill:focus-visible { outline: 3px solid var(--focus); outline-offset: -2px; }
.cal-pill[aria-selected='true'] {
  background: var(--navy-900);
  color: #fff;
}
/* A thin season bar under each month, so the strip reads as a year at a
   glance even before anything is selected. */
.cal-pill { position: relative; }
.cal-pill::after {
  content: '';
  position: absolute;
  inset: auto 25% 0.28rem 25%;
  block-size: 3px;
  border-radius: 2px;
  background: var(--season-dry);
}
.cal-pill[data-cal-season='green']::after { background: var(--season-green); }
.cal-pill[data-cal-season='rains']::after { background: var(--season-rains); }
.cal-pill[data-cal-season='short']::after { background: var(--season-short); }
.cal-pill[aria-selected='true']::after { inset-inline: 30%; block-size: 4px; }

.cal-key {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.1rem;
  justify-content: center;
  color: var(--text-2);
  font-size: var(--t-xs);
}
.cal-key-item { display: inline-flex; align-items: center; gap: 0.4rem; }
.cal-key-item i {
  inline-size: 0.7rem;
  block-size: 0.7rem;
  border-radius: 50%;
  background: var(--season-dry);
}
.cal-key-item[data-cal-season='green'] i { background: var(--season-green); }
.cal-key-item[data-cal-season='rains'] i { background: var(--season-rains); }
.cal-key-item[data-cal-season='short'] i { background: var(--season-short); }

.cal-panel {
  display: grid;
  gap: clamp(1rem, 3vw, 2rem);
  padding: clamp(1rem, 3vw, 1.9rem);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-1);
}
.cal-panel[hidden] { display: none; }
@media (width >= 56rem) {
  .cal-panel { grid-template-columns: minmax(0, 1.25fr) minmax(0, 1fr); }
}
.cal-season {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  margin: 0 0 0.35rem;
  color: var(--text-3);
  font-size: var(--t-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.cal-season i {
  inline-size: 0.6rem; block-size: 0.6rem; border-radius: 50%;
  background: var(--season-dry);
}
.cal-season[data-cal-season='green'] i { background: var(--season-green); }
.cal-season[data-cal-season='rains'] i { background: var(--season-rains); }
.cal-season[data-cal-season='short'] i { background: var(--season-short); }
.cal-month {
  margin: 0 0 0.2rem;
  color: var(--navy-900);
  font-size: var(--t-xl);
  line-height: 1.1;
}
.cal-standfirst {
  margin: 0 0 0.9rem;
  color: var(--text-3);
  font-size: var(--t-xs);
  font-weight: 700;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.cal-points { margin: 0; padding-inline-start: 1.1rem; display: grid; gap: 0.55rem; }
.cal-points li { color: var(--text-2); font-size: var(--t-sm); line-height: 1.7; }

.cal-tiles {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.75rem;
  align-content: start;
}
.cal-tile {
  display: grid;
  gap: 0.3rem;
  padding: 0.85rem 0.8rem;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--powder-100);
}
.cal-tile svg {
  inline-size: 1.5rem; block-size: 1.5rem;
  color: var(--gold);
}
.cal-tile-v { color: var(--navy-900); font-size: var(--t-sm); font-weight: 750; line-height: 1.35; }
.cal-tile-k {
  color: var(--text-3);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}

.cal-note {
  display: flex;
  gap: 0.6rem;
  max-width: 82ch;
  margin: 0.2rem auto 0;
  padding: 0.75rem 0.9rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--sun-300);
  border-radius: var(--r-s);
  background: var(--powder-100);
  color: var(--text-2);
  font-size: var(--t-xs);
  line-height: 1.65;
}
.cal-note > svg {
  flex: none; inline-size: 1.05rem; block-size: 1.05rem;
  margin-top: 0.12rem; color: var(--gold);
}

@media (prefers-reduced-motion: reduce) { .cal-pill { transition: none; } }


/* ===========================================================================
   THE ACCLIMATISATION PLANNER
   ========================================================================= */
.trek {
  display: grid;
  gap: clamp(1rem, 3vw, 2rem);
  align-items: start;
  padding: clamp(1rem, 3vw, 1.9rem);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-1);
}
@media (width >= 56rem) {
  .trek { grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr); }
}
.trek-form { display: grid; gap: 1rem; align-content: start; }
.trek-field { display: grid; gap: 0.35rem; }
.trek-field label,
.trek-legend {
  color: var(--text-2);
  font-size: var(--t-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.trek-field .input { min-block-size: 48px; }
.trek-hint { margin: 0; color: var(--text-3); font-size: var(--t-xs); line-height: 1.55; }

.trek-seg {
  display: inline-flex;
  gap: 0.25rem;
  padding: 0.25rem;
  border-radius: 999px;
  background: var(--powder-200);
  justify-self: start;
}
.trek-seg button {
  min-inline-size: 4.5rem;
  min-block-size: 40px;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: var(--text-2);
  font: 750 var(--t-sm)/1 var(--font-ui);
  cursor: pointer;
}
.trek-seg button[aria-pressed='true'] { background: var(--navy-900); color: #fff; }
.trek-seg button:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }

.trek-card {
  display: grid;
  gap: 0.75rem;
  padding: clamp(0.9rem, 2.5vw, 1.4rem);
  border: 1px solid var(--line);
  border-left: 4px solid var(--season-dry);
  border-radius: var(--r-s);
  background: var(--powder-100);
}
/* The border colour is a summary, never the only signal — the verdict is
   always stated in words directly beside it. */
.trek-card[data-tone='ok'] { border-left-color: var(--season-green); }
.trek-card[data-tone='warn'] { border-left-color: var(--season-short); }
.trek-card[data-tone='bad'] { border-left-color: var(--season-rains); }

.trek-verdict {
  margin: 0;
  color: var(--navy-900);
  font-size: var(--t-md);
  font-weight: 750;
  line-height: 1.35;
}
.trek-route-note { margin: 0; color: var(--text-2); font-size: var(--t-sm); line-height: 1.65; }
.trek-rows { display: grid; gap: 0; margin: 0.2rem 0 0; }
.trek-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  gap: 0.75rem;
  padding: 0.5rem 0;
  border-top: 1px solid var(--line);
}
.trek-row dt { color: var(--text-2); font-size: var(--t-xs); }
.trek-row dd {
  margin: 0;
  color: var(--navy-900);
  font-size: var(--t-sm);
  font-weight: 750;
  text-align: end;
  font-variant-numeric: tabular-nums;
}
.trek-flag,
.trek-note,
.trek-note-good {
  margin: 0;
  padding: 0.55rem 0.7rem;
  border-radius: var(--r-s);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.trek-flag { background: #fdf0e3; color: #6a3b12; }
.trek-note { background: var(--powder-200); color: var(--text-2); }
.trek-note-good { background: #e6f0e8; color: #27452e; }


/* .xp-text is capped at 62ch because that is a comfortable measure for
   prose. A table is not prose: on the destination pages the ground-
   conditions table was being squeezed to that width and its third column
   ran off the edge. When the column holds a table it takes the space. */
.xp-text:has(table) { max-width: none; }
.xp-text .matrix-scroll { overflow-x: auto; }
.xp-text .matrix { inline-size: 100%; }
.xp-text .matrix td,
.xp-text .matrix th { white-space: normal; overflow-wrap: anywhere; }


/* The ground-conditions table is two columns of key and value. Left to
   auto layout it asked for 736px inside a 660px column and became a
   horizontal scroller, which for three rows of plain text is a worse
   answer than wrapping. Fixed layout, with the key column pinned, so it
   fits the space it has. */
.xp-text .matrix {
  table-layout: fixed;
  min-inline-size: 0;
}
.xp-text .matrix th:first-child,
.xp-text .matrix td:first-child { inline-size: 9rem; }
.xp-text .matrix-scroll { overflow-x: visible; }


/* On a phone the key/value row squeezed "Dedicated acclimatisation day"
   into three lines beside its answer. Stack them instead. */
@media (width < 30rem) {
  .trek-row { grid-template-columns: 1fr; gap: 0.15rem; }
  .trek-row dd { text-align: start; }
}


/* ===========================================================================
   ACCESS & CARE

   The page Montero is actually selling, so it gets the most precise
   treatment on the site: numbered measurement rows that read like a spec,
   a working profile builder, and a record card that looks like the document
   it describes.

   "Advanced" here is not an excuse for motion or contrast tricks. Every
   control is a real control, the only animation is a 150ms colour change,
   and it all works from the keyboard. On this page of all pages a clever
   interface that a screen reader cannot drive would be self-refuting.
   ========================================================================= */

/* ---- the twelve measurements ------------------------------------------- */
.am-list {
  counter-reset: am;
  display: grid;
  gap: 0.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}
@media (width >= 50rem) { .am-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (width >= 80rem) { .am-list { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.am-item {
  counter-increment: am;
  position: relative;
  display: grid;
  gap: 0.2rem;
  padding: 0.9rem 0.95rem 0.9rem 2.9rem;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--surface-1);
}
.am-item::before {
  content: counter(am, decimal-leading-zero);
  position: absolute;
  inset-block-start: 0.95rem;
  inset-inline-start: 0.9rem;
  color: var(--gold);
  font-size: 0.68rem;
  font-weight: 800;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.06em;
}
.am-what { color: var(--text-1); font-size: var(--t-sm); font-weight: 750; line-height: 1.3; }
.am-unit {
  justify-self: start;
  padding: 0.08rem 0.45rem;
  border-radius: 999px;
  background: var(--powder-200);
  color: var(--navy-900);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
}
.am-why { color: var(--text-3); font-size: var(--t-xs); line-height: 1.55; }

/* ---- the profile builder ------------------------------------------------ */
.ap {
  display: grid;
  gap: clamp(1rem, 3vw, 2rem);
  align-items: start;
}
@media (width >= 64rem) { .ap { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); } }

.ap-form { display: grid; gap: 1rem; }
.ap-group {
  margin: 0;
  padding: 0.9rem 1rem 1rem;
  border: 1px solid var(--line);
  border-radius: var(--r-s);
  background: var(--surface-1);
}
.ap-group legend {
  padding-inline: 0.4rem;
  margin-inline-start: -0.4rem;
  color: var(--navy-900);
  font-size: var(--t-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.ap-opts { display: grid; gap: 0.3rem; margin-top: 0.5rem; }
.ap-opt {
  display: grid;
  grid-template-columns: 1.4rem minmax(0, 1fr);
  gap: 0.6rem;
  align-items: start;
  min-block-size: 44px;
  padding: 0.45rem 0.5rem;
  border-radius: var(--r-s);
  cursor: pointer;
  transition: background-color 150ms ease;
}
.ap-opt:hover { background: var(--powder-100); }
.ap-opt input {
  inline-size: 1.25rem;
  block-size: 1.25rem;
  margin: 0.1rem 0 0;
  accent-color: var(--navy-900);
  cursor: pointer;
}
.ap-opt input:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.ap-opt-text { color: var(--text-2); font-size: var(--t-sm); line-height: 1.5; }
.ap-opt:has(input:checked) { background: var(--powder-200); }
.ap-opt:has(input:checked) .ap-opt-text { color: var(--text-1); font-weight: 650; }

.ap-privacy,
.ap-note {
  display: flex;
  gap: 0.55rem;
  margin: 0;
  padding: 0.7rem 0.85rem;
  border: 1px solid var(--line);
  border-left: 3px solid var(--sun-300);
  border-radius: var(--r-s);
  background: var(--powder-100);
  color: var(--text-2);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.ap-note { max-width: 78ch; margin-inline: auto; margin-block-start: 1.5rem; }
.ap-privacy > svg,
.ap-note > svg {
  flex: none; inline-size: 1rem; block-size: 1rem;
  margin-block-start: 0.15rem; color: var(--gold);
}

.ap-out {
  padding: clamp(1rem, 3vw, 1.5rem);
  border: 1px solid var(--powder-400);
  border-radius: var(--r-m);
  background: var(--navy-900);
  color: var(--on-dark-1);
}
@media (width >= 64rem) {
  .ap-out { position: sticky; inset-block-start: calc(var(--header-h, 4.5rem) + 1.5rem); }
}
.ap-out-h {
  margin: 0 0 0.6rem;
  color: #fff;
  font-size: var(--t-lg);
  line-height: 1.2;
}
.ap-empty { margin: 0; color: var(--powder-200); font-size: var(--t-sm); line-height: 1.7; }
.ap-count {
  margin: 0 0 0.7rem;
  color: var(--sun-300);
  font-size: var(--t-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.ap-lines { display: grid; gap: 0.55rem; margin: 0 0 1.1rem; padding: 0; list-style: none; }
.ap-line {
  display: grid;
  gap: 0.15rem;
  padding-block-end: 0.55rem;
  border-block-end: 1px solid rgb(255 255 255 / 14%);
}
.ap-line:last-child { border-block-end: 0; padding-block-end: 0; }
.ap-line b { color: #fff; font-size: var(--t-sm); }
.ap-line span { color: var(--powder-200); font-size: var(--t-xs); line-height: 1.55; }
.ap-actions { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ap-copied { margin: 0.6rem 0 0; color: var(--sun-300); font-size: var(--t-xs); font-weight: 700; }
.ap-copied[hidden] { display: none; }

/* ---- the worked record -------------------------------------------------- */
.ar-card {
  max-width: 46rem;
  margin: 0 auto;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  overflow: hidden;
  background: var(--surface-1);
  box-shadow: var(--shadow-2);
}
.ar-head {
  display: grid;
  gap: 0.2rem;
  padding: 1rem 1.15rem;
  background: var(--navy-900);
  color: #fff;
}
.ar-tag {
  justify-self: start;
  padding: 0.12rem 0.5rem;
  border-radius: 999px;
  background: var(--sun-300);
  color: var(--navy-900);
  font-size: 0.64rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.ar-name { color: #fff; font-size: var(--t-md); font-weight: 750; }
.ar-sub { color: var(--powder-200); font-size: var(--t-xs); }
.ar-table { inline-size: 100%; border-collapse: collapse; }
.ar-table th,
.ar-table td {
  padding: 0.6rem 1.15rem;
  text-align: start;
  font-size: var(--t-sm);
  vertical-align: top;
  border-block-start: 1px solid var(--line);
}
.ar-table tr:first-child th,
.ar-table tr:first-child td { border-block-start: 0; }
.ar-table th { color: var(--text-2); font-weight: 650; inline-size: 48%; }
.ar-table td {
  color: var(--navy-900);
  font-weight: 750;
  font-variant-numeric: tabular-nums;
}
.ar-foot {
  margin: 0;
  padding: 0.85rem 1.15rem;
  border-block-start: 1px solid var(--line);
  background: var(--powder-100);
  color: var(--text-3);
  font-size: var(--t-xs);
  line-height: 1.6;
}

@media (prefers-reduced-motion: reduce) { .ap-opt { transition: none; } }


/* ===========================================================================
   THE CATALOGUE CONTROLS

   What is filtering, a way out of each of it, a sort, and a comparison.
   All of it reads the catalogue's own data; none of it invents a fact about
   a journey.
   ========================================================================= */
.jbar {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1.25rem;
  align-items: center;
  justify-content: space-between;
  margin-block: 1.25rem 0.75rem;
  padding-block: 0.75rem;
  border-block: 1px solid var(--line);
}
.jbar-active {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 0.6rem;
  align-items: center;
  min-inline-size: 0;
}
.jbar-active[hidden] { display: none; }
.jbar-label {
  color: var(--text-3);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.jbar-chips { display: flex; flex-wrap: wrap; gap: 0.35rem; margin: 0; padding: 0; list-style: none; }
.jchip {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  min-block-size: 34px;
  padding: 0.2rem 0.5rem 0.2rem 0.7rem;
  border: 1px solid var(--navy-900);
  border-radius: 999px;
  background: var(--navy-900);
  color: #fff;
  font: 700 var(--t-xs)/1 var(--font-ui);
  cursor: pointer;
  transition: background-color 150ms ease;
}
.jchip svg { inline-size: 0.85rem; block-size: 0.85rem; }
.jchip:hover { background: var(--navy-700); }
.jchip:focus-visible { outline: 3px solid var(--focus); outline-offset: 2px; }
.jbar-clear {
  border: 0;
  background: none;
  padding: 0.3rem 0.2rem;
  min-block-size: 34px;
  color: var(--text-2);
  font: 700 var(--t-xs)/1 var(--font-ui);
  text-decoration: underline;
  text-underline-offset: 0.2em;
  cursor: pointer;
}
.jbar-clear:hover { color: var(--navy-900); }
.jbar-sort { display: flex; align-items: center; gap: 0.5rem; margin-inline-start: auto; }
.jbar-sort label {
  color: var(--text-3);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.jbar-sort .input { min-block-size: 40px; inline-size: auto; padding-block: 0.3rem; }

/* ---- the compare control on a card -------------------------------------- */
.cmp-pick {
  position: absolute;
  /* Top-RIGHT, beside the save control, NOT top-left.

     portal.css already carries a comment about this: the save button was
     moved out of the top-left corner because it sat on .tour-over and hid
     the first word of every card title. The Compare pill was then dropped
     into that same corner and covered the category chip outright — the
     card read with no style on it at all. The two card-level actions
     belong together in the one corner that is free of content. */
  inset-block-start: 0.6rem;
  inset-inline-end: calc(1rem + 38px);
  inset-inline-start: auto;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem 0.3rem 0.45rem;
  border: 1px solid rgb(255 255 255 / 34%);
  border-radius: 999px;
  background: rgb(16 27 45 / 62%);
  color: #fff;
  font: 750 0.68rem/1 var(--font-ui);
  cursor: pointer;
  backdrop-filter: blur(4px);
}
.cmp-pick[hidden] { display: none; }
.cmp-pick input { inline-size: 0.95rem; block-size: 0.95rem; margin: 0; accent-color: var(--sun-300); cursor: pointer; }
.cmp-pick:has(input:checked) { background: var(--sun-300); border-color: var(--sun-300); color: var(--navy-900); }
.cmp-pick[data-full='true'] { opacity: 0.45; cursor: not-allowed; }
.cmp-pick input:focus-visible { outline: 3px solid var(--sun-300); outline-offset: 2px; }

/* ---- the tray ----------------------------------------------------------- */
.cmp-tray {
  position: sticky;
  inset-block-end: 1rem;
  z-index: 30;
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 1rem;
  align-items: center;
  justify-content: space-between;
  margin-block-start: 1.25rem;
  padding: 0.7rem 0.9rem;
  border-radius: var(--r-m);
  background: var(--navy-900);
  color: #fff;
  box-shadow: 0 10px 30px rgb(16 27 45 / 30%);
}
.cmp-tray[hidden] { display: none; }
.cmp-count { margin: 0; font-size: var(--t-sm); font-weight: 700; }
.cmp-actions { display: flex; gap: 0.5rem; }
.cmp-tray .btn-ghost { color: #fff; border-color: rgb(255 255 255 / 45%); }
.cmp-tray .btn-ghost:hover,
.cmp-tray .btn-ghost:focus-visible {
  background: var(--sun-300); border-color: var(--sun-300); color: var(--navy-900);
}
.cmp-tray .btn[disabled] { opacity: 0.5; pointer-events: none; }

/* ---- the comparison itself ---------------------------------------------- */
.cmp-box {
  /* The UA centres a modal dialog with `margin: auto`, and setting any
     margin shorthand elsewhere in the cascade loses it. Stated here so the
     dialog cannot end up pinned to the top-left corner. */
  margin: auto;
  inline-size: min(68rem, calc(100vw - 2rem));
  max-block-size: min(90vh, 52rem);
  padding: 0;
  border: 0;
  border-radius: var(--r-m);
  background: var(--surface-1);
  color: var(--text-1);
  overflow: hidden;
}
.cmp-box::backdrop { background: rgb(8 14 24 / 78%); backdrop-filter: blur(4px); }
.cmp-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.9rem 1.1rem;
  background: var(--navy-900);
  color: #fff;
}
.cmp-head h2 { margin: 0; font-size: var(--t-md); }
.cmp-close {
  inline-size: 44px; block-size: 44px;
  display: grid; place-items: center;
  border: 1px solid rgb(255 255 255 / 32%);
  border-radius: 50%;
  background: transparent;
  color: #fff;
  cursor: pointer;
}
.cmp-close:hover, .cmp-close:focus-visible {
  background: var(--sun-300); border-color: var(--sun-300); color: var(--navy-900);
}
.cmp-close svg { inline-size: 1.1rem; block-size: 1.1rem; }
.cmp-scroll { overflow: auto; max-block-size: calc(90vh - 11rem); }
.cmp-table { inline-size: 100%; border-collapse: collapse; }
.cmp-table th,
.cmp-table td {
  padding: 0.7rem 0.9rem;
  text-align: start;
  vertical-align: top;
  font-size: var(--t-sm);
  border-block-start: 1px solid var(--line);
}
.cmp-table thead th {
  position: sticky;
  inset-block-start: 0;
  background: var(--powder-200);
  border-block-start: 0;
  font-weight: 800;
}
.cmp-table thead a { color: var(--navy-900); }
.cmp-table tbody th {
  inline-size: 11rem;
  color: var(--text-3);
  font-size: var(--t-xs);
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
}
.cmp-table tbody td { color: var(--text-2); }
.cmp-fact {
  display: block;
  padding-inline-start: 0.9rem;
  position: relative;
  line-height: 1.5;
}
.cmp-fact + .cmp-fact { margin-top: 0.3rem; }
.cmp-fact::before {
  content: '';
  position: absolute;
  inset-block-start: 0.52em;
  inset-inline-start: 0;
  inline-size: 0.35rem; block-size: 0.35rem;
  border-radius: 50%;
  background: var(--sun-300);
}
.cmp-foot {
  margin: 0;
  padding: 0.8rem 1.1rem;
  border-block-start: 1px solid var(--line);
  background: var(--powder-100);
  color: var(--text-3);
  font-size: var(--t-xs);
  line-height: 1.6;
}

@media (width < 44rem) {
  .jbar { flex-direction: column; align-items: stretch; }
  .jbar-sort { margin-inline-start: 0; }
  .jbar-sort .input { inline-size: 100%; }
  .cmp-table tbody th { inline-size: 7rem; }
}
@media (prefers-reduced-motion: reduce) { .jchip { transition: none; } }


/* ---------------------------------------------------------------------------
   The filter panel

   Six rows of "LABEL  pill pill pill" with the label floating beside a
   wrapping row. The labels sat at different heights depending on how many
   pills wrapped, so the left edge of the groups never lined up and the
   block read as a pile rather than a control.

   A grid instead: labels in their own column, aligned, each group separated
   by a hairline. On a narrow screen the label sits above its row, which is
   the only arrangement that works at 375px.
   ------------------------------------------------------------------------- */
.filter-grid {
  display: grid;
  gap: 0;
  padding: clamp(0.75rem, 2vw, 1.1rem) clamp(0.85rem, 2.5vw, 1.4rem);
  border: 1px solid var(--line);
  border-radius: var(--r-m);
  background: var(--surface-1);
}
.filter-row {
  display: grid;
  gap: 0.5rem 1.1rem;
  align-items: start;
  padding-block: 0.7rem;
}
.filter-row + .filter-row { border-block-start: 1px solid var(--line); }
@media (width >= 48rem) {
  .filter-row { grid-template-columns: 8.5rem minmax(0, 1fr); align-items: center; }
}
.filter-legend {
  margin: 0;
  padding-block-start: 0.2rem;
  color: var(--text-3);
  font-size: 0.68rem;
  font-weight: 800;
  letter-spacing: var(--track-wider);
  text-transform: uppercase;
  line-height: 1.3;
}
.filter-row .tabs { display: flex; flex-wrap: wrap; gap: 0.4rem; }
.filter-row .tab {
  min-block-size: 40px;
  padding-inline: 0.85rem;
  font-size: var(--t-xs);
  font-weight: 700;
  background: var(--surface-1);
  border-color: var(--line-strong);
  color: var(--text-2);
}
.filter-row .tab:hover { border-color: var(--navy-900); color: var(--navy-900); }
.filter-row .tab[aria-pressed='true'] {
  background: var(--navy-900);
  border-color: var(--navy-900);
  color: #fff;
}
.filter-row .tab svg { opacity: 0.75; }
.filter-row .tab[aria-pressed='true'] svg { opacity: 1; }

/* The filter panel now has a frame, so the bar beneath it does not need
   its own top rule. */
.jbar { border-block-start: 0; margin-block-start: 0.9rem; }


/* ---------------------------------------------------------------------------
   The consent bar

   Appears only when a backend is configured and the visitor has not already
   answered. It is a real dialog with focus moved into it, it does not cover
   the page content, and "No thanks" is as prominent as "Yes" — a refusal
   that is harder to click than an acceptance is not a free choice.
   ------------------------------------------------------------------------- */
.consent {
  position: fixed;
  inset-inline: 0;
  inset-block-end: 0;
  z-index: 500;
  padding: clamp(0.75rem, 2vw, 1rem);
  background: var(--navy-900);
  color: var(--on-dark-1);
  border-block-start: 3px solid var(--sun-300);
  box-shadow: 0 -10px 34px rgb(16 27 45 / 34%);
}
.consent-in {
  display: flex;
  flex-wrap: wrap;
  gap: 0.85rem 1.5rem;
  align-items: center;
  justify-content: space-between;
  width: min(100% - 1rem, var(--maxw, 75rem));
  margin-inline: auto;
}
.consent-text { max-width: 68ch; }
.consent-text h2 {
  margin: 0 0 0.2rem;
  color: #fff;
  font-size: var(--t-base);
  line-height: 1.3;
}
.consent-text p {
  margin: 0;
  color: var(--powder-200);
  font-size: var(--t-xs);
  line-height: 1.6;
}
.consent-text a { color: var(--sun-300); }
.consent-btns { display: flex; gap: 0.5rem; flex: none; }
/* "No thanks" on the consent bar. The hover rule below paints it gold with
   a navy label, but `.btn-ghost` sets `--btn-fill: var(--accent)` -- navy --
   and that sheet wipes across on hover and focus, landing navy on navy at
   1:1. Same fault as the primary button had, in the one control where a
   visitor is being asked to refuse something: a refusal that is hard to see
   is not a fair choice. The wipe is set to the colour the hover state was
   already going to. */
.consent .btn-ghost {
  color: #fff;
  border-color: rgb(255 255 255 / 45%);
  --btn-fill: var(--sun-300);
}
.consent .btn-ghost:hover,
.consent .btn-ghost:focus-visible {
  background: var(--sun-300); border-color: var(--sun-300); color: var(--navy-900);
}
.consent :focus-visible { outline: 3px solid var(--sun-300); outline-offset: 2px; }

@media (width < 44rem) {
  .consent-btns { inline-size: 100%; }
  .consent-btns .btn { flex: 1; justify-content: center; }
}
