/* ============================================================
   Pratapgarh Farms & Resorts — Blog theme
   Brand design language mirrored from pratapgarhfarms.com
   ============================================================ */

/* ---------- Type ----------
   System fonts only — no webfont is downloaded.

   This started as Google's Roboto + Roboto Serif, then self-hosted latin
   subsets (107 KB: 65 serif, 42 sans). Dropping them costs nothing on Android,
   where system-ui *is* Roboto, and gives up a little fidelity on iOS and
   Windows in exchange for ~107 KB — which on a Slow-4G landing page is bandwidth
   the hero image does not have to share.

   The heading face is the real loss: there is no system equivalent of Roboto
   Serif, so Georgia takes it. That is the deliberate trade — if the brand serif
   matters more than the bandwidth, put the two @font-face rules back; the files
   are in git history at static/fonts/. */

:root {
  /* Brand tokens */
  --gold: #fdb100;        /* primary: header / nav background */
  --gold-dark: #e09a00;   /* hover */
  --pink: #ff0171;        /* accent: links, category chips, buttons */
  --pink-dark: #d6005e;   /* accent hover */
  --green: #336601;       /* secondary: farm / nature accents */
  --ink: #222222;         /* body text / headings */
  --ink-soft: #575760;
  --paper: #ffffff;
  --cream: #fdf6e3;       /* warm highlight / hero */
  --line: #ece7d8;        /* subtle borders */
  --shadow: 0 10px 30px rgba(34, 34, 34, 0.10);
  --shadow-sm: 0 4px 14px rgba(34, 34, 34, 0.08);

  --font-head: Georgia, "Times New Roman", serif;
  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --container: 1180px;
  --radius: 14px;
  --radius-sm: 8px;

  --header-h: 76px;
  --actnav-h: 54px;      /* sticky activities/food strip; keep in sync with .actnav__link */
}

/* ---------- Reset & base ---------- */
*, *::before, *::after { box-sizing: border-box; }
/* `clip` (not hidden) guards against horizontal page scroll from the
   full-bleed galleries without creating a scroll container. */
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; overflow-x: clip; }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.7;
  color: var(--ink);
  background: var(--paper);
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--pink); text-decoration: none; }
a:hover { color: var(--pink-dark); text-decoration: underline; }

h1, h2, h3, h4, h5 {
  font-family: var(--font-head);
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 0.6em;
  letter-spacing: -0.01em;
}
h1 { font-size: clamp(1.9rem, 4vw, 2.9rem); }
h2 { font-size: clamp(1.4rem, 3vw, 1.9rem); }
h3 { font-size: 1.25rem; }
p { margin: 0 0 1.1em; }

.container {
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 20px;
}

/* Skip link (accessibility) */
.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 200;
  background: var(--pink);
  color: #fff;
  padding: 10px 16px;
  border-radius: 0 0 8px 0;
}
.skip-link:focus { left: 0; color: #fff; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.95rem;
  padding: 11px 22px;
  border-radius: 999px;
  border: 0;
  cursor: pointer;
  text-align: center;
  transition: transform 0.15s ease, background-color 0.15s ease, color 0.15s ease;
  text-decoration: none;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn--primary { background: var(--pink); color: #fff; }
.btn--primary:hover { background: var(--pink-dark); color: #fff; }
/* The band's secondary buttons — school's brochure download and Call Now.
   Green rather than the old gold: on the gold band, gold-on-gold read as
   disabled, and these are now the only actions there (the Book Now button is
   hidden on /school/). White on --green is 6.9:1. Hover walks towards --ink,
   which is the same family as the accent rather than a second hue. */
.btn--green { background: var(--green); color: #fff; }
.btn--green:hover { background: #26490b; color: #fff; }
.btn--ghost { background: transparent; color: var(--ink); border: 2px solid var(--ink); }
.btn--ghost:hover { background: var(--ink); color: #fff; }

/* Floating action pair (lower-left corner, every page): Call Now above
   Book Now. The wrapper is the only fixed element — positioning each button
   separately would mean keeping two sets of offsets in sync by hand, and the
   gap between them is what guarantees they never overlap.
   Plain column, because the order wanted is also the order that should be
   announced: Call Now first, then Book Now, top to bottom. */
.floating-actions {
  position: fixed;
  bottom: 20px;
  left: 20px;
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 10px;
  /* A fixed wrapper spans the viewport; sized to its content it covers only
     the buttons. Without this the empty strip to the right of the buttons is
     still inside the element and swallows clicks meant for the footer
     underneath it. */
  width: max-content;
  max-width: calc(100vw - 40px);
}
.floating-book,
.floating-call {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: #fff;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.02em;
  padding: 13px 22px;
  border-radius: 999px;
  text-decoration: none;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
/* Pink is the primary action and keeps the colour it always had. The call
   button takes the site's own --green (#336601, the farm/nature accent already
   used for section subtitles and links), so the two are told apart at a glance
   rather than reading as a doubled Book Now. White on that green measures
   6.9:1 — comfortably past AA for text this size. */
.floating-book {
  background: var(--pink);
  box-shadow: 0 8px 24px rgba(255, 1, 113, 0.35);
}
/* The shadow cannot inherit the background's colour, so it carries #336601's
   channels as a literal; keep the two in step if --green ever changes. */
.floating-call {
  background: var(--green);
  box-shadow: 0 8px 24px rgba(51, 102, 1, 0.30);
}
.floating-book:hover { transform: translateY(-2px); box-shadow: 0 12px 28px rgba(255, 1, 113, 0.45); color: #fff; text-decoration: none; }
.floating-call:hover { transform: translateY(-2px); box-shadow: 0 12px 28px rgba(51, 102, 1, 0.40); color: #fff; text-decoration: none; }
.floating-book svg,
.floating-call svg { width: 18px; height: 18px; }

/* ---------- Header ---------- */
.site-header {
  background: var(--gold);
  position: sticky;
  top: 0;
  z-index: 100;
  box-shadow: var(--shadow-sm);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  height: var(--header-h);
}
.brand { display: flex; align-items: center; flex-shrink: 0; }
.brand__logo { height: 44px; width: auto; }
.brand__logo:hover { opacity: 0.9; }

.nav { display: flex; align-items: center; gap: 4px; }
.nav__link {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--ink);
  padding: 8px 12px;
  border-radius: 8px;
  white-space: nowrap;
}
.nav__link:hover { background: rgba(255, 255, 255, 0.45); text-decoration: none; color: var(--ink); }
.nav__link.is-active { background: var(--ink); color: #fff; }
.nav__link.is-active:hover { background: var(--ink); color: #fff; }

/* Mobile menu toggle */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  border: 2px solid var(--ink);
  border-radius: 8px;
  background: transparent;
  cursor: pointer;
  align-items: center;
  justify-content: center;
}
.nav-toggle svg { width: 22px; height: 22px; }

/* ---------- Hero ----------
   Background photo from the original WordPress hero. The source still has
   its folk-art border baked in; once the borderless photo lands, the frame
   becomes an SVG overlay stretched over the hero (see the .hero__frame hook
   below) and `cover` then works at every aspect ratio.

   Both the photo and the frame are two files, not one, because the hero box is
   1:1 on phones and 2:1 from 768px up: a single master meant cropping a 2560px
   photo into a 412px square and scaling a 2400px frame into 820px. The
   derivatives are built by .tools/build-hero-images.py; the masters live in
   assets/images/home/ and are never published. */
.hero {
  position: relative;
  /* The frame dictates the hero's shape; the photo `cover`s behind it and is
     cropped. 1:1 on phones, 2:1 from tablet width up. */
  aspect-ratio: 1 / 1;
  display: flex;
  align-items: center;
  justify-content: center;
  background-color: var(--gold);
  background-image: url("../images/home/hero-bg-phone.webp");
  background-position: center center;
  background-repeat: no-repeat;
  background-size: cover;
  border-bottom: 1px solid var(--line);
  text-align: center;
  padding: 32px 0;
  overflow: hidden;
}
/* Dark scrim, as in the original (#202020), to keep text legible on the photo */
.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(32, 32, 32, 0.55);
}
/* Folk-art frame overlay — a transparent-centred image stretched over the
   hero, so it holds its proportions at any aspect ratio. The photo shows
   through the middle. Swapped for the 2:1 artwork from tablet width up. */
.hero__frame {
  position: absolute;
  inset: 0;
  z-index: 3;
  pointer-events: none;
  background-image: url("../images/home/hero-frame-phone.webp");
  background-repeat: no-repeat;
  background-position: center;
  background-size: 100% 100%;
}
/* 2:1 frame from tablet width up; phones keep the 1:1 artwork. */
@media (min-width: 768px) {
  .hero {
    aspect-ratio: 2 / 1;
    background-image: url("../images/home/hero-bg-desk.webp");
  }
  .hero__frame { background-image: url("../images/home/hero-frame-desk.webp"); }
}
.hero > .container {
  position: relative;
  z-index: 2;
  width: 100%;
}
.hero__kicker {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.8rem;
  /* Pinned because this element used to be an h1 and is now a <p>: the base
     heading rule hands out line-height 1.2, and a paragraph would otherwise
     inherit the body's 1.7 and stand about 6px taller, shifting the centred
     hero. Everything else here already overrode the heading rule. */
  line-height: 1.2;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #fff;
  background: none;
  padding: 0;
  margin: 0 0 14px;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.55);
}
.hero__title {
  font-size: clamp(2rem, 5vw, 3.4rem);
  margin-bottom: 10px;
  color: #fff;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45);
}
.hero__sub {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(1rem, 2.2vw, 1.25rem);
  color: #fff;
  margin-bottom: 0;
  text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}
.hero__rule {
  width: 64px;
  height: 4px;
  border-radius: 2px;
  background: var(--gold);
  margin: 20px auto 0;
}

/* ---------- Slide hero ----------
   Family, School and Corporate open with a photo slideshow upstream: several
   full-bleed photos, each with its own caption and Book Now button, crossfading
   on a timer. Rebuilt on the .hero chassis so it inherits the aspect ratio and
   the frame overlay rather than duplicating them.

   The frame and the scrim stay where they were on the homepage — the frame
   above everything, the scrim between the photo and the caption — but the scrim
   moves from .hero::before onto each slide, because the stage below is its own
   stacking context and a caption inside it could never rise above a scrim drawn
   outside it. Sliding both with the photo also means the scrim matches whichever
   photo is showing.

   The first slide is served visible and is never faded in. It is this page's LCP
   element: starting it at opacity:0 delays the paint and, worse, LCP ignores
   fully transparent elements, so the metric would stop describing the hero. */
.hero--slides { background-image: none; }
.hero--slides::before { display: none; }

.hero__stage { position: absolute; inset: 0; z-index: 1; }

.hero__slide {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 32px 0;
  opacity: 0;
}
/* The incoming slide rides above the outgoing one, so wrapping from the last
   slide back to the first is still a crossfade rather than a reveal from
   underneath. */
.hero__slide.is-active { opacity: 1; z-index: 2; }
/* Transition lives under .has-js so a no-JavaScript page ships no transition
   on its LCP element at all. */
.has-js .hero__slide { transition: opacity 0.9s cubic-bezier(0.16, 1, 0.3, 1); }

.hero__slide-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}
.hero__slide::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background: rgba(32, 32, 32, 0.55);
}
.hero__slide-body { position: relative; z-index: 2; width: 100%; text-align: center; }
.hero__slide-title {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: clamp(1.5rem, 3.6vw, 2.6rem);
  line-height: 1.2;
  color: #fff;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.45);
  margin-bottom: 20px;
}

/* Dots sit centre-bottom, below the frame's ornamental border — that border is
   drawn about 2% in from the edge, and only the corner medallions reach further
   in, so the centre of the bottom edge is clear. Hidden without JavaScript:
   they are the only manual control, and inert dots are worse than none. */
.hero__dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: clamp(22px, 5%, 56px);
  z-index: 4;
  display: none;
  gap: 10px;
  justify-content: center;
}
.has-js .hero__dots { display: flex; }
.hero__dot {
  width: 10px;
  height: 10px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.45);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.5);
  cursor: pointer;
}
.hero__dot.is-active { background: var(--gold); }
.hero__dot:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }

/* ---------- Layout ---------- */
.main { padding: 40px 0 64px; }
/* Centred, matching .section__title. Every other heading on the site is already
   centred, so a left-aligned page head was the odd one out — it showed most on
   the landing pages, where the title sits under a centred hero immediately
   followed by centred section headings. Set on the wrapper so the title and the
   meta line under it stay centred together. */
.page-head { margin-bottom: 28px; text-align: center; }
.page-head__title { margin-bottom: 4px; }
.page-head__meta { color: var(--ink-soft); font-size: 0.95rem; }
.page-head__meta a { color: var(--pink); }

/* ---------- Post grid ---------- */
.post-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 26px;
}

