/* ========================================
   Men's Wellness Retreat – Landing Page
   Color scheme: Warm & Calm (earth tones)
   ======================================== */

/* --- Google Fonts --- */
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&family=Playfair+Display:ital,wght@0,500;0,700;1,500&display=swap');

/* --- Custom Properties --- */
:root {
  /* Surfaces. Sections alternate between --color-bg and --color-white. Whatever
     sits on a white section – day chips, room cards, the gallery strip – is
     filled with --color-bg, so a card is always the ground tone on white.
     --color-bg-alt never grounds a section; it is the step below, for hover and
     for panels nested inside something else. */
  --color-bg: #FAF6F1;
  --color-bg-alt: #F0E9E0;
  --color-text: #3D3229;
  --color-text-light: #6B5D52;
  --color-accent: #7A8B6F;
  --color-accent-hover: #647556;
  --color-warm: #C4956A;
  --color-warm-light: #E8D5C0;
  --color-border: #DDD4C9;
  --color-white: #FFFFFF;
  --color-warm-hover: #B8855A;
  /* The inverted half of the page alternates the same way the light half does,
     with a step of the same size: --color-dark, then --color-dark-alt, then back.
     --color-dark-alt happens to match --color-text, but it is a surface, not the
     text colour doing double duty. */
  --color-dark: #4A3C33;
  --color-dark-alt: #3D3229;

  /* Line heights. Tight for headings, normal for UI text, relaxed for the long
     reading passages. */
  --leading-tight: 1.3;
  --leading-snug: 1.7;
  --leading-normal: 1.8;
  --leading-relaxed: 1.9;

  --transition-fast: 0.15s;
  --transition-base: 0.2s;
  --transition-slow: 0.3s;

  --shadow-sm: 0 1px 5px rgba(0, 0, 0, 0.15);
  --shadow-md: 0 4px 16px rgba(0, 0, 0, 0.1);

  --font-body: 'Inter', sans-serif;
  --font-heading: 'Playfair Display', serif;

  /* Type scale. Anything below --text-lg is supporting text: labels, stats,
     captions. --text-lg is body copy. Headings have their own scale so they
     can carry the display font without dragging the UI sizes along. */
  --text-xs: 0.7rem;
  --text-sm: 0.8rem;
  --text-md: 0.9rem;
  --text-lg: 1rem;
  --text-xl: 1.15rem;

  --heading-sm: 1.25rem;
  --heading-md: 1.4rem;
  --heading-lg: 1.7rem;
  --heading-xl: 2rem;
  --heading-2xl: 2.75rem;

  /* Spacing scale. Every gap, padding and margin on the page picks from these. */
  --space-2xs: 0.25rem;
  --space-xs: 0.5rem;
  --space-sm: 0.75rem;
  --space-md: 1rem;
  --space-lg: 1.5rem;
  --space-xl: 2rem;
  --space-2xl: 2.5rem;
  --space-3xl: 3rem;
  --space-4xl: 4rem;

  /* Corner radii: sm for anything inset inside a panel, md for panels and
     rows, lg for the large standalone blocks. */
  --radius-sm: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;

  /* Icon sizes, tied to the text they sit next to */
  --icon-sm: 1rem;
  --icon-md: 1.1rem;
  --icon-lg: 1.4rem;

  --max-width: 960px;
  --spacing-section: 6rem;
}

/* --- Reset & Base --- */
*,
*::before,
*::after {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

html {
  scroll-behavior: smooth;
  font-size: 16px;
  overflow-x: hidden;
}

body {
  font-family: var(--font-body);
  color: var(--color-text);
  background-color: var(--color-bg);
  line-height: var(--leading-snug);
  -webkit-font-smoothing: antialiased;
}

img {
  max-width: 100%;
  /* Required: with width/height attributes in the markup, a CSS width alone
     leaves the attribute height in force and the box comes out the wrong
     shape. */
  height: auto;
  display: block;
}

a {
  color: var(--color-accent);
  text-decoration: none;
  transition: color var(--transition-base);
}

a:hover {
  color: var(--color-accent-hover);
}

/* --- Typography --- */
h1, h2, h3 {
  font-family: var(--font-heading);
  font-weight: 500;
  line-height: var(--leading-tight);
}

h1 {
  font-size: var(--heading-2xl);
  color: var(--color-white);
}

h2 {
  font-size: var(--heading-xl);
  margin-bottom: var(--space-lg);
  color: var(--color-text);
}

h3 {
  font-size: var(--heading-sm);
  margin-bottom: var(--space-xs);
}

p {
  margin-bottom: var(--space-md);
}

/* --- Layout --- */
.container {
  max-width: var(--max-width);
  margin: 0 auto;
  padding: 0 var(--space-lg);
}

section {
  padding: var(--spacing-section) 0;
  scroll-margin-top: var(--nav-height, 76px);
}

/* --- Navigation --- */
.nav {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 100;
  padding: var(--space-md) 0;
  background: rgba(250, 246, 241, 0.95);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid transparent;
  transition: border-color var(--transition-slow);
}

.nav.scrolled {
  border-bottom-color: var(--color-border);
}

.nav .container {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.nav-logo {
  display: flex;
  flex-direction: column;
  line-height: 1.2;
  color: var(--color-text);
}

.nav-logo-name {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: 500;
}

.nav-logo-sub {
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 400;
  color: var(--color-text-light);
  letter-spacing: 0.08em;
}

.nav-cta {
  font-size: var(--text-md);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--color-text-light);
  transition: color var(--transition-base);
}

.nav-cta:hover {
  color: var(--color-text);
}

/* --- Hero --- */
.hero {
  position: relative;
  min-height: 100vh;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 0;
  overflow: hidden;
}

.hero-bg {
  position: absolute;
  inset: 0;
  background-image: url('content/hero.jpeg');
  background-size: cover;
  background-position: center;
  z-index: 0;
}

.hero-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.3);
}

.hero-content {
  position: relative;
  z-index: 1;
  max-width: 700px;
  padding: var(--space-xl);
}