/* ---------- Card ---------- */
.card {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: var(--shadow-sm);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
}
.card:hover { transform: translateY(-4px); box-shadow: var(--shadow); }
.card__media {
  position: relative;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  background: var(--cream);
}
.card__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.35s ease; }
.card:hover .card__media img { transform: scale(1.05); }
.card__media--placeholder {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  color: var(--gold-dark);
}
.card__chip {
  position: absolute;
  top: 12px;
  left: 12px;
  background: var(--pink);
  color: #fff;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.72rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  padding: 4px 11px;
  border-radius: 999px;
}
.card__chip:hover { background: var(--pink-dark); color: #fff; text-decoration: none; }
.card__body { padding: 20px 22px 22px; display: flex; flex-direction: column; flex: 1; }
.card__title {
  font-size: 1.22rem;
  line-height: 1.3;
  margin-bottom: 8px;
}
.card__title a { color: var(--ink); }
.card__title a:hover { color: var(--pink); text-decoration: none; }
.card__excerpt {
  color: var(--ink-soft);
  font-size: 0.95rem;
  line-height: 1.6;
  margin-bottom: 14px;
  flex: 1;
}
.card__meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.8rem;
  color: var(--ink-soft);
  border-top: 1px solid var(--line);
  padding-top: 12px;
}
.card__meta .dot { color: var(--gold-dark); }

/* ---------- Single post ---------- */
.post { max-width: 780px; margin: 0 auto; }
/* A landing page is not an article to read, it is a sequence of full-width
   rows, so the reading measure is lifted. The prose inside still gets it back
   from .post__content--flow, which constrains each text element instead of the
   whole document. Without this the galleries and the gold band were boxed to
   780px and sat off-centre inside a 1440px window. */
.post--wide { max-width: none; }
/* Prose pages keep the blog's reading measure — but on the header and the prose
   themselves rather than on the whole <article>, so the full-bleed banner
   between them is not boxed into the text column. Scoped to these modifiers so
   the blog list and taxonomy headers, which also use .page-head, keep the full
   container width. */
.page-head--read,
.post__content--read { max-width: 780px; margin-inline: auto; }
/* Full-bleed banner under a page heading. The source image is 3:2; cropping it
   to a band stops a decorative photo from pushing the actual content a full
   screen down. */
.page-banner {
  margin: 0 0 32px;
  overflow: hidden;
}
.page-banner img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 1;
  object-fit: cover;
  object-position: center;
}
.post__header { margin-bottom: 28px; }
.breadcrumb {
  font-size: 0.85rem;
  color: var(--ink-soft);
  margin-bottom: 18px;
}
.breadcrumb a { color: var(--pink); }
.post__title { margin-bottom: 14px; }
.post__byline {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 16px;
  align-items: center;
  font-size: 0.88rem;
  color: var(--ink-soft);
  margin-bottom: 20px;
}
.post__byline strong { color: var(--ink); font-weight: 600; }
.post__featured {
  border-radius: var(--radius);
  overflow: hidden;
  margin-bottom: 28px;
  box-shadow: var(--shadow-sm);
}
.post__featured img { width: 100%; }

/* On This Page — the post's table of contents, placed by the single template
   between the featured image and the body. Deliberately quieter than the Summary
   panel it sits under: no fill, a hairline border and a gold rule along the top,
   so the two panels at the top of a post do not compete. Two columns once there
   is width for them, because ten sections in one narrow column is a wall. */
.toc {
  margin: 0 0 2em;
  padding: 20px 24px 22px;
  background: var(--paper);
  border: 1px solid var(--line);
  border-top: 3px solid var(--gold);
  border-radius: var(--radius-sm);
}
.toc__title {
  margin: 0 0 12px;
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
}
.toc nav ul { margin: 0; padding: 0; list-style: none; }
.toc nav li { margin: 0 0 8px; }
.toc nav li:last-child { margin-bottom: 0; }
.toc nav a {
  color: var(--ink-soft);
  font-size: 0.95rem;
  text-decoration: none;
}
.toc nav a:hover { color: var(--pink); text-decoration: underline; text-underline-offset: 3px; }
@media (min-width: 720px) {
  .toc nav > ul { columns: 2; column-gap: 32px; }
  .toc nav li { break-inside: avoid; }
}

/* A contents link must land the reader where the heading is visible rather than
   underneath the sticky header. Same offset the activity-list rows use. */
.post__content :is(h2, h3) { scroll-margin-top: calc(var(--header-h) + 16px); }

.post__content { font-size: 1.05rem; line-height: 1.85; }
.post__content h2 { margin-top: 1.6em; }
.post__content h3 { margin-top: 1.4em; }
.post__content a { text-decoration: underline; text-underline-offset: 3px; }
.post__content img { border-radius: var(--radius-sm); margin: 1.2em 0; }
.post__content blockquote {
  margin: 1.4em 0;
  padding: 4px 0 4px 20px;
  border-left: 4px solid var(--gold);
  font-style: italic;
  color: var(--ink-soft);
}
.post__content code {
  background: var(--cream);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 0.9em;
}
.post__content pre {
  background: var(--ink);
  color: #f5f2e8;
  padding: 18px;
  border-radius: var(--radius-sm);
  overflow-x: auto;
}
.post__content pre code { background: transparent; color: inherit; padding: 0; }
.post__content ul, .post__content ol { padding-left: 1.4em; }

/* Tables in page and post bodies — the at-a-glance tables on /family/ and
   /school/. Keep them readable at 360px without a horizontal scroll. */
.post__content table {
  width: 100%;
  border-collapse: collapse;
  margin: 1.75rem 0;
  font-size: 0.975rem;
}
.post__content th,
.post__content td {
  padding: 0.7rem 0.85rem;
  border-bottom: 1px solid var(--line);
  text-align: left;
  vertical-align: top;
}
.post__content thead th {
  background: var(--cream);
  font-weight: 700;
}
.post__content tbody td:first-child {
  font-weight: 600;
}
/* A flow body does not wrap its blocks in .container, so the rule that gives
   the prose its measure never reached the table and it ran the full window
   width. Sit it at half width and centre it; below 900px give it the same
   20px gutter as the paragraphs, where it needs the room. */
.post__content--flow > table {
  width: 50%;
  max-width: var(--container);
  margin-inline: auto;
}
@media (max-width: 900px) {
  .post__content--flow > table {
    width: calc(100% - 40px);
  }
}
@media (max-width: 600px) {
  .post__content table { font-size: 0.925rem; }
  .post__content th,
  .post__content td { padding: 0.55rem 0.5rem; }
}

/* Summary box at the top of a post — the shortcode's markup, styled here.
   A tinted panel with a gold rule down the left, so the reader can see at a
   glance that this is a different kind of block from the prose and skip or read
   it deliberately. Cream rather than white so it reads as a panel without
   needing a heavy border, and the label is set in the body face, uppercase and
   letterspaced, to sit apart from the Georgia headings around it.
   Inner spacing is set on the children, not the box, so the first and last
   bullets do not double up against the padding. */
.summary {
  margin: 0 0 2em;
  padding: 26px 28px;
  background: var(--cream);
  border-left: 5px solid var(--gold);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
}
/* Two classes deep on purpose: .post__content h2 sets a 1.6em top margin that
   would otherwise push the label down inside its own box. */
.summary .summary__title {
  margin: 0 0 14px;
  font-family: var(--font-body);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
}
.summary__body > ul,
.summary__body > ol { margin: 0; padding-left: 1.15em; }
.summary__body li { margin: 0 0 10px; }
.summary__body li:last-child { margin-bottom: 0; }
.summary__body li::marker { color: var(--gold-dark); }
.summary__body > p { margin: 0; }
.summary__body > p + p { margin-top: 0.8em; }

/* Flow body, for the landing pages.
   Their bodies are a sequence of full-bleed blocks — galleries, the gold ticket
   band, the rules — with prose between them. So the body is NOT wrapped in
   .container: each text element carries the container's own measure instead, and
   the block shortcodes span the full width exactly as the homepage rows do. A
   gallery boxed inside a container cannot bleed, and the negative-margin trick
   that would let it escape is the kind of thing that eventually overflows on a
   narrow screen by the width of a scrollbar.
   Only text-level elements are constrained, so nothing here touches the
   shortcode blocks. */
.post__content--flow > p,
.post__content--flow > h2,
.post__content--flow > h3,
.post__content--flow > h4,
.post__content--flow > ul,
.post__content--flow > ol,
.post__content--flow > blockquote {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: 20px;
}
.post__content--flow > p:first-child { margin-top: 0; }
/* Section headings in a flow body are centred, matching .section__title on the
   homepage, because several of them introduce exactly the same rows: the 145+
   activities heading and the desi feast heading appear on both pages and should
   not sit differently on one of them. Body paragraphs stay left-aligned.
   h3 is here because the flow bodies use it for section headings too — a bare
   "### Everything You Can Do Here" on /family/ reads as a peer of the h2s above
   it, so it must sit the way they do. Card headings (.feature__title,
   .tile__title) are deliberately not listed: they are one line inside a picture
   card, not a row heading, and centring them is not the same change. */
.post__content--flow > h2,
.post__content--flow > h3 { text-align: center; }
/* The activity list's group titles. These are h3s too, but nested inside the
   list wrapper, which is a shortcode block rather than a direct child of the
   flow body — so the rule above cannot reach them. They introduce the same kind
   of row as the flow h2s, hence the same alignment. */
.actset__title { text-align: center; }
/* The deck line under a section heading reads as a subtitle, not as body copy. */
.post__content--flow > .deck {
  text-align: center;
  color: var(--green);
  font-family: var(--font-head);
  font-weight: 500;
  font-size: 1.05rem;
}

.post__tags {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 28px;
  padding-top: 20px;
  border-top: 1px solid var(--line);
}
.tag {
  display: inline-block;
  font-size: 0.8rem;
  font-weight: 600;
  font-family: var(--font-body);
  color: var(--green);
  background: rgba(51, 102, 1, 0.08);
  border-radius: 999px;
  padding: 4px 12px;
}
.tag:hover { background: var(--green); color: #fff; text-decoration: none; }

/* ---------- Related posts ---------- */
.related { margin-top: 40px; padding-top: 28px; border-top: 2px solid var(--gold); }
.related__title { margin-bottom: 18px; }
.related__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; }
.related__card { border: 1px solid var(--line); border-radius: var(--radius-sm); overflow: hidden; }
.related__card a { display: block; }
.related__card img { aspect-ratio: 16/10; object-fit: cover; width: 100%; }
.related__card-body { padding: 12px 14px 14px; }
.related__card-title { font-family: var(--font-head); font-size: 0.95rem; line-height: 1.35; color: var(--ink); margin: 0; }
.related__card a:hover .related__card-title { color: var(--pink); }

/* ---------- Pagination ---------- */
.pagination {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin-top: 40px;
  flex-wrap: wrap;
}
.pagination__item {
  min-width: 42px;
  height: 42px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 8px;
  color: var(--ink);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.9rem;
}
.pagination__item:hover { border-color: var(--gold); background: var(--cream); text-decoration: none; color: var(--ink); }
.pagination__item.is-active { background: var(--gold); border-color: var(--gold); color: var(--ink); }
.pagination__item.is-disabled { opacity: 0.45; pointer-events: none; }

/* ---------- Footer ---------- */
.site-footer { background: var(--ink); color: #e9e5da; margin-top: 40px; }

.site-footer a { color: #ffd257; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.footer-grid {
  display: grid;
  grid-template-columns: 2fr 1fr 1.4fr;
  gap: 32px;
  padding: 48px 0 36px;
}
/* h2, not h3: the footer columns are a top-level section of the document, and
   emitting them at h3 put a heading-level jump straight after the h1 on every
   page whose body has no h2 of its own. */
.footer-col h2 {
  color: #fff;
  font-size: 1rem;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  margin-bottom: 14px;
}
.footer-col p { font-size: 0.92rem; margin-bottom: 8px; color: #c9c4b6; }
.footer-links { list-style: none; margin: 0; padding: 0; }
.footer-links li { margin-bottom: 8px; }
.footer-links a { font-size: 0.92rem; }
.footer-social { display: flex; gap: 12px; margin-top: 14px; }
.footer-social a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.08);
  color: #fff;
  transition: background 0.15s ease;
}
.footer-social a:hover { background: var(--gold); color: var(--ink); text-decoration: none; }
.footer-social svg { width: 18px; height: 18px; }
/* The government listings, one line above the copyright. No border of its own —
   .footer-bottom's hairline closes the block, and a second rule 18px above it
   reads as a double line. */