.hero h1 {
  margin-bottom: var(--space-lg);
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.hero-subtitle {
  font-size: var(--text-xl);
  color: rgba(255, 255, 255, 0.9);
  font-weight: 400;
  line-height: var(--leading-normal);
  margin-bottom: var(--space-2xl);
}

.hero-details {
  display: flex;
  gap: var(--space-xl);
  justify-content: center;
  flex-wrap: wrap;
  font-size: var(--text-md);
  color: rgba(255, 255, 255, 0.8);
}

.hero-details span {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.hero-cta {
  display: inline-block;
  margin-top: var(--space-2xl);
  padding: var(--space-sm) var(--space-2xl);
  background: var(--color-warm);
  color: var(--color-white);
  font-weight: 500;
  font-size: var(--text-lg);
  border-radius: var(--radius-sm);
  transition: background var(--transition-base);
}

.hero-cta:hover {
  background: var(--color-warm-hover);
  color: var(--color-white);
}

.hero-arrow {
  position: absolute;
  bottom: 2rem;
  left: 50%;
  transform: translateX(-50%);
  z-index: 1;
  color: rgba(255, 255, 255, 0.6);
  font-size: var(--heading-md);
  text-decoration: none;
  animation: bounce 2s infinite;
  transition: color var(--transition-base);
}

.hero-arrow:hover {
  color: rgba(255, 255, 255, 0.9);
}

@keyframes bounce {
  0%, 100% { transform: translateX(-50%) translateY(0); }
  50% { transform: translateX(-50%) translateY(8px); }
}

/* --- Vision --- */
.vision {
  background: var(--color-bg);
}

.vision-content {
  max-width: 680px;
  margin: 0 auto;
  text-align: center;
}

.vision-content p {
  font-size: var(--text-xl);
  color: var(--color-text-light);
  line-height: var(--leading-relaxed);
}

.vision-content .highlight {
  color: var(--color-text);
  font-weight: 500;
}

/* --- Vision Pillars --- */
.vision-pillars {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2xl) var(--space-4xl);
  margin-top: var(--space-4xl);
}

.vision-pillar {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
  padding-top: var(--space-md);
  border-top: 1px solid var(--color-warm-light);
}

.vision-pillar-header {
  display: flex;
  align-items: center;
  gap: var(--space-xs);
}

.vision-pillar svg {
  width: var(--icon-md);
  height: var(--icon-md);
  color: var(--color-warm);
  stroke-width: 1.75;
  flex-shrink: 0;
}

.vision-pillar-title {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  font-weight: 500;
  color: var(--color-text);
}

.vision-pillar-text {
  font-size: var(--text-md);
  color: var(--color-text-light);
  line-height: var(--leading-relaxed);
}

/* --- Schedule --- */
.schedule {
  background: var(--color-white);
}

/* Master-detail layout wrapper (desktop) */
.schedule-layout {
  display: grid;
  grid-template-columns: 1fr 2fr;
  gap: var(--space-sm);
  margin-bottom: var(--space-2xl);
}

/* The days read as a list, not as a grid of tiles: a grid of equal tiles is
   the visual language of a table, and nobody clicks a table. Separate rounded
   rows read as single objects you can pick up – and there is no leftover cell. */
.schedule-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

/* No outline: the rows already stand out as filled shapes against the white
   section. Height is not set here – flex hands each row an equal share of
   whatever the map panel asks for, so more gap means slimmer rows and the
   list stays exactly as tall as the panel next to it. */
.schedule-day {
  flex: 1;
  display: grid;
  grid-template-columns: var(--icon-lg) 3.5rem 1fr auto;
  align-items: center;
  gap: var(--space-sm);
  padding: var(--space-2xs) var(--space-md);
  background: var(--color-bg);
  border-radius: var(--radius-md);
  transition: background var(--transition-base), color var(--transition-base);
  cursor: pointer;
  user-select: none;
}

.schedule-day:hover:not(.schedule-day--locked):not(.active) {
  background: var(--color-bg-alt);
}

.schedule-day:hover:not(.schedule-day--locked):not(.active) .day-chevron {
  transform: translateX(2px);
  color: var(--color-accent);
}

/* Arrival and farewell look exactly like every other day, because that is what
   they are – days of the week, in the same type, on the same surface. Nothing
   here is dimmed and nothing is outlined: both would treat them as a button
   that has been defeated, and they are not buttons at all, they are rows with
   nothing behind them. What tells them apart is the chevron they never had.
   A row that carries the mark opens something, a row without it is a statement
   – the disclosure convention every list on a phone already runs on. */
.schedule-day--locked {
  cursor: default;
}

.schedule-day.active {
  background: var(--color-accent);
}

.schedule-day.active .day-label {
  color: rgba(255, 255, 255, 0.65);
}

.schedule-day.active svg,
.schedule-day.active .day-title {
  color: var(--color-white);
}

.schedule-day svg {
  width: var(--icon-lg);
  height: var(--icon-lg);
  stroke-width: 1.5;
  color: var(--color-accent);
}

.day-chevron {
  width: 1rem !important;
  height: 1rem !important;
  color: var(--color-border);
  transition: transform var(--transition-base), color var(--transition-base);
}

.day-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-light);
}

.day-title {
  font-weight: 500;
  font-size: var(--text-md);
  color: var(--color-text);
}


/* Detail panel – the map lives here permanently and only ever changes what it
   shows. The head above it swaps between the resting hint and the picked day;
   its min-height keeps the map from jumping when the text length changes. */
/* Map on the left, text to the right of it, both halves fixed. The routes run
   roughly twice as far north to south as they do east to west, so half a
   column already gives the map the shape its content has – widening it would
   only add empty sea. Nothing resizes when a day is picked, so the map never
   has to be re-measured mid-animation. */
.schedule-detail {
  background: var(--color-bg);
  border-radius: var(--radius-md);
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-template-rows: 1fr auto;
  /* Rows tighter than columns: the row gap sits above the figures, and their
     own spacing sits below – uneven gaps around one element read as a mistake. */
  gap: var(--space-sm) var(--space-lg);
  padding: var(--space-lg);
  /* Fixed, not a minimum: the list next to it divides this height between its
     rows, so a long day text must never make the panel grow – it scrolls. */
  height: 34rem;
}

/* One viewport, several sheets of text sliding through it. Only one is on
   screen at a time, so they are stacked on top of each other and moved
   sideways rather than laid out in a row. */
.schedule-panes {
  position: relative;
  min-width: 0;
  overflow: hidden;
}

/* The curve matters more than the duration: it leaves fast and settles slowly,
   which is what makes a swipe feel like it carries weight instead of playing
   an animation. Keep in step with PANE_MS in app.js. */
.schedule-pane {
  position: absolute;
  inset: 0;
  overflow-y: auto;
  transition: transform 0.4s cubic-bezier(0.32, 0.72, 0, 1),
              opacity 0.25s ease;
  scrollbar-width: thin;
  scrollbar-color: var(--color-border) transparent;
}

.schedule-pane::-webkit-scrollbar {
  width: 6px;
}

.schedule-pane::-webkit-scrollbar-track {
  background: transparent;
}

.schedule-pane::-webkit-scrollbar-thumb {
  background: var(--color-border);
  border-radius: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .schedule-pane {
    transition: opacity var(--transition-base) ease;
  }
}

}