.footer-recognised { padding: 0 0 18px; text-align: center; font-size: 0.85rem; color: #a8a294; }
.footer-recognised p { margin: 0; }
.footer-bottom {
  border-top: 1px solid rgba(255, 255, 255, 0.12);
  padding: 18px 0;
  text-align: center;
  font-size: 0.85rem;
  color: #a8a294;
}

/* ---------- 404 / empty ---------- */
.empty { text-align: center; padding: 60px 20px; }
.empty__emoji { font-size: 3rem; margin-bottom: 10px; }
.empty__title { margin-bottom: 8px; }

/* ---------- Responsive ---------- */
@media (max-width: 1024px) {
  .post-grid { grid-template-columns: repeat(2, 1fr); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
}

/* The eight nav links plus the logo need ~1031px; below that the burger takes
   over. Kept above the 1024px grid rule so the two never fight. */
@media (max-width: 1080px) {
  .nav-toggle { display: inline-flex; }
  .nav {
    display: none;
    position: absolute;
    top: var(--header-h);
    left: 0;
    right: 0;
    background: var(--gold);
    flex-direction: column;
    align-items: stretch;
    padding: 12px 20px 20px;
    gap: 2px;
    box-shadow: var(--shadow-sm);
  }
  .nav.is-open { display: flex; }
  .nav__link { padding: 12px 14px; border-radius: 8px; }
  /* The logo is 8:1, so at a fixed height it crowds the toggle out on narrow
     phones. Cap the width and let the height follow. */
  .brand__logo { height: auto; max-height: 40px; max-width: 68vw; }
}

@media (max-width: 640px) {
  .post-grid, .related__grid { grid-template-columns: 1fr; }
  .summary { padding: 20px 18px; }
  .review { padding: 16px 16px; }
  .footer-grid { grid-template-columns: 1fr; gap: 24px; }
  .hero { padding: 40px 0 36px; }
  .main { padding: 28px 0 48px; }
  .floating-actions { bottom: 16px; left: 16px; }
  .floating-book,
  .floating-call { padding: 11px 18px; font-size: 0.88rem; }
}

/* ---------- Homepage sections ---------- */
.section { padding: 56px 0; }
/* Deferred rendering for sections below the fold.
   `loading="lazy"` was not enough on its own: Chrome scales its lazy-loading
   distance to the connection, so on Slow 4G it eagerly fetched everything
   within about 3000px — the whole activity gallery, the feast images and the
   ticket cards — onto the same pipe as the hero. The hero is the LCP element,
   so it finished last at ~6.4 s having simply shared bandwidth.
   content-visibility:auto skips rendering, and therefore fetching, outside
   roughly a viewport of the visible area. contain-intrinsic-size keeps the
   scroll height honest while a section is skipped; `auto` makes it remember
   the real height once measured, so the fallback only matters on first paint.
   Each section passes its own measured height in --cv-size, because they range
   from 585px to 2850px and one shared guess left the page 1000px short. */
.section--defer {
  content-visibility: auto;
  contain-intrinsic-size: auto var(--cv-size, 900px);
}
/* The decorative bands and the ticket band sit between sections rather than
   inside one, so they were the last things still fetched from below the fold:
   the mandala alone is 47 KB of mostly-base64 SVG. Heights are the measured
   ones — see the note above on why a single guess is not good enough. */
.divider { content-visibility: auto; contain-intrinsic-size: auto 74px; }
.horizon { content-visibility: auto; contain-intrinsic-size: auto 60px; }
.pricing-band { content-visibility: auto; contain-intrinsic-size: auto 980px; }
.section + .section { border-top: 1px solid var(--line); }
.section--last { padding-bottom: 72px; }
.section__title { text-align: center; margin-bottom: 8px; }
.section__title--sm { font-size: 1.35rem; margin-top: 40px; }
.section__sub {
  text-align: center;
  color: var(--green);
  font-family: var(--font-head);
  font-weight: 500;
  font-size: 1.05rem;
  margin-bottom: 8px;
}

/* ---------- The intro card, in an Apple-keynote idiom ----------
   The homepage's opening statement, set the way Apple sets a product line: one
   very large, tightly-tracked, near-black statement with everything else
   stepped well down behind it. The hierarchy is carried by scale and tracking
   rather than by colour or ornament.
   Two deliberate details:
     - The sub-line leaves the serif for the system stack and goes uppercase
       with wide tracking. That is the counterweight Apple puts under a large
       headline, and it separates the two lines at a glance.
     - "system-ui, -apple-system" is already this site's body stack, so on a
       Mac, iPhone or iPad this is drawn in San Francisco — the actual Apple
       face, not an impression of it. Elsewhere it falls to Segoe UI or Roboto,
       which keep the same rhythm.
   The heading takes its own sizes here rather than using .section__title's,
   because this card is a statement rather than a section header: the scale is
   the point. Its element and classes are unchanged, so nothing else is aware. */
.section--intro { padding: 64px 0 56px; }
/* The card itself. Built only from brand tokens — --paper surface, --gold and
   --pink as the accent rule, --line for the hairline — so the statement reads
   as part of the page's palette rather than as a pasted-in panel.
   The top rule is the one loud element: gold running into the accent pink is
   the colour pairing the header and the Book Now button already use.
   Padding is generous on purpose. This is the quietest card on the page and
   the most important sentence on it, so it gets room rather than decoration. */
.section--intro .container {
  position: relative;
  max-width: 940px;
  padding: 48px 44px 44px;
  /* White, as asked, with a whisper of warm grey at the foot rather than a
     flat fill: the card sits on the page's own white, so without the faint
     gradient and the hairline below, its lower edge would dissolve into the
     background and the card would stop reading as a card. */
  background: linear-gradient(180deg, var(--paper) 0%, #fbfaf7 100%);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-sm);
  overflow: hidden;
}
/* The same accent rule top and bottom. One rule per edge so the card is
   bounded rather than signed off only at the top — and it is the same gradient
   left to right, not mirrored, so the two edges match when read as a pair. */
.section--intro .container::before,
.section--intro .container::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 4px;
  background: linear-gradient(90deg, var(--gold) 0%, var(--pink) 100%);
}
.section--intro .container::before { top: 0; }
.section--intro .container::after { bottom: 0; }
.section--intro .section__title {
  font-size: clamp(1.75rem, 4.6vw, 3.35rem);
  font-weight: 700;
  letter-spacing: -0.022em;
  line-height: 1.06;
  margin-bottom: 0;
  /* Solid --ink on the cream card, no gradient: at 14.75:1 this is the
     strongest text/background pair in the block, and it keeps the card's one
     flourish (the gold-to-pink rule above) from having to share the stage. */
  color: var(--ink);
}
.section--intro .section__sub {
  margin-top: 16px;
  margin-bottom: 0;
  /* Brand green rather than --ink-soft: 6.40:1 on --cream, and it ties the
     eyebrow to the green running through the rest of the page. */
  color: var(--green);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(0.72rem, 1.15vw, 0.92rem);
  line-height: 1.5;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  /* The source string may be one long line; keep it to a readable measure
     instead of letting it run the full container width. */
  max-width: 46ch;
  margin-inline: auto;
}
@media (max-width: 640px) {
  .section--intro { padding: 48px 0 44px; }
  .section--intro .container { padding: 34px 22px 32px; }
  .section--intro .section__sub { letter-spacing: 0.12em; }
}

.hero__cta {
  margin-top: 22px;
  letter-spacing: 0.06em;
  padding: 14px 34px;
  font-size: 1rem;
}

/* Intro video — 16:9, autoplay/muted/loop like the original embed */
.intro-video { background: var(--ink); }
.intro-video__frame {
  position: relative;
  width: 100%;
  max-width: var(--container);
  margin: 0 auto;
  aspect-ratio: 16 / 9;
}
.intro-video__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}
/* Click-to-play façade. The embed used to autoplay here: that streamed ~14 MB
   down the same Slow-4G pipe as the hero and cost about 1.5 s of main-thread
   blocking, which was the single largest cost on the homepage. Until someone
   asks for the video this is the whole player — one lazy poster image and a
   button. initVideo in main.js swaps in the iframe on click. */
.intro-video__play {
  position: absolute;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
}
.intro-video__poster {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
/* Play badge: a circle and a triangle, drawn in CSS rather than shipped as an
   icon file or a data URI the minifier can mangle. */
.intro-video__play::before,
.intro-video__play::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
}
.intro-video__play::before {
  width: 76px;
  height: 76px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
}
.intro-video__play::after {
  /* Offset right by half the triangle's own width so it reads as centred. */
  margin-left: 6px;
  border-style: solid;
  border-width: 14px 0 14px 24px;
  border-color: transparent transparent transparent #fff;
}
.intro-video__play:hover::before { background: rgba(0, 0, 0, 0.72); }

/* ---------- Galleries (Apple-style scroll galleries) ----------
   Full-bleed, snap-scrolling image rows: fixed-ish card widths so the next
   card always peeks, flat cards with a large radius, no scrollbar, and
   circular arrows that page by one card (see main.js). */
.gallery {
  position: relative;
  margin: 32px 0 0;
}
.gallery__track {
  display: flex;
  gap: 24px;
  margin: 0;
  padding: 0 24px;
  list-style: none;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline-start: 24px;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.gallery__track::-webkit-scrollbar { display: none; }

/* Short sets that fit on wide screens: centre them instead of leaving dead
   space to the right. `safe center` keeps the first card reachable if the
   row ever does overflow (plain `center` would crop it unreachably). */
.gallery__track--centered {
  justify-content: center;
  justify-content: safe center;
}
.gallery__track--centered .gallery__item {
  scroll-snap-align: center;
}

.gallery__item {
  /* Sized for a clear peek of the next card (~2.5 across on desktop)
     instead of a breakpoint table of fixed counts. */
  flex: 0 0 clamp(250px, 28vw, 460px);
  scroll-snap-align: start;
}
.gallery__item img {
  /* No fixed aspect-ratio and no object-fit on purpose: these source images
     are designed tiles with text and borders baked in, so any forced shape
     slices the artwork. width/height attributes come from carousel.html and
     give the browser the ratio up front, so this still reserves space. */
  width: 100%;
  height: auto;
  border-radius: 18px;
}
/* Opt-in uniform row — carousel.html sets --card-ratio from the gallery's
   `aspect` param, and only for the rows that ask for it. Every other gallery
   keeps its mixed shapes.
   The card is given the ratio and the image is cropped to fill it rather than
   letterboxed: a part-empty card in a row of full ones reads as a mistake.
   Because cards are a fixed flex-basis, equal ratios mean equal heights, which
   is the whole point. */
.gallery__track--uniform .gallery__item img {
  aspect-ratio: var(--card-ratio);
  object-fit: cover;
}

/* Circular edge arrows */
.gallery__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.85);
  color: var(--ink);
  box-shadow: 0 2px 10px rgba(34, 34, 34, 0.18);
  cursor: pointer;
  transition: background-color 0.15s ease, opacity 0.15s ease;
}
.gallery__arrow svg { width: 20px; height: 20px; }
.gallery__arrow--prev { left: 12px; }
.gallery__arrow--next { right: 12px; }
/* Show whenever there is room beside the cards. Deliberately keyed off
   width rather than `hover: hover`: a wrong hover report (common in
   headless/VM setups) would otherwise hide the controls entirely.
   Above the burger breakpoint so the two never collide. */
@media (min-width: 1081px) {
  .gallery__arrow:not([hidden]) { display: flex; }
}
@media (hover: hover) {
  .gallery__arrow:hover { background: #fff; }
}
.gallery__arrow:focus-visible { outline: 3px solid var(--pink); outline-offset: 2px; }

/* Feast package pricing — full-bleed brand-gold band */
.pricing-band {
  background: var(--gold);
  padding: 48px 0 44px;
}
/* Inside the band the section title needs no top margin of its own, and the
   muted note colour fails AA on gold (3.9:1) — --ink is 8.8:1. */
.pricing-band .section__title--sm { margin-top: 0; }
.pricing-band .feast__note { color: var(--ink); }
/* The school package band carries a second line under its heading. */
.pricing__sub {
  text-align: center;
  font-family: var(--font-head);
  font-weight: 500;
  color: var(--ink);
  margin-top: 2px;
}
.pricing {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 28px;
  margin-top: 24px;
}
/* The card artwork's own outer edge is gold (254,178,1) — the same as the
   band — so it is deliberately left with no ring and no shadow: the cards
   melt into the gold and only their white price panels read. That is the
   intended look, not an oversight; adding a border or shadow here breaks it. */
.pricing__card {
  width: 380px;
  height: auto;
}
/* The band's action row. Flex, not `text-align: center` on inline-block
   buttons: with those, the newline between two buttons in the template is the
   only thing separating them, and minification collapses it — the two ended up
   touching with a measured gap of 0. `gap` states the spacing instead of
   depending on markup whitespace. 28px is the same spacing the ticket cards
   above use, and wrapping keeps the row usable on a phone. */
.pricing__cta {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 28px;
  margin: 32px 0 0;
}
.feast__note {
  margin: 20px auto 0;
  max-width: 760px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.9rem;
}

/* ---------- Activities + food list with its sticky local nav ----------
   Apple-style product-page local nav: a horizontally scrollable strip of every
   section anchor that parks under the header and keeps a sliding underline on
   whichever section you are looking at. 18 sections and ~150 items follow, so
   this is what stops the bottom of the list being unreachable by intent. */
.actnav {
  position: sticky;
  top: var(--header-h);
  z-index: 90;
  /* border-box + a fixed height keeps the measured height exactly
     --actnav-h, which is what .spec__row's scroll-margin-top is calculated
     from. Letting the borders add to it would put every anchor 2px wrong. */
  box-sizing: border-box;
  height: var(--actnav-h);
  background: var(--paper);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.actnav__scroll {
  height: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.actnav__scroll::-webkit-scrollbar { display: none; }

/* min-width:100% + justify-content:center keeps the strip centred while it
   still fits, then lets it bleed and scroll once it does not. */
.actnav__track {
  position: relative;
  display: flex;
  justify-content: center;
  width: max-content;
  min-width: 100%;
  padding: 0 12px;
}
.actnav__list {
  display: flex;
  gap: 2px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.actnav__link {
  display: flex;
  align-items: center;
  height: 100%;
  padding: 0 14px;
  color: var(--ink-soft);
  font-size: 0.92rem;
  font-weight: 500;
  white-space: nowrap;
  text-decoration: none;
  transition: color 0.18s ease;
}
.actnav__link:hover { color: var(--ink); text-decoration: none; }
.actnav__link[aria-current="true"] { color: var(--ink); font-weight: 600; }

/* One shared underline that slides, rather than each link lighting up. It
   fades out (not slides) when no section is active, hence the base having
   only the opacity transition. */
.actnav__bar {
  position: absolute;
  bottom: 0;
  left: 0;
  width: 0;
  height: 2px;
  background: var(--pink);
  opacity: 0;
  transition: opacity 0.2s ease;
}
.actnav.is-ready .actnav__bar {
  opacity: 1;
  transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1), width 0.28s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.2s ease;
}
/* Edge fades, shown only when there is actually more strip to scroll to. */
.actnav::before,
.actnav::after {
  content: "";
  position: absolute;
  top: 0;
  bottom: 0;
  width: 30px;
  z-index: 1;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.2s ease;
}
.actnav::before { left: 0; background: linear-gradient(90deg, var(--paper), rgba(255, 255, 255, 0)); }
.actnav::after { right: 0; background: linear-gradient(270deg, var(--paper), rgba(255, 255, 255, 0)); }
.actnav.can-start::before { opacity: 1; }
.actnav.can-end::after { opacity: 1; }

/* The 18 sections render as spec-sheet rows: name in a fixed left column, all
   its items as a single run of inline text on the right, hairline between rows.
   That is what stops 160 items costing 3,600px — a row's height follows its own
   item count, instead of every section paying ~150px for a full-width heading
   whether it holds two items or twenty-nine. scroll-margin-top is what makes an
   anchor click land with the row clear of both sticky bars. */
.actlist {
  /* This section carries an id, so a shared or restored #everything URL has to
     land with its title below the header. The strip is not parked yet at that
     scroll position, so only the header needs clearing here. */
  scroll-margin-top: var(--header-h);
}
.actset__title {
  margin: 34px 0 6px;
  font-size: 1.55rem;
}
.actset__title:first-child { margin-top: 8px; }
.spec__row {
  display: grid;
  grid-template-columns: 250px 1fr;
  gap: 32px;
  padding: 13px 0;
  border-top: 1px solid var(--line);
  scroll-margin-top: calc(var(--header-h) + var(--actnav-h) + 8px);
}
.spec__row:last-child { border-bottom: 1px solid var(--line); }
/* Sans, not the serif that h4 inherits: these are spec terms, not headings to
   read as prose, and 18 of them in serif make the column noisy. */
.spec__label {
  margin: 0;
  font-family: var(--font-body);
  font-size: 0.95rem;
  font-weight: 600;
  line-height: 1.4;
}
.spec__note {
  display: block;
  margin-top: 2px;
  font-size: 0.8rem;
  font-weight: 400;
  color: var(--ink-soft);
}
.spec__items {
  margin: 0;
  font-size: 0.9rem;
  line-height: 1.75;
  color: var(--ink-soft);
}
/* No column split here, deliberately. Splitting a long row's items into two
   sub-columns was measured at +25px and it broke "Zig Zag Walk" across the
   column gap, so a reader meets "Zig Zag" at the foot of one column and "Walk"
   at the head of the next as if they were separate items. One run is shorter
   and never splits an item. */
@media (max-width: 767px) {
  .actset__title { margin-top: 28px; font-size: 1.3rem; }
  .spec__row { display: block; }
  .spec__label { margin-bottom: 3px; }
}

/* ---------- Entrance reveals ----------
   One signature: fade in and settle, 720ms, on the curve Apple uses for
   entrances. Everything here hangs off .has-js, which only JavaScript adds,
   so the served HTML never hides content from a crawler or a visitor without
   JavaScript — the page is simply static in that case. The whole block is
   also skipped under prefers-reduced-motion, so those visitors get no hidden
   state at all rather than a fast one.

   The hero carries no data-reveal on purpose: it is this page's LCP element,
   and a transparent element is excluded from LCP, which makes the metric
   stop describing it. */
@media (prefers-reduced-motion: no-preference) {
  .has-js [data-reveal] { opacity: 0; }
  .has-js [data-reveal="scale"] { transform: scale(0.96); }
  .has-js [data-reveal]:not([data-reveal="scale"]) { transform: translateY(22px); }
  /* The transition lives on the revealed state, not the base one, so nothing
     transitions on first paint. main.js sets transition-delay inline for
     staggered groups, and an inline longhand beats this shorthand. */
  .has-js [data-reveal].is-in {
    opacity: 1;
    transform: none;
    transition: opacity 0.72s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.72s cubic-bezier(0.16, 1, 0.3, 1);
  }

  /* These rows are the nav strip's anchor targets, so the row itself must never
     move: scroll-into-view measures the transformed box, and a 22px offset put
     a jumped-to row 22px higher than intended — underneath the sticky bars it
     was supposed to clear. The row stays exactly where it is and its two
     children do the rising instead. Same look, honest geometry. */
  .has-js .spec__row[data-reveal] { opacity: 1; transform: none; }
  .has-js .spec__row[data-reveal] > * { opacity: 0; transform: translateY(22px); }
  .has-js .spec__row[data-reveal].is-in > * {
    opacity: 1;
    transform: none;
    transition: opacity 0.72s cubic-bezier(0.16, 1, 0.3, 1),
                transform 0.72s cubic-bezier(0.16, 1, 0.3, 1);
  }
}

/* ---------- House rules (family / school / corporate) ----------
   The same three groups on all three pages, rendered by partials/notes.html.
   Native <details>, so there is no JavaScript and no ARIA state to keep in sync
   — the browser already reports expanded state and already maps Enter/Space on
   the summary. Collapsed by default, as the original toggle block was: these are
   reference rules for someone already booking, not part of the pitch.
   The three are independent rather than exclusive: checking one rule should not
   snap the other two shut. */
.notes__group {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-top: 12px;
  overflow: hidden;
}
.notes__summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 18px;
  cursor: pointer;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
  list-style: none; /* Firefox */
}
.notes__summary::-webkit-details-marker { display: none; } /* Chrome, Safari */
.notes__summary:hover { background: var(--cream); }
.notes__summary:focus-visible { outline: 2px solid var(--pink); outline-offset: -2px; }
.notes__chevron {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--ink-soft);
  transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.notes__group[open] .notes__chevron { transform: rotate(180deg); }
.notes__list {
  margin: 0;
  padding: 0 20px 18px 42px;
  color: var(--ink-soft);
  font-size: 0.98rem;
  line-height: 1.7;
}
.notes__list li { margin-top: 9px; }
/* The gold marker is the only place the brand colour lands in this block, which
   is what keeps a wall of legal-ish text looking like the rest of the site. */
.notes__list li::marker { color: var(--gold); font-weight: 700; }

/* ---------- FAQ (shortcodes/faq.html) ----------
   Mirrors the .notes disclosure above — same border, radius, cream hover and
   rotating chevron — because both are native <details> blocks and a second
   disclosure style would read as a different component rather than a variant.
   Open by default would be wrong here: the answers are for someone already
   weighing the trip, and collapsed keeps a long page scannable. */
.faq { padding: 56px 0; }
.faq__title { text-align: center; margin-bottom: 24px; }
.faq__item {
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  margin-top: 10px;
  overflow: hidden;
}
.faq__q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 16px 18px;
  cursor: pointer;
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
  list-style: none; /* Firefox */
}
.faq__q::-webkit-details-marker { display: none; } /* Chrome, Safari */
.faq__q:hover { background: var(--cream); }
.faq__q:focus-visible { outline: 2px solid var(--pink); outline-offset: -2px; }
.faq__chevron {
  flex: none;
  width: 20px;
  height: 20px;
  color: var(--ink-soft);
  transition: transform 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.faq__item[open] .faq__chevron { transform: rotate(180deg); }
.faq__a {
  margin: 0;
  padding: 0 20px 18px;
  color: var(--ink-soft);
  font-size: 0.98rem;
  line-height: 1.7;
}

/* ---------- Contact details, map and captioned figures ----------
   /contact-us/ and /accreditation/ carry the same registered-office block
   upstream, rendered from site params by shortcodes/contact-details.html so it
   cannot drift from the footer. */
.contact-card {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 26px 28px;
}
.contact-card__name {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.2rem;
  color: var(--ink);
  margin-bottom: 16px;
}
/* A definition list, because these are label/value pairs and a screen reader
   should say so — the footer's run of bare <p> tags does not. */
.contact-card__list {
  display: grid;
  grid-template-columns: minmax(120px, max-content) 1fr;
  gap: 10px 24px;
  margin: 0;
}
.contact-card__list dt {
  font-weight: 600;
  color: var(--ink);
  font-size: 0.92rem;
  letter-spacing: 0.02em;
}
.contact-card__list dd { margin: 0; color: var(--ink-soft); }
.contact-card__list a { color: var(--green); text-decoration: none; }
.contact-card__list a:hover { text-decoration: underline; }

@media (max-width: 640px) {
  .contact-card { padding: 20px; }
  .contact-card__list { grid-template-columns: 1fr; gap: 2px 0; }
  .contact-card__list dd { margin-bottom: 10px; }
}

.map-embed {
  margin-top: 28px;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  /* Reserves the frame's height before the third-party document loads, so the
     footer does not jump down the page when it arrives. */
  aspect-ratio: 16 / 10;
  max-height: 460px;
}
.map-embed iframe { display: block; width: 100%; height: 100%; border: 0; }

.figure { margin: 0 0 28px; }
.figure img {
  display: block;
  width: 100%;
  height: auto;
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
}
.figure__caption {
  margin-top: 10px;
  text-align: center;
  color: var(--ink-soft);
  font-size: 0.92rem;
}

/* ---------- Feature row, tile grid, recognition strip ----------
   Three elements /corporate/ needs because the deck it is built from is not an
   article: it is a sequence of themed pitches. They carry the container measure
   themselves, like the flow prose around them, because a landing page body is
   deliberately not wrapped in a container. */

/* Image beside text, alternating sides. */
.feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: center;
  gap: 48px;
  width: 100%;
  max-width: var(--container);
  margin: 44px auto 0;
  padding-inline: 20px;
}
/* Source order stays image-then-text so the DOM reads in the order it is
   written, and only the visual order swaps. */
.feature--flip .feature__media { order: 2; }
.feature__media { margin: 0; }
.feature__media img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
}
.feature__title { font-size: clamp(1.15rem, 2.1vw, 1.5rem); margin-bottom: 10px; }
.feature__text { color: var(--ink-soft); }
.feature__text > :last-child { margin-bottom: 0; }