/* Resting text next to the map. The closing line is the promise of the whole
   week, so it is set apart instead of buried at the end of a paragraph. */
.schedule-intro p {
  color: var(--color-text-light);
  line-height: var(--leading-normal);
  margin-bottom: 0;
}

.schedule-intro p + p {
  margin-top: var(--space-md);
  color: var(--color-accent-hover);
  font-weight: 500;
}

/* No inset for the close button: it sits on the line of the day label, which
   is short enough to keep clear of it. Everything below runs the full width
   of its column, so both text edges line up with the panel. */
.schedule-detail-content {
  display: flex;
  flex-direction: column;
  gap: var(--space-sm);
}

.detail-day-label {
  padding-right: var(--space-lg);
}

.schedule-detail-close {
  position: absolute;
  top: var(--space-lg);
  right: var(--space-lg);
  z-index: 2;
  background: none;
  border: none;
  cursor: pointer;
  padding: 0;
  color: var(--color-text-light);
  line-height: 1;
  /* visibility rather than [hidden], so it can fade with the text */
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--transition-base) ease,
              visibility var(--transition-base),
              color var(--transition-fast);
}

.schedule-detail-close.is-visible {
  opacity: 1;
  visibility: visible;
}

.schedule-detail-close:hover {
  color: var(--color-text);
}

.schedule-detail-close svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  stroke-width: 2;
}

.detail-day-label {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--color-accent);
  font-weight: 500;
}

.detail-day-title {
  font-family: var(--font-heading);
  font-size: var(--text-xl);
  color: var(--color-text);
  line-height: var(--leading-tight);
}

.detail-day-text {
  font-size: var(--text-lg);
  color: var(--color-text-light);
  line-height: var(--leading-normal);
}

/* Map – always on screen, it only ever changes what it shows */
.schedule-map {
  width: 100%;
  height: 100%;
  min-width: 0;
  border-radius: var(--radius-sm);
  overflow: hidden;
  border: 1px solid var(--color-border);
  isolation: isolate;
}

/* Every line is a way into its day */
.schedule-map .leaflet-interactive {
  cursor: pointer;
}

/* Leaflet writes weight, colour and opacity straight onto the SVG path, so a
   route lighting up under the pointer is otherwise an instant switch. These
   are the only properties it touches for styling. */
.schedule-map .leaflet-overlay-pane path {
  transition: stroke var(--transition-base) ease,
              stroke-width var(--transition-base) ease,
              stroke-opacity var(--transition-base) ease,
              fill-opacity var(--transition-base) ease;
}

/* Waypoint marker – solid (start / finish) */
.map-waypoint-marker {
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: var(--color-accent);
  display: flex;
  align-items: center;
  justify-content: center;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.2));
  cursor: pointer;
  transition: transform var(--transition-fast), filter var(--transition-fast);
}

.map-waypoint-marker:hover {
  transform: scale(1.12);
  filter: drop-shadow(0 3px 8px rgba(0, 0, 0, 0.28));
}

.map-waypoint-marker svg {
  width: 12px;
  height: 12px;
  color: var(--color-white);
  stroke-width: 2.5;
}

/* Outline variant – POI waypoints */
.map-waypoint-marker--outline {
  background: var(--color-bg);
  border: 1.5px solid var(--color-accent);
}

.map-waypoint-marker--outline svg {
  color: var(--color-accent);
}

/* Custom zoom controls */
.map-zoom-control {
  display: flex;
  flex-direction: column;
  gap: 1px;
  background: var(--color-border);
  border-radius: var(--radius-sm);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}

.map-zoom-btn {
  width: 32px;
  height: 32px;
  background: var(--color-bg);
  border: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-fast);
}

.map-zoom-btn:hover {
  background: var(--color-bg-alt);
}

.map-zoom-btn svg {
  width: 14px;
  height: 14px;
  color: var(--color-text);
  stroke-width: 2;
}

/* Attribution watermark */
.leaflet-control-attribution {
  background: rgba(250, 246, 241, 0.8) !important;
  backdrop-filter: blur(4px);
  color: var(--color-text-light) !important;
  font-family: var(--font-body) !important;
  font-size: 0.6rem !important;
  padding: 2px 6px !important;
  box-shadow: none !important;
  border-radius: 4px 0 0 0 !important;
}

.leaflet-control-attribution a {
  color: var(--color-accent) !important;
}

/* Leaflet popup – match website design */
.leaflet-popup-content-wrapper {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md);
  font-family: var(--font-body);
  color: var(--color-text);
  font-size: var(--text-sm);
  padding: 0;
}

.leaflet-popup-content {
  margin: 0.6rem 0.9rem !important;
}

.leaflet-popup-tip {
  background: var(--color-bg);
}

.leaflet-popup-close-button {
  color: var(--color-text-light) !important;
  font-size: 1rem !important;
  padding: 4px 6px !important;
}

.map-popup-label {
  font-weight: 500;
  color: var(--color-text);
}

/* --- Elevation profile ---------------------------------------------------
   Runs the full width under both columns. Distance left to right means an
   out-and-back lays its two halves side by side instead of on top of each
   other, which is exactly what the coloured line on the map cannot do.
   At rest the same strip carries the week's totals, so nothing changes size
   when a day is opened. */
.schedule-profile {
  grid-column: 1 / -1;
  position: relative;
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* Fixed either way, so the map above keeps one height whether a day is open
     or the week's totals are showing. */
  height: 6.5rem;
}

/* Between the map and the chart, because that is what they describe – and as
   two small cards rather than a line of text: distance and climbing are the
   figures people actually go looking for. Anchored here they also stay in one
   place, instead of following the end of a day text that changes length. */
.route-stats {
  /* Fixed columns rather than natural width: "8.6 km" and "41.8 km" would
     otherwise be different sizes, and the cards would jump when the day
     changes instead of being able to cross-fade in place. */
  display: grid;
  /* A pair per track, so a day with a walk in it carries four cards where a
     ridden day carries two – the row grows rather than the numbers being
     folded together. Width is measured from the actual values once the GPX
     files are in – see sizeStatCards in app.js. max-content stands until then. */
  grid-auto-flow: column;
  grid-auto-columns: var(--stat-width, max-content);
  justify-content: start;
  gap: var(--space-xs);
  margin-bottom: var(--space-sm);
  min-height: 1.75rem;
  /* Arrives with the curve that grows under it, leaves ahead of it */
  animation: profile-fade-in var(--transition-slow) ease;
  transition: opacity var(--transition-fast) ease;
}

/* Only the way out is a fade – between days the numbers count across instead */
.schedule-profile.is-collapsing .route-stats {
  opacity: 0;
}