@media (max-width: 860px) {
  .feature { grid-template-columns: 1fr; gap: 20px; }
  /* Stacked, the image always leads, whichever side it sits on at desktop. */
  .feature--flip .feature__media { order: 0; }
}

/* Parallel short themes: cards wrap at any count, so adding or removing one
   never needs a matching column rule. */
.tiles {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 28px;
  width: 100%;
  max-width: var(--container);
  margin: 36px auto 0;
  padding-inline: 20px;
}
.tile {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.tile__img {
  display: block;
  width: 100%;
  height: auto;
  /* Cards in a row are as tall as their own content, so without a shared ratio
     the images end at different heights and the headings under them do not line
     up. Cropping to a common band is what keeps the row readable. */
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.tile__body { padding: 18px 20px 22px; }
.tile__title { font-size: 1.08rem; margin-bottom: 8px; }
.tile__text { color: var(--ink-soft); font-size: 0.95rem; }
.tile__text > :last-child { margin-bottom: 0; }

/* ---------- Linked cards: the homepage's jump-off row ----------
   The three audience cards (Families / School / Corporate) before Featured In.
   Deliberately a sibling of .tiles rather than a reuse of it: these are links,
   and the whole card is the target — it lifts and takes a shadow on hover so
   it reads as one object rather than a picture with a link somewhere in it.
   The grid is the same auto-fit pattern, so the count is never hard-coded. */
.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  /* Each card ends where its own text ends. Left to stretch, a card with
     shorter copy carries a gap under it and its link drifts away from the
     others' — the row reads as misaligned rather than as one set. */
  align-items: start;
  gap: 28px;
  width: 100%;
  max-width: var(--container);
  margin: 36px auto 0;
  padding-inline: 20px;
}
.card {
  display: flex;
  flex-direction: column;
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
  color: inherit;
  text-decoration: none;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.card:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: rgba(51, 102, 1, 0.35);
  color: inherit;
  text-decoration: none;
}
.card:focus-visible { outline: 3px solid var(--pink); outline-offset: 3px; }
/* A shared ratio keeps the three photos the same band height, whatever shape
   each source file is, so the headings below them line up. */
.card__img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.card__body { padding: 20px 22px 24px; }
.card__title { font-size: 1.25rem; margin-bottom: 8px; }
.card:hover .card__title { color: var(--green); }
.card__text { color: var(--ink-soft); font-size: 0.95rem; }
.card__text > :last-child { margin-bottom: 0; }
/* The affordance, not a second button: the card is already the link, and three
   buttons in a row would compete with the page's real calls to action. */
.card__cta {
  margin: 14px 0 0;
  color: var(--green);
  font-weight: 600;
  font-size: 0.92rem;
}
.card__cta span { display: inline-block; transition: transform 0.18s ease; }
.card:hover .card__cta span { transform: translateX(3px); }

/* Recognition: the Google rating plus the named awards. */
.awards { padding: 48px 0 8px; }
.awards__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 20px;
}
.award {
  background: var(--cream);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 22px 24px;
  text-align: center;
}
.award__score {
  font-family: var(--font-head);
  font-weight: 700;
  font-size: 2.1rem;
  line-height: 1;
  color: var(--ink);
  margin-bottom: 8px;
}
.award__stars {
  display: inline-flex;
  gap: 2px;
  margin-left: 8px;
  vertical-align: middle;
  color: var(--gold);
}
.award__stars svg { width: 18px; height: 18px; }
.award__title {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.02rem;
  color: var(--ink);
  margin-bottom: 4px;
}
.award__year {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 0.78rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  background: var(--gold);
  border-radius: 999px;
  padding: 2px 9px;
  vertical-align: middle;
}
.award__meta { color: var(--ink-soft); font-size: 0.9rem; margin-bottom: 0; }