/* Tabular figures: proportional digits change width as they count, which makes
   the number jitter even though the card around it stands still. */
.stat-value {
  font-variant-numeric: tabular-nums;
}

/* The totals fade in once the curve has gone */
/* Same box for both directions: laid over the strip so the chart can have the
   space while the totals are still fading across it. */
.profile-summary.is-arriving,
.profile-summary.is-leaving {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  pointer-events: none;
  transition: opacity var(--transition-base) ease;
}

.profile-summary.is-leaving {
  opacity: 0;
}

/* Waits until the curve is most of the way down before it starts appearing –
   arriving at the same moment the chart begins to leave reads as too eager.
   backwards keeps it invisible during the delay. */
.profile-summary.is-arriving {
  animation-delay: 150ms;
  animation-fill-mode: backwards;
}

/* Already faded in by the time it lands in the flow, so it must not start over */
.profile-summary.no-fade {
  animation: none;
}

@keyframes profile-fade-in {
  from { opacity: 0; }
  to   { opacity: 1; }
}

.route-stat {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--space-2xs) var(--space-xs);
  background: var(--color-bg-alt);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-text);
  letter-spacing: 0.02em;
  white-space: nowrap;
}

.route-stat svg {
  width: 0.85rem;
  height: 0.85rem;
  color: var(--color-accent);
  stroke-width: 2;
  flex-shrink: 0;
}

/* A pair that only one of two days has – see reconcileFigures in app.js. In on
   an animation, out on a transition, at the same speeds as the row itself, so a
   walk joining the row reads as the same gesture one size smaller. */
.route-stat.is-arriving {
  animation: profile-fade-in var(--transition-slow) ease;
}

.route-stat.is-leaving {
  opacity: 0;
  transition: opacity var(--transition-fast) ease;
}

/* The card keeps the same box; only its icon changes colour, and it changes to
   the colour that leg is drawn in on the map and in the profile. That is what
   ties three readings of the same stretch together without a legend. */
.route-stat--hike svg {
  color: var(--color-warm);
}

/* Holds the chart and the cursor that runs across it in one coordinate space.
   Both take their height from the same variable, so the cursor cannot end up
   spanning the baseline as well and sitting a pixel low. */
/* Open, with no frame and no background of its own: the fill fades out at the
   bottom, so there is no edge that would need one. */
.profile-chart {
  position: relative;
  cursor: crosshair;
  --profile-height: 4rem;
}

.profile-svg {
  width: 100%;
  height: var(--profile-height);
  display: block;
  color: var(--color-accent);   /* the gradient reads this through currentColor */
}

/* The line marks the distance, the dot sits on the height at that distance –
   the same place the marker on the map is showing. */
.profile-cursor {
  position: absolute;
  top: 0;
  height: var(--profile-height);
  width: 1px;
  background: var(--color-accent);
  opacity: 0.5;
  pointer-events: none;
}

.profile-cursor--hike {
  background: var(--color-warm);
}

.profile-cursor--hike .profile-cursor-dot {
  background: var(--color-warm-hover);
}

.profile-cursor-dot {
  position: absolute;
  top: var(--dot-top, 50%);
  left: 50%;
  /* translate works off the rendered box, so the white ring is counted in.
     Offsetting by half the width alone left the dot sitting a ring-width
     down and to the right. */
  transform: translate(-50%, -50%);
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--color-accent-hover);
  border: 2px solid var(--color-white);
}

/* fill comes from the gradient in the markup */
.profile-area {
  stroke: none;
}

.profile-line {
  fill: none;
  stroke: var(--color-accent);
  stroke-width: 1.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* The walked leg, in the same warm tone as its line on the map. The gap either
   side of it comes from the drawing (PROFILE_GAP in route-map.js); the colour
   is what says which of the two kinds of effort the raised middle stretch is. */
.profile-line--hike {
  stroke: var(--color-warm);
}

/* A day changing shape passes through here: the walk in the ride's colour, the
   breaks closed to nothing – a drawing identical to a day with no walk in it,
   which is what lets the shapes themselves be swapped without it showing.
   The colour transitions, the breaks are drawn frame by frame, and both take
   the same moment as the curve changing height. */
.profile-chart.is-uniform .profile-line--hike {
  stroke: var(--color-accent);
}

.profile-chart.is-uniform .profile-fade--hike stop {
  stop-color: var(--color-accent);
}

.profile-line,
.profile-fade stop {
  transition: stroke var(--transition-slow) ease, stop-color var(--transition-slow) ease;
}

/* The fade under each leg. Kept here rather than in the markup so both ends of
   a route – the line and the ground under it – take their colour from the same
   place. */
.profile-fade--ride stop { stop-color: var(--color-accent); }
.profile-fade--hike stop { stop-color: var(--color-warm); }
.profile-fade-top    { stop-opacity: 0.3; }
.profile-fade-bottom { stop-opacity: 0.02; }

.profile-summary {
  /* In on an animation, out on a transition – and out faster than in, like
     everything else in this module. Keep in step with SUMMARY_FADE_MS.
     No margin: a bottom margin counts towards the centring while the line is
     in the flow, so it would shift by half of it the moment it is taken out. */
  animation: profile-fade-in var(--transition-slow) ease;
  transition: opacity var(--transition-fast) ease;
  margin: 0;
  /* Same voice as the invitation line in the panel beside it: both are
     statements about the week rather than supporting text. */
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--color-accent-hover);
  text-align: center;
}

/* --- Bike Accordion --- */
.bike-accordion {
  margin-top: var(--space-2xl);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--color-bg);
}

.bike-accordion-trigger {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-md) var(--space-lg);
  background: none;
  border: none;
  cursor: pointer;
  font-family: var(--font-body);
  font-size: var(--text-md);
  font-weight: 500;
  color: var(--color-text-light);
  gap: var(--space-xs);
  transition: background var(--transition-base), color var(--transition-base);
}

.bike-accordion-trigger:hover { background: var(--color-bg-alt); }

.bike-accordion-chevron {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
  transition: transform var(--transition-base) ease;
}

.bike-accordion.is-open .bike-accordion-chevron {
  transform: rotate(180deg);
}

.bike-accordion-panel {
  max-height: 0;
  overflow: hidden;
  transition: max-height var(--transition-slow) ease;
}

.bike-accordion-inner {
  display: grid;
  grid-template-columns: 1fr 1.6fr;
  gap: var(--space-xl);
  padding: var(--space-lg) var(--space-lg) var(--space-xl);
  border-top: 1px solid var(--color-border);
}

.bike-image-wrap {
  display: flex;
  align-items: center;
  justify-content: center;
}

.bike-image {
  width: 100%;
  max-width: 340px;
}

.bike-info-columns {
  display: flex;
  flex-direction: column;
  gap: var(--space-lg);
}

.bike-info-col-title {
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-text-light);
  margin-bottom: var(--space-xs);
  margin-top: var(--space-lg);
}

.bike-info-col-title:first-child { margin-top: 0; }

.bike-spec-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-2xs);
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.bike-spec-list li {
  font-size: var(--text-sm);
  color: var(--color-text);
  display: flex;
  gap: var(--space-2xs);
  flex-wrap: wrap;
}

.spec-key {
  color: var(--color-text-light);
  min-width: 5rem;
  flex-shrink: 0;
}

.spec-val { font-weight: 400; }

.bike-check-list {
  list-style: none;
  padding: 0;
  margin: 0 0 var(--space-2xs);
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.bike-check-list li {
  font-size: var(--text-sm);
  color: var(--color-text);
  display: flex;
  align-items: flex-start;
  gap: var(--space-xs);
}

.bike-check-list li svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  flex-shrink: 0;
  margin-top: 2px;
  color: var(--color-accent);
  stroke-width: 2.5;
}

/* --- Details Block --- */
.details-block {
  margin-bottom: var(--space-3xl);
  padding-bottom: var(--space-xl);
}

.details-facts {
  display: flex;
  gap: var(--space-3xl);
  flex-wrap: wrap;
}

.details-fact {
  display: flex;
  align-items: center;
  gap: var(--space-sm);
  color: var(--color-text);
}

.details-fact svg {
  width: var(--icon-md);
  height: var(--icon-md);
  stroke-width: 1.5;
  color: var(--color-accent);
  flex-shrink: 0;
}

.fact-value {
  display: block;
  font-weight: 500;
  font-size: var(--text-md);
}

.fact-note {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-text-light);
  margin-top: var(--space-2xs);
}

.details-divider {
  height: 1px;
  background: var(--color-border);
  margin: var(--space-lg) 0;
}

.details-prices {
  display: flex;
  gap: var(--space-md);
  flex-wrap: wrap;
}

.price-wrapper {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
}

.details-prices .details-fact {
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: var(--radius-md);
  padding: var(--space-md) var(--space-lg);
}

.details-prices .fact-value {
  font-family: var(--font-heading);
  font-size: var(--heading-lg);
  font-weight: 500;
  line-height: 1.1;
}

.details-prices .fact-note {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: var(--space-2xs);
}

.price-available {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-warm-light);
  margin-top: var(--space-xs);
}

.price-includes h3 {
  font-family: var(--font-body);
  font-size: var(--text-sm);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--color-text-light);
  margin-bottom: var(--space-md);
}

.price-includes-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--space-xs) var(--space-xl);
}

.price-includes-list li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-sm);
  font-size: var(--text-md);
  line-height: var(--leading-tight);
  color: var(--color-text);
}

.price-includes-list svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  stroke-width: 2;
  color: var(--color-accent);
  flex-shrink: 0;
  margin-top: var(--space-2xs);
}

.price-excludes {
  font-size: var(--text-sm);
  color: var(--color-text-light);
  margin-top: var(--space-md);
}

/* --- Island (full-bleed photo, caption anchored to the grid) --- */
.island {
  padding: 0;
}

.island-banner {
  position: relative;
  height: 380px;
  background-color: var(--color-warm-light);
  background-size: cover;
  background-position: center;
  display: flex;
  align-items: center;
}

/* An even veil rather than a text shadow, so the type stays clean. */
.island-banner::before {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(ellipse 70% 90% at center, rgba(38, 30, 24, 0.4), transparent 75%),
    linear-gradient(to bottom, rgba(38, 30, 24, 0.25), rgba(38, 30, 24, 0.35));
}

.island-banner .container {
  position: relative;
  z-index: 1;
}

.island-caption {
  text-align: center;
}

.island-kicker {
  font-size: var(--text-xs);
  text-transform: uppercase;
  letter-spacing: 0.32em;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.6);
  margin-bottom: var(--space-lg);
}

/* Three short claims on one line, held apart by hairlines. Short enough
   to read as set type rather than as a sentence laid over a photo. */
.island-points {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: var(--space-lg);
  font-size: var(--text-lg);
  font-weight: 400;
  letter-spacing: 0.02em;
  color: var(--color-white);
}

.island-sep {
  width: 1px;
  height: 0.9rem;
  background: rgba(255, 255, 255, 0.35);
  flex-shrink: 0;
}

/* --- About --- */
/* Second beat of the inverted closing block: contact, about, FAQ and the footer
   run dark, dark-alt, dark, dark-alt, so the bottom of the page keeps its edges. */
.about {
  background: var(--color-dark-alt);
}

.about h2 {
  color: var(--color-bg);
}

.about-content {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: var(--space-3xl);
  align-items: start;
}

.about-photo {
  width: 260px;
  height: 350px;
  max-width: 100%;
  border-radius: var(--radius-md);
  object-fit: cover;
  object-position: center;
}

.about-text p {
  color: rgba(250, 246, 241, 0.7);
  font-size: var(--text-lg);
  white-space: pre-line;
}

/* --- Gallery --- */
.gallery {
  margin-bottom: var(--space-3xl);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--color-border);
}

.gallery-viewport {
  position: relative;
  overflow: hidden;
  touch-action: pan-y;
  cursor: grab;
  user-select: none;
}

.gallery-viewport.dragging {
  cursor: grabbing;
}

.gallery-track {
  display: flex;
  transition: transform var(--transition-slow) ease;
}

.gallery-slide {
  min-width: 100%;
}

.gallery-image {
  width: 100%;
  height: 440px;
  object-fit: cover;
  display: block;
}

.gallery-image-placeholder {
  width: 100%;
  height: 440px;
  background: var(--color-warm-light);
}

.gallery-btn {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  background: rgba(255, 255, 255, 0.88);
  border: none;
  border-radius: 50%;
  width: 2.75rem;
  height: 2.75rem;
  font-size: var(--text-xl);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background var(--transition-base);
  z-index: 1;
}

.gallery-btn:hover {
  background: var(--color-white);
}

.gallery-btn-prev { left: 1rem; }
.gallery-btn-next { right: 1rem; }

.gallery-footer {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--space-sm) var(--space-md);
  background: var(--color-bg);
}

.gallery-caption {
  font-size: var(--text-md);
  color: var(--color-text-light);
  margin: 0;
}

.gallery-dots {
  display: flex;
  gap: var(--space-xs);
}

.gallery-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  border: none;
  background: var(--color-border);
  cursor: pointer;
  padding: 0;
  transition: background var(--transition-base);
}