/* Reviews (/reviews/), drawn by shortcodes/reviews.html.

   One column, because the page keeps the 780px reading measure every other
   prose page uses and these are paragraphs of someone else's writing, not
   cards to be scanned.

   The list is a div, not a <ul>: .post__content ul carries a list's own
   padding and markers, and the review text inside each item is already
   paragraphs — a list of one-paragraph blocks buys nothing and has to be
   un-styled again. */
.reviews__list { display: grid; gap: 18px; }
.review {
  background: var(--paper);
  border: 1px solid var(--line);
  border-left: 4px solid var(--gold);
  border-radius: var(--radius-sm);
  padding: 20px 22px;
}
.review__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 2px 10px;
  margin: 0 0 8px;
}
.review__author {
  font-family: var(--font-head);
  font-weight: 600;
  font-size: 1.05rem;
  color: var(--ink);
}
.review__date { color: var(--ink-soft); font-size: 0.85rem; }
.review__stars { display: flex; gap: 2px; color: var(--gold); margin: 0 0 10px; }
.review__stars svg { width: 15px; height: 15px; }
.review__text { font-size: 0.97rem; }
.review__text > p { margin: 0 0 0.7em; }
.review__text > p:last-child { margin-bottom: 0; }

/* ---------- Review form (/s/leave-a-review/) ----------

   Drawn by shortcodes/review-form.html. Same card as .review above — cream
   page, thin rule, gold edge — because it is the same conversation: the page
   lists what guests said, then asks.

   The star radio row is reversed on screen (row-reverse) and in the DOM written
   5 to 1, which is what lets one sibling selector fill every star to the left
   of the chosen one. Reading order stays 1 to 5, keyboard arrows walk it in
   visual order, and each label carries its "N out of 5" in .sr-only. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Step one is the stars alone, so the form carries no box yet: a bordered card
   around an otherwise empty row of stars reads as a form that failed to load.
   The card arrives with the block it is meant to hold, in the step below. */
.review-form {
  padding: 0;
}

/* The salutation above the stars: Namaskar between the two hands, one line of
   thanks, the rating, the stars — all centred, because the hands make a
   symmetric ornament and nothing off-centre can sit next to it. The photograph
   closes the page, below the stars. */
.review-hero { text-align: center; }
/* Inline-block, not flex: as flex children these two hands were being joined by
   anonymous line boxes and the row stood 97px tall for a 36px ornament. On the
   text baseline they sit exactly where they look like they sit. */
/* Height is fixed to the hands' own, not left to the line box: the two inline
   images plus the word were producing a 97px row for a 44px ornament, and a
   fixed row is the honest way to say how tall the ornament is. */
.review-hero__hello {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 44px;
  font-family: var(--font-head);
  font-size: 1.9rem;
  line-height: 1.2;
  margin: 0 0 6px;
}
.review-hero__hands {
  display: inline-block;
  width: 44px;
  height: 44px;
  margin: 0 10px;
  vertical-align: middle;
}
.review-hero__hands--flip { transform: scaleX(-1); }
.review-hero__line { color: var(--ink-soft); margin: 0 0 18px; }

/* Five stars: the TripAdvisor ask. Revealed by main.js, so it is not on screen
   for the guests who did not have a five-star day. */
.review-tripadvisor { margin-top: 26px; }
.review-tripadvisor__line {
  font-family: var(--font-head);
  font-size: 1.15rem;
  line-height: 1.35;
  margin: 0 0 14px;
}
/* .post__content a underlines every link inside the reading measure, and this
   button is one. Same specificity, so this only has to come later. */
.review-tripadvisor a { text-decoration: none; }
.review-tripadvisor__btn {
  font-size: 1.05rem;
  padding: 16px 34px;
}
.review-tripadvisor__btn:hover { color: #fff; }

/* The confetti canvas covers the viewport for the two seconds it lives, and
   never takes a click. */
.confetti {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 200;
}

.review-photo { margin: 34px auto 0; max-width: 640px; }
.review-photo__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: var(--radius-sm);
}

@media (max-width: 620px) {
  .review-hero__hello { height: 36px; font-size: 1.6rem; }
  .review-hero__hands { width: 36px; height: 36px; margin: 0 8px; }
  .review-photo { margin-top: 26px; }
}

/* The honeypot. Off-screen rather than display:none — a hidden field some bots
   skip, an off-screen one they fill. Not focusable, not announced. */