.gallery-dot.active {
  background: var(--color-warm);
}

/* --- Conversations --- */
/* Nothing but words – no card, no plate, no image sitting on the surface. So the
   tone is free, and white suits what is written here: the quietest thing the page
   says, said on an empty page. */
.conversations {
  background: var(--color-white);
}

.conversations-body {
  max-width: 620px;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
}

.conversations-body p {
  font-size: var(--text-lg);
  line-height: var(--leading-snug);
  color: var(--color-text);
  white-space: pre-line;
}

.conversations-note {
  margin-top: var(--space-xl);
  font-size: var(--text-md);
  color: var(--color-text-light);
  font-style: italic;
}

/* --- Accommodation --- */
/* Tinted on purpose, and it has to stay that way: the room cards and the strip
   carrying the gallery caption are white plates, and this is the ground that
   lets them read as plates at all. On white they dissolve into the page and all
   that survives is a hairline. If this section ever needs a different tone, the
   things standing on it have to be rethought at the same time. */
.accommodation {
  background: var(--color-white);
}

.accommodation-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-xl);
  margin-top: var(--space-xl);
}

.accommodation-card {
  background: var(--color-bg);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--color-border);
  display: flex;
  flex-direction: column;
}

.accommodation-image-wrap {
  position: relative;
}

.accommodation-image {
  width: 100%;
  height: 260px;
  object-fit: cover;
  display: block;
}

.accommodation-image-placeholder {
  width: 100%;
  height: 260px;
  background: var(--color-warm-light);
}

.accommodation-info {
  padding: var(--space-lg);
}

.accommodation-header {
  display: flex;
  justify-content: space-between;
  align-items: flex-start;
}

.accommodation-name {
  font-family: var(--font-heading);
  font-size: var(--heading-sm);
  color: var(--color-text);
}

.accommodation-price-block {
  text-align: right;
}

.accommodation-price {
  display: block;
  font-family: var(--font-heading);
  font-size: var(--heading-md);
  color: var(--color-text);
  line-height: 1.1;
}

.accommodation-price-label {
  display: block;
  font-size: var(--text-xs);
  color: var(--color-text-light);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  margin-top: var(--space-2xs);
}

.accommodation-note {
  position: absolute;
  top: 0.85rem;
  left: 0.85rem;
  font-size: var(--text-xs);
  font-style: italic;
  color: var(--color-text);
  background: rgba(250, 246, 241, 0.88);
  padding: var(--space-2xs) var(--space-sm);
  border-radius: var(--radius-sm);
  backdrop-filter: blur(4px);
  margin: 0;
}

/* --- Food ---
   A grid instead of prose: days across the top, meals down the side. Full board
   is a claim, a week you can count is a fact – the arrival day visibly starts
   at dinner, the last one stops after breakfast, and the stops on the road sit
   in a row of their own because they come on top of everything else.

   The grid is the section; the two lines around it only introduce it and add
   what it cannot say. So it stands on a plate of its own, the way the room
   cards and the gallery strip do – loose marks on the section's ground read as
   something unfinished rather than as a drawing.

   The whole section hangs off the right margin, heading included. Every other
   heading on the page starts on the left, so this one changing sides is what
   says the section is its own thing – and a block that leans one way reads as
   placed, where a heading on one margin and its content on the other reads as
   two things that never met. */
.food {
  background: var(--color-bg);
}

.food h2,
.food-intro,
.food-summary,
.food-note {
  text-align: right;
}

.food-intro {
  max-width: 34rem;
  margin-top: var(--space-lg);
  margin-left: auto;
  color: var(--color-text-light);
}

.food-week {
  max-width: 38rem;
  margin-top: var(--space-2xl);
  /* Only the box moves. Its width is the one thing the alignment must not
     touch – shrinking it to its contents squeezes the columns together. */
  margin-left: auto;
  padding: var(--space-2xl) var(--space-xl);
  background: var(--color-white);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-lg);
}

/* One column per day, all of them equal, with the labels taking whatever they
   need. --food-days comes from the markup, so the edition switch can change how
   many there are without a second place to edit.

   The row gap is deliberately generous: the columns are wide, and a grid whose
   rows sit much closer together than its columns falls apart into scattered
   marks instead of reading as one field. */
.food-grid {
  display: grid;
  grid-template-columns: auto repeat(var(--food-days, 7), 1fr);
  align-items: center;
  gap: var(--space-lg) var(--space-2xs);
}

.food-day {
  text-align: center;
  font-size: var(--text-xs);
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.08em;
  color: var(--color-text-light);
}

.food-label {
  padding-right: var(--space-lg);
  font-size: var(--text-sm);
  color: var(--color-text);
  white-space: nowrap;
}

/* The one row that is not the kitchen's, marked in the colour of its own
   shapes. This is why the grid needs no legend. */
.food-label--out {
  color: var(--color-warm);
}

/* Every cell is drawn, so the grid keeps its rhythm where nothing is served –
   an empty slot is a faint dot rather than a hole. */
.food-cell {
  justify-self: center;
  width: 0.5rem;
  height: 0.5rem;
  border-radius: 50%;
  background: var(--color-border);
}

.food-cell--house {
  width: 0.7rem;
  height: 0.7rem;
  background: var(--color-accent);
}

/* A different shape as well as a different colour: the row is read across, and
   a square turned on its corner survives being small better than a second
   shade of the same dot. */
.food-cell--out {
  width: 0.6rem;
  height: 0.6rem;
  border-radius: 1px;
  background: var(--color-warm);
  transform: rotate(45deg);
}

/* The two half days, named under their own columns. Set quietly – they are a
   caption on the grid, not a fifth row of it. */
.food-edge {
  text-align: center;
  font-size: var(--text-xs);
  letter-spacing: 0.04em;
  color: var(--color-text-light);
  opacity: 0.75;
}

.food-total {
  max-width: 34rem;
  margin-top: var(--space-2xl);
  margin-left: auto;
}

.food-summary {
  margin-bottom: var(--space-xs);
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--color-text);
}

.food-note {
  margin-bottom: 0;
  font-size: var(--text-md);
  line-height: var(--leading-relaxed);
  color: var(--color-text-light);
}

@media (max-width: 768px) {
  /* Hanging off the right margin needs a left half to play against. On a phone
     there is one column, and everything reads from the left like the rest of
     the page. */
  .food h2,
  .food-intro,
  .food-summary,
  .food-note {
    text-align: left;
  }

  .food-intro,
  .food-week,
  .food-total {
    margin-left: 0;
  }
}

@media (max-width: 480px) {
  .food-week {
    padding: var(--space-xl) var(--space-md);
  }

  /* The labels are the only thing that can give – the columns are already down
     to a dot apiece. */
  .food-label {
    padding-right: var(--space-sm);
    font-size: var(--text-xs);
  }

  .food-edge {
    font-size: 0.65rem;
  }
}

/* --- Contact --- */
.contact {
  background: var(--color-dark);
}

.contact h2 {
  color: var(--color-white);
}

.contact-content {
  margin-top: var(--space-3xl);
}

.contact .details-block {
  border-color: rgba(255, 255, 255, 0.12);
}

.contact .details-fact {
  color: var(--color-white);
}

.contact .details-fact svg {
  color: var(--color-warm-light);
}

.contact .fact-value {
  color: var(--color-white);
}

.contact .fact-note {
  color: rgba(255, 255, 255, 0.5);
}

.contact .details-divider {
  background: rgba(255, 255, 255, 0.12);
}

.contact .price-includes h3 {
  color: rgba(255, 255, 255, 0.5);
}

.contact .price-includes-list li {
  color: rgba(255, 255, 255, 0.85);
}

.contact .price-includes-list svg {
  color: var(--color-warm-light);
}

.contact .price-excludes {
  color: rgba(255, 255, 255, 0.5);
}

.contact-content {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0;
  background: var(--color-white);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.contact-info {
  padding: var(--space-2xl);
  background: var(--color-bg-alt);
}

.contact-info h3 {
  font-family: var(--font-body);
  font-weight: 600;
  margin-bottom: var(--space-md);
  margin-top: var(--space-lg);
}

.contact-info h3:first-child {
  margin-top: 0;
}

.contact-info p {
  color: var(--color-text-light);
}

/* The steps carry their reason with them, so the section needs no separate
   paragraph explaining the process above the card. Numerals in the display face,
   the same idiom the food rows use. */
.contact-steps {
  list-style: none;
  counter-reset: step;
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  margin-bottom: var(--space-2xl);
}

.contact-steps li {
  counter-increment: step;
  display: grid;
  grid-template-columns: var(--space-lg) 1fr;
  gap: var(--space-sm);
}

.contact-steps li::before {
  content: counter(step);
  font-family: var(--font-heading);
  font-style: italic;
  font-size: var(--heading-sm);
  line-height: var(--leading-tight);
  color: var(--color-warm);
}

.step-title {
  display: block;
  font-size: var(--text-md);
  font-weight: 500;
  color: var(--color-text);
}

.step-note {
  display: block;
  font-size: var(--text-sm);
  line-height: var(--leading-snug);
  color: var(--color-text-light);
}

.contact-channels {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-sm);
}

.contact-link {
  display: inline-flex;
  align-items: center;
  gap: var(--space-xs);
  color: var(--color-text);
  font-weight: 500;
  font-size: var(--text-md);
  transition: color var(--transition-base);
}

.contact-link:hover {
  color: var(--color-accent);
}

.contact-link svg {
  width: var(--icon-sm);
  height: var(--icon-sm);
  stroke-width: 1.75;
  flex-shrink: 0;
  color: var(--color-accent);
}

.contact-form {
  display: flex;
  flex-direction: column;
  gap: var(--space-md);
  padding: var(--space-2xl);
}

.form-group {
  display: flex;
  flex-direction: column;
  gap: var(--space-2xs);
}

.form-group label {
  font-size: var(--text-sm);
  font-weight: 500;
  color: var(--color-text-light);
}

.form-group input,
.form-group textarea {
  padding: var(--space-sm) var(--space-md);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-md);
  color: var(--color-text);
  background: var(--color-white);
  transition: border-color var(--transition-base);
}

.form-group input:focus,
.form-group textarea:focus {
  outline: none;
  border-color: var(--color-accent);
}

.form-group textarea {
  resize: vertical;
  min-height: 120px;
}

.form-submit {
  padding: var(--space-sm) var(--space-xl);
  background: var(--color-warm);
  color: var(--color-white);
  border: none;
  border-radius: var(--radius-sm);
  font-family: var(--font-body);
  font-size: var(--text-lg);
  font-weight: 500;
  cursor: pointer;
  transition: background var(--transition-base);
  align-self: flex-start;
}

.form-submit:hover {
  background: var(--color-warm-hover);
}

.form-submit:disabled {
  opacity: 0.55;
  cursor: default;
}

/* Bot trap: kept out of sight and out of the tab order, but not
   display:none, which the smarter crawlers check for. */
.form-decoy {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  font-size: var(--text-md);
  line-height: var(--leading-snug);
  margin: 0;
}

.form-status:empty {
  display: none;
}

.form-status--pending {
  color: var(--color-text-light);
}

.form-status--success {
  color: var(--color-warm);
}

.form-status--error {
  color: #B4453C;
}

/* --- Footer --- */
.footer {
  padding: var(--space-xl) 0;
  background: var(--color-dark-alt);
  color: rgba(255, 255, 255, 0.6);
  font-size: var(--text-sm);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
}

.footer .container {
  display: flex;
  justify-content: flex-end;
  align-items: center;
}

.footer-links {
  display: flex;
  gap: var(--space-lg);
  list-style: none;
}

.footer-links a {
  color: rgba(255, 255, 255, 0.6);
}

.footer-links a:hover {
  color: rgba(255, 255, 255, 0.9);
}

/* --- Responsive --- */