.review-form__trap {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.stars { border: 0; margin: 0 0 18px; padding: 0; }
.stars:last-child { margin-bottom: 0; }
.stars__legend { padding: 0; margin-bottom: 6px; font-weight: 600; font-size: 0.98rem; }
.stars--sub .stars__legend { font-size: 0.92rem; font-weight: 500; color: var(--ink-soft); }
.stars__row { display: flex; flex-direction: row-reverse; justify-content: flex-end; gap: 2px; }
.stars--main { margin: 0; }
.stars--main .stars__row { justify-content: center; gap: 10px; }
/* The rating sits under the stars, smaller than the thanks above them: it is
   the record of what other guests said, not the ask. */
.review-form__proof {
  color: var(--ink-soft);
  font-size: 0.82rem;
  line-height: 1.4;
  margin: 10px 0 0;
}
.stars__row input { position: absolute; width: 1px; height: 1px; opacity: 0; }
.stars__row label {
  cursor: pointer;
  line-height: 0;
  color: #c9c1ab;
  transition: color 0.12s ease, transform 0.12s ease;
}
/* Empty stars are outlines, chosen ones are solid: an empty grey star that is
   already filled reads as "3 of 5 selected" before anything is picked. The path
   carries fill="currentColor" as an attribute, which these rules override. */
.stars__row label svg path {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.4;
  transition: fill 0.12s ease;
}
.stars--main .stars__row label svg { width: 48px; height: 48px; }
.stars--sub .stars__row label svg { width: 24px; height: 24px; }
/* Filled: the hovered star and every one below it, or the checked one and
   everything below it. `~ label` is the lower numbers because the DOM is
   reversed — see the block comment above. */
.stars__row input:checked ~ label,
.stars__row label:hover,
.stars__row label:hover ~ label { color: var(--gold); }
/* …and the same set is the one that fills in. Colour alone would leave a
   chosen star an outline, which at 48px reads as "not picked". */
.stars__row input:checked ~ label svg path,
.stars__row label:hover svg path,
.stars__row label:hover ~ label svg path { fill: currentColor; }
.stars__row label:hover { transform: scale(1.08); }
.stars__row input:focus-visible + label { outline: 2px solid var(--pink); outline-offset: 3px; border-radius: 4px; }

/* Four stars or fewer: one question at a time, each replacing the last, so an
   unhappy guest never meets a six-field wall. The star questions answer
   themselves — a click is the answer and the way forward — and the two boxes
   and the name carry a Next. Only the last step submits. */
.review-wizard { margin-top: 18px; }

.review-step { animation: review-step-in 0.2s ease both; }
@keyframes review-step-in {
  from { opacity: 0; transform: translateY(6px); }
  to { opacity: 1; transform: none; }
}
@media (prefers-reduced-motion: reduce) {
  .review-step { animation: none; }
}

.review-step__ask:focus { outline: none; }
.review-step__ask {
  font-family: var(--font-head);
  font-size: 1.4rem;
  line-height: 1.25;
  margin: 0 0 12px;
}
.review-step .stars--sub { margin: 0 0 2px; }
.review-step .stars__row { justify-content: center; }
.review-step .stars--sub .stars__row label svg { width: 34px; height: 34px; }

/* A name does not need 780px, and a 520px box reads as something to fill in. */
.review-step input[type="text"],
.review-step textarea {
  max-width: 520px;
  display: block;
  margin-inline: auto;
}

.review-step__actions { margin: 12px 0 0; }
.review-step__skip,
.review-step__next {
  background: none;
  border: 0;
  padding: 6px;
  font: inherit;
  font-size: 0.92rem;
  color: var(--ink-soft);
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}
.review-step__skip:hover,
.review-step__next:hover { color: var(--pink); }
.review-step__next { color: var(--pink); font-weight: 600; font-size: 0.98rem; }

/* The page is centred; the words a guest types are not. */
.review-form textarea,
.review-form input[type="text"] { text-align: left; }

.review-form__field { margin: 0 0 16px; }
.review-form__field label { display: block; font-weight: 600; font-size: 0.92rem; margin-bottom: 5px; }
.review-form__hint { font-weight: 400; color: var(--ink-soft); }
.review-form input[type="text"],
.review-form textarea {
  width: 100%;
  font: inherit;
  font-size: 0.97rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  padding: 10px 12px;
}
.review-form textarea { resize: vertical; min-height: 84px; }
.review-form input[type="text"]:focus,
.review-form textarea:focus {
  outline: 2px solid var(--pink);
  outline-offset: 1px;
  border-color: transparent;
}
.review-form__submit { margin: 0 0 14px; }
.review-form__note { color: var(--ink-soft); font-size: 0.85rem; margin: 0 0 10px; }
.review-form__error {
  background: #fdecef;
  border-left: 3px solid var(--pink);
  border-radius: var(--radius-sm);
  color: var(--ink);
  font-size: 0.92rem;
  padding: 10px 14px;
  margin: 0 0 14px;
}
.review-form__done {
  background: var(--cream);
  border-left: 4px solid var(--green);
  border-radius: var(--radius-sm);
  padding: 24px;
}
.review-form__done h2 { margin: 0 0 8px; }
.review-form__done p:last-child { margin-bottom: 0; }

@media (max-width: 620px) {
  .stars--main .stars__row label svg { width: 42px; height: 42px; }
}

/* ---------- Decorative brand ornaments ----------
   Three reference SVGs, stripped of their vectorised word labels and with
   their embedded rasters re-encoded to WebP at 240px. Each is drawn at a
   fraction of that, so none is soft. Every one is decorative: no alt text,
   aria-hidden on the wrapper, and none of it is needed to understand a page. */

/* The camels' gold dune meets the gold band below it. The -1px closes the
   hairline of antialiasing that would otherwise show as a pale seam between
   an image edge and the band. */
.horizon { background: var(--paper); }
.horizon__dunes { display: block; width: 100%; height: auto; margin-bottom: -1px; }

/* A hairline broken by the mandala. Sits between two .section elements, so the
   hairline they would have shared via .section + .section is gone: the
   adjacency is broken and this rule takes its place instead of doubling it. */
.divider {
  display: flex;
  align-items: center;
  gap: 18px;
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 20px;
  box-sizing: border-box;
}
.divider::before,
.divider::after { content: ""; flex: 1; height: 1px; background: var(--line); }
.divider img { flex: 0 0 auto; width: 74px; height: 74px; }

/* The puppets hang from the top edge of whichever section hosts them: the gold
   band's bottom edge for the activities list, the video band's bottom edge for
   the section under it. Either way their strings meet the band above and the
   figures hang down into the section. The calc aligns them to the content
   column rather than the viewport once the screen is wider than the container. */
.hangs { position: relative; }
/* The puppets hang into a page's main section on every page but the homepage,
   which hosts its own pairs inside .section. That section's own 56px of padding
   is not enough on its own, so .main gets an explicit larger one: 84px of figure
   on desktop plus a gap before the title's ink. */
.main.hangs { padding-top: 112px; }
.hang {
  position: absolute;
  top: 0;
  width: 76px;
  height: auto;
}
.hang--left { left: max(20px, calc(50% - var(--container) / 2 + 20px)); }
.hang--right { right: max(20px, calc(50% - var(--container) / 2 + 20px)); }
/* On phones the puppets stay — they are decorative and absolutely positioned,
   so their width costs the text nothing. What they do need is vertical room:
   they hang from the section's top edge, so the heading has to start below
   their feet or the title runs underneath them. Hence the extra padding-top,
   sized to clear the scaled-down figures with a small gap. */
@media (max-width: 1023px) {
  .hang { width: 62px; }
  .hang--left { left: 14px; }
  .hang--right { right: 14px; }
  /* .section.hangs, not .hangs: the small-screen block further down sets
     `.section { padding: 40px 0 }` and wins on source order at equal
     specificity, which left the title sitting on top of the puppets. */
  .section.hangs { padding-top: 84px; }
  /* The puppets scale to 62px here, so 69px of figure plus the gap. */
  .main.hangs { padding-top: 96px; }
}

@media (prefers-reduced-motion: reduce) {
  .actnav.is-ready .actnav__bar { transition: none; }
  .has-js .hero__slide { transition: none; }
  .notes__chevron { transition: none; }
}

/* width:100% matters — without it this wide logo strip keeps its intrinsic
   width on narrow screens and overflows the page. */
.featured__img { display: block; width: 100%; max-width: 720px; margin: 0 auto; }

@media (max-width: 640px) {
  .gallery__track { gap: 16px; padding: 0 16px; scroll-padding-inline-start: 16px; }
  .gallery__item { flex-basis: 78%; }
  .section { padding: 40px 0; }
  .section__title--sm { margin-top: 28px; }
  .pricing__card { width: 260px; }
}