/* Tablet */
@media (max-width: 768px) {
  :root {
    --spacing-section: 4rem;
  }

  h1 {
    font-size: var(--heading-xl);
  }

  h2 {
    font-size: var(--heading-lg);
  }

.about-content {
    grid-template-columns: 1fr;
    text-align: center;
  }

  .about-photo {
    margin: 0 auto;
  }

  .accommodation-grid {
    grid-template-columns: 1fr;
  }

  /* Stack the bike image above its details instead of squeezing both
     into two narrow columns. */
  .bike-accordion-inner {
    grid-template-columns: 1fr;
    gap: var(--space-lg);
  }

  .island-banner {
    height: 280px;
  }

  .island-points {
    gap: var(--space-md);
    font-size: var(--text-md);
  }

  .contact-content {
    grid-template-columns: 1fr;
    border-radius: var(--radius-md);
  }

  .price-includes-list {
    grid-template-columns: 1fr;
  }

  .contact-info {
    padding: var(--space-xl);
  }

  .contact-form {
    padding: var(--space-xl);
  }

  .schedule-layout {
    grid-template-columns: 1fr;
  }

  /* Seven rows stacked above the map would push it off a phone screen before
     anyone reaches it. Side by side the days fit into one band and the map
     stays in the same glance – the strip is swiped, not scrolled past. */
  .schedule-list {
    flex-direction: row;
    gap: var(--space-xs);
    overflow-x: auto;
    overflow-y: hidden;
    scrollbar-width: none;
    /* Runs to both screen edges: a card cut off by the edge reads as carrying
       on past it, and that is the only thing telling anyone there is more. */
    margin-inline: calc(var(--space-lg) * -1);
    padding-inline: var(--space-lg);
  }

  .schedule-list::-webkit-scrollbar {
    display: none;
  }

  /* Each day becomes a chip as wide as its own title. The icon keeps the place
     it holds in the desktop row – left of the text – so this reads as the same
     object rewrapped rather than a second component built from the same data.
     The day number moves above the title, where it captions it instead of
     standing beside it as an equal. */
  .schedule-day {
    flex: 0 0 auto;   /* as wide as its title, and no panel height to share out */
    grid-template-columns: var(--icon-lg) auto;
    grid-template-rows: auto auto;
    align-content: center;
    gap: 0 var(--space-sm);
    padding: var(--space-sm) var(--space-md);
    /* Two lines of body leading make the chip taller than it has anything to
       say. Both lines are a handful of words that never wrap, so the air
       between them is doing no reading work – only adding height. */
    line-height: var(--leading-tight);
    white-space: nowrap;
  }

  /* The icon stands beside both text lines, which stack to the right of it. */
  .schedule-day > :first-child {
    grid-row: 1 / span 2;
  }

  /* The chevron carries the distinction on the desktop, where a row also has a
     hover response to back it up. A swiped strip has neither, so here the chip
     itself says it. */
  .day-chevron {
    display: none;
  }

  /* The duller fill is the hover tone, which costs nothing at this width –
     there is no pointer on a touchscreen to claim it. One step down from the
     plain chip: enough for the eye to sort the row into two kinds at a glance,
     not so much that these two days look like a separate category. The writing
     steps back with it, onto the muted tone the day number already uses, so the
     whole chip sits on one level instead of half dimmed and half bright. */
  .schedule-day--locked {
    background: var(--color-bg-alt);
  }

  .schedule-day--locked .day-title,
  .schedule-day--locked svg {
    color: var(--color-text-light);
  }

  /* Stacked: text on top, map under it. No neighbour height to match, so the
     panel grows with its content instead of scrolling inside a fixed box. */
  .schedule-detail {
    grid-template-columns: 1fr;
    height: auto;
    padding: var(--space-md);
  }

  /* Side by side the map can lead, because the text is right there next to it.
     Stacked it cannot: the map would fill the screen and the sentence saying
     what the day is would sit below the fold, so the day gets read before it
     gets located. The profile stays under the map – it describes the route,
     not the day. */
  .schedule-panes {
    order: -1;
    /* Same curve and duration as the sheets sliding across it, so the box and
       its contents read as one movement rather than two. The height itself is
       set from growPanes in app.js – auto cannot be transitioned, so the box is
       given the two numbers to travel between. */
    transition: height 0.4s cubic-bezier(0.32, 0.72, 0, 1);
  }

  /* Side by side there is a fixed height for both sheets to fill, so both can
     be absolute. Stacked there is none, and an absolute sheet would leave the
     panel with no height at all. So the arriving sheet joins the flow and gives
     the panel its height, and only the departing one is lifted out – where it
     can still slide and fade across the sheet replacing it. Hiding it outright
     would turn the swap into a cut, and the direction of that slide is what
     says which way through the week you just moved. */
  .schedule-pane {
    position: relative;
    overflow-y: visible;
  }

  .schedule-pane.is-leaving {
    position: absolute;
    inset: 0 0 auto 0;
  }

  .schedule-map {
    height: 20rem;
  }

  .schedule-detail-close {
    top: var(--space-md);
    right: var(--space-md);
  }

  .vision-pillars {
    grid-template-columns: 1fr;
    gap: var(--space-xl);
  }
}

/* Mobile */
@media (max-width: 480px) {
  :root {
    --spacing-section: 3rem;
  }

  /* Four cards have to fit across a phone on the days that carry a walk. The
     row is what tells ridden from walked, so the cards give up size instead of
     wrapping – a second line would not fit the strip's fixed height either.
     The measured width in sizeStatCards follows this size, since it measures a
     real card at whatever size the viewport gives it. */
  .route-stats {
    gap: var(--space-2xs);
  }

  .route-stat {
    font-size: var(--text-xs);
    padding: var(--space-2xs);
    gap: var(--space-2xs);
  }

  h1 {
    font-size: var(--heading-lg);
  }

  .hero-subtitle {
    font-size: var(--text-lg);
  }

  .hero-details {
    flex-direction: column;
    gap: var(--space-xs);
    align-items: center;
  }

  .footer .container {
    flex-direction: column;
    gap: var(--space-md);
    text-align: center;
  }
}

/* --- FAQ --- */
.faq {
  background: var(--color-dark);
  padding: var(--spacing-section) 0;
}

.faq h2 {
  color: var(--color-bg);
}

.faq-list {
  margin-top: var(--space-3xl);
  list-style: none;
  padding: 0;
}

.faq-item {
  border-bottom: 1px solid rgba(250, 246, 241, 0.12);
}

.faq-item:first-child {
  border-top: 1px solid rgba(250, 246, 241, 0.12);
}

.faq-question {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  padding: var(--space-lg) 0;
  background: none;
  border: none;
  cursor: pointer;
  text-align: left;
  font-size: var(--text-lg);
  font-weight: 500;
  color: var(--color-bg);
  font-family: var(--font-body);
}

.faq-icon {
  width: 1rem;
  height: 1rem;
  flex-shrink: 0;
  color: rgba(250, 246, 241, 0.45);
  stroke-width: 2;
  transition: transform var(--transition-base) ease, color var(--transition-base) ease;
}

.faq-item.is-open .faq-icon {
  transform: rotate(45deg);
  color: rgba(250, 246, 241, 0.8);
}

.faq-answer {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--transition-slow) ease;
}

.faq-item.is-open .faq-answer {
  grid-template-rows: 1fr;
}

.faq-answer-inner {
  overflow: hidden;
  font-size: var(--text-md);
  line-height: var(--leading-snug);
  color: rgba(250, 246, 241, 0.6);
  padding-bottom: 0;
  opacity: 0;
  transform: translateY(-4px);
  /* The 0.05s here are delays, not durations – they hold the content back
     until the panel has started opening. */
  transition: opacity var(--transition-base) ease 0.05s, transform var(--transition-base) ease 0.05s, padding-bottom var(--transition-slow) ease;
}

.faq-item.is-open .faq-answer-inner {
  padding-bottom: var(--space-lg);
  opacity: 1;
  transform: translateY(0);
}
