/* ----------------------------------------------------------------
   Taigh Tuaram — Editorial Hebridean
   Custom CSS beyond Tailwind/DaisyUI
   ---------------------------------------------------------------- */

/* === FONTS === */

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

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

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

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

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

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

@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("/static/fonts/sourcesans3-italic-latin.71c881907d08.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6,
    U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122,
    U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Source Sans 3';
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("/static/fonts/sourcesans3-italic-latin-ext.5358bd4fb16e.woff2") format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7,
    U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F,
    U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F,
    U+A720-A7FF;
}


/* === BODY PROSE COLOUR ===
   --color-prose lives here (not in @theme) because Tailwind v4 only
   emits @theme tokens that are referenced by utility classes; this one
   is consumed by raw CSS.

   Rules wrapped in @layer components so Tailwind utilities (text-white,
   text-base-content, etc.) — which live in @layer utilities — can
   override on a per-element basis. Unlayered rules beat layered ones
   regardless of specificity, which would otherwise break text-white on
   hero headings. */

:root {
  --color-prose: oklch(30% 0.015 250);
  /* Shared minimum touch-target (44px) for interactive controls. Mirrored on the
     DaisyUI side by --size-field in theme/static_src/src/styles.css. */
  --tap-target: 2.75rem;
}

@layer components {
  main {
    color: var(--color-prose);
  }

  main h1,
  main h2,
  main h3,
  main h4 {
    color: var(--color-base-content);
  }
}


/* === HEADING SCALE === */

/* Fluid clamps scale smoothly between the old mobile and 768px sizes
   (min = former mobile value, max = former desktop value) so there is no
   abrupt jump at the breakpoint and small phones get a proportional size. */

.h-display {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-weight: 300;
  font-size: clamp(3rem, 1.5rem + 6vw, 4.5rem);
  line-height: 1.05;
  letter-spacing: -0.02em;
}

.h-section {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-weight: 400;
  font-size: clamp(2.25rem, 1.5rem + 3vw, 3rem);
  line-height: 1.1;
  letter-spacing: -0.015em;
}

.h-subsection {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-weight: 400;
  font-size: clamp(1.5rem, 1.1rem + 1.5vw, 1.875rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.prose-narrow {
  max-width: 65ch;
}


/* === HARRIS TWEED TEXTURES === */

[class*="texture-"] {
  position: relative;
  isolation: isolate;
}

[class*="texture-"]::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  border-radius: inherit;
}

.texture-herringbone::before {
  opacity: 0.35;
  background-image: url("/static/images/tweed-herringbone.177f0fcf4862.svg");
  background-size: 64px 64px;
  background-repeat: repeat;
}

.texture-twill::before {
  opacity: 0.03;
  background-image: repeating-linear-gradient(45deg,
      transparent,
      transparent 4px,
      oklch(50% 0.02 240) 4px,
      oklch(50% 0.02 240) 5px);
}

.texture-warp::before {
  opacity: 0.06;
  background-image: repeating-linear-gradient(0deg,
      transparent,
      transparent 2px,
      oklch(50% 0.02 240) 2px,
      oklch(50% 0.02 240) 3px);
  background-size: 100% 8px;
}

/* Light-on-dark variant — for the footer over neutral granite */
.texture-herringbone-light::before {
  opacity: 0.6;
  background-image: url("/static/images/tweed-herringbone-dark.efa10c5efa16.svg");
  background-size: 64px 64px;
  background-repeat: repeat;
}


/* === HERO === */

.hero-scenic {
  position: relative;
  /* Full-bleed hero sized to the viewport so the bottom-aligned title is always
     visible on load without scrolling. The very-wide landscape (~2:1) source is
     centre-cropped by object-fit: cover. At every normal viewport (narrower than
     2:1) the crop is horizontal only — the vertical fills exactly — so wide screens
     show nearly the whole scene and tall phones show a central vertical slice.
     min-height stops it collapsing on very short viewports. (Avoid aspect-ratio +
     max-height here: when max-height clamps the height, the ratio derives width
     from it and the hero stops filling the width.) */
  width: 100%;
  height: 100vh;
  height: 100dvh;
  min-height: 32rem;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: center;
  overflow: hidden;
}

.hero-scenic__image {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.hero-scenic__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Very-wide source (~2:1) crops horizontally at all normal viewports, so only
     object-position X bites (Y is a no-op until the viewport is wider than the
     image). The cliff and sea stacks sit on the right; on narrow/portrait screens
     a centred slice would be open sea only, so bias the crop rightward to keep
     them in frame. Wide screens show the whole scene, so they centre (below). */
  object-position: 80% 50%;
}

@media (min-width: 1024px) {
  .hero-scenic__image img {
    object-position: 50% 50%;
  }
}

.hero-scenic__overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to bottom,
      rgba(0, 0, 0, 0.5) 0%,
      rgba(0, 0, 0, 0.15) 18%,
      rgba(0, 0, 0, 0.05) 45%,
      rgba(0, 0, 0, 0.25) 75%,
      rgba(0, 0, 0, 0.65) 100%);
}

/* For shorter banners (image-banner, image-16-9) where the title sits in
   the bottom ~15%. White display text needs the underlying composite
   pixel below ~50% luminance; against bright sand/sky that requires
   ~0.65 alpha minimum at the title position. */
.image-overlay-scrim {
  background: linear-gradient(to bottom,
      transparent 0%,
      transparent 30%,
      rgba(0, 0, 0, 0.3) 55%,
      rgba(0, 0, 0, 0.7) 80%,
      rgba(0, 0, 0, 0.9) 100%);
}

.image-overlay-scrim h1,
.image-overlay-scrim h2 {
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.35);
}

.hero-scenic__content {
  position: relative;
  z-index: 2;
  padding-bottom: 12vh;
  text-align: center;
}


/* === PULL QUOTE === */

.pull-quote {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-style: italic;
  font-weight: 300;
  font-size: 1.375rem;
  line-height: 1.5;
  padding-left: 1.5rem;
  border-left: 2px solid var(--color-accent);
  color: oklch(35% 0.02 250);
}


/* === SQUARE IMAGE === */

/* Square cells suit the mixed-orientation gallery: the portrait stove keeps
   most of its height, the landscapes lose only a little width. */
.image-square {
  aspect-ratio: 1 / 1;
  overflow: hidden;
  position: relative;
}

.image-square img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-16-9 {
  aspect-ratio: 16 / 9;
  overflow: hidden;
  position: relative;
}

.image-16-9 img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.image-banner {
  aspect-ratio: 3 / 1;
  overflow: hidden;
  position: relative;
}

.image-banner img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Experiences use overlaid headings on relatively short scenic images. The
   generic ratios are too shallow on phones, which can crop the text block. */
.experience-banner {
  min-height: 14rem;
}

.experience-hero-image {
  min-height: 20rem;
  width: 100%;
}

.experience-card-image {
  aspect-ratio: 4 / 3;
}

@media (min-width: 768px) {
  .experience-card-image {
    aspect-ratio: 16 / 9;
  }
}


/* === NAV LINK === */

.nav-link {
  text-transform: uppercase;
  font-weight: 500;
  font-size: 0.875rem;
  letter-spacing: 0.1em;
  padding: 0.5rem 0;
}

.nav-link:hover {
  color: oklch(38% 0.08 245);
}

/* White variant for transparent nav over hero */
.nav-link-light {
  color: rgba(255, 255, 255, 0.85);
}

.nav-link-light:hover {
  color: white;
}

/* Visible keyboard focus for links and icon buttons that otherwise only signal
   on hover. currentColor keeps the ring legible on both the light navbar and
   the white-on-hero and dark-footer variants. */
.nav-link:focus-visible,
.nav-link-light:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 4px;
  border-radius: 2px;
}

footer a:focus-visible,
.dropdown-content a:focus-visible,
.dropdown > button:focus-visible,
.console-nav a:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
  border-radius: 0.375rem;
}

/* Alert dismiss: a full tap target pulled back into the alert padding so the
   hit area clears 44px without enlarging the alert visually. */
.alert-dismiss {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: var(--tap-target);
  min-height: var(--tap-target);
  margin: -0.5rem -0.5rem -0.5rem 0;
  border-radius: 0.375rem;
}

.alert-dismiss:focus-visible {
  outline: 2px solid currentColor;
  outline-offset: 2px;
}


/* === EDITORIAL CARD ===
   Separation by background-shift, not border. The card auto-detects its
   surrounding section: on a base-200 section a card is base-100; on a
   base-100 section a card is base-200. Hover steps one stop further. */

.card-editorial {
  border-radius: 0.5rem;
  overflow: hidden;
  background: var(--color-base-100);
}

.bg-base-100 .card-editorial,
.texture-herringbone.bg-base-100 .card-editorial {
  background: var(--color-base-200);
}

a.card-editorial,
.card-editorial[role="button"] {
  display: block;
  color: inherit;
}

a.card-editorial:hover,
.card-editorial[role="button"]:hover {
  background: var(--color-base-300);
}

a.card-editorial:focus-visible,
.card-editorial[role="button"]:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 4px;
}


/* === BUTTONS — snap states, no transition === */

.btn-primary-editorial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-target);
  padding: 0.875rem 2rem;
  background: var(--color-primary);
  color: var(--color-primary-content);
  font-size: 0.875rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  border-radius: 0.375rem;
  border: none;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}

.btn-primary-editorial:hover {
  background: var(--color-primary-strong);
}

.btn-primary-editorial:active {
  background: var(--color-primary-strong);
  transform: translateY(1px);
}

.btn-primary-editorial:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.btn-primary-editorial:disabled,
.btn-primary-editorial[aria-disabled="true"] {
  opacity: 0.5;
  cursor: not-allowed;
}

.btn-primary-editorial.is-block {
  width: 100%;
}

.btn-secondary-editorial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-target);
  padding: 0.75rem 1.5rem;
  background: transparent;
  color: var(--color-base-content);
  font-size: 0.875rem;
  font-weight: 500;
  border: 1px solid var(--color-base-300);
  border-radius: 0.375rem;
  cursor: pointer;
  text-decoration: none;
  text-align: center;
}

.btn-secondary-editorial:hover {
  background: var(--color-base-200);
}

.btn-secondary-editorial:active {
  background: var(--color-base-300);
}

.btn-secondary-editorial:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}


/* === EDITORIAL ALERT (replaces DaisyUI full-colour fills) === */

.alert-editorial {
  border-left: 4px solid;
  border-radius: 0.375rem;
  padding: 1rem 1.25rem;
  background: oklch(97.5% 0.005 240 / 0.8);
}

.alert-editorial[data-type="success"] {
  border-left-color: oklch(50% 0.09 155);
}

.alert-editorial[data-type="error"] {
  border-left-color: oklch(50% 0.18 25);
}

.alert-editorial[data-type="warning"] {
  border-left-color: oklch(73% 0.13 75);
}

.alert-editorial[data-type="info"] {
  border-left-color: oklch(55% 0.08 230);
}

.alert-editorial[data-type="debug"] {
  border-left-color: oklch(86% 0.012 240);
}


/* === SECTION BREAK === */

.section-break {
  width: 100%;
  height: 1px;
  position: relative;
  overflow: hidden;
}

.section-break::before {
  content: '';
  position: absolute;
  inset: 0;
  background: repeating-linear-gradient(90deg,
      oklch(86% 0.012 240),
      oklch(86% 0.012 240) 4px,
      transparent 4px,
      transparent 8px);
}


/* === ERROR PAGES === */

.error-page {
  min-height: 100vh;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 2rem;
  position: relative;
  overflow: hidden;
}

.error-page__code {
  position: absolute;
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-weight: 200;
  font-size: clamp(12rem, 30vw, 28rem);
  line-height: 1;
  opacity: 0.06;
  user-select: none;
  pointer-events: none;
  z-index: 0;
}

.error-page__content {
  position: relative;
  z-index: 1;
  max-width: 28rem;
}


/* === MUSIC TOGGLE (site-wide background-music control) === */

/* Off-screen but fully rendered, so the YouTube iframe / audio keeps playing
   while out of sight. display:none or visibility:hidden would stop playback. */
.music__stage {
  position: fixed;
  left: -9999px;
  bottom: 0;
  width: 320px;
  height: 180px;
  overflow: hidden;
  pointer-events: none;
}

.music__stage iframe {
  width: 100%;
  height: 100%;
  border: 0;
}

.music-toggle {
  position: fixed;
  bottom: 1rem;
  left: 1rem;
  z-index: 40;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  min-height: var(--tap-target);
  padding: 0.5rem 1rem 0.5rem 0.625rem;
  background: var(--color-base-100);
  color: var(--color-base-content);
  border: 1px solid var(--color-base-300);
  border-radius: 9999px;
  box-shadow: 0 2px 10px oklch(20% 0.02 250 / 0.12);
  cursor: pointer;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
  transition: background 200ms ease, border-color 200ms ease, box-shadow 200ms ease;
}

.music-toggle:hover {
  background: var(--color-base-200);
  border-color: var(--color-stone);
}

.music-toggle:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.music-toggle__icon {
  flex-shrink: 0;
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  color: var(--color-primary);
}

.music-toggle__icon svg {
  width: 1.05rem;
  height: 1.05rem;
}

/* Play glyph at rest; pause glyph while playing. */
.music-toggle__pause { display: none; }
.music-toggle[data-playing] .music-toggle__play { display: none; }
.music-toggle[data-playing] .music-toggle__pause { display: block; }

.music-toggle__label {
  white-space: nowrap;
}

/* The swell: four bars that roll like a passing wave, only while playing. */
.music-toggle__swell {
  display: none;
  align-items: flex-end;
  gap: 2px;
  height: 0.9rem;
}

.music-toggle[data-playing] .music-toggle__swell {
  display: inline-flex;
}

.music-toggle__swell span {
  width: 3px;
  height: 100%;
  border-radius: 2px;
  background: var(--color-accent);
  transform-origin: bottom;
  transform: scaleY(0.3);
  animation: music-swell 2.4s ease-in-out infinite;
}

.music-toggle__swell span:nth-child(2) { animation-delay: 0.3s; }
.music-toggle__swell span:nth-child(3) { animation-delay: 0.6s; }
.music-toggle__swell span:nth-child(4) { animation-delay: 0.9s; }

@keyframes music-swell {
  0%, 100% { transform: scaleY(0.3); }
  50% { transform: scaleY(1); }
}

@media (prefers-reduced-motion: reduce) {
  .music-toggle__swell span {
    animation: none;
    transform: scaleY(0.55);
  }
}

/* Compact to an icon disc on phones, so it never crowds the content. */
@media (max-width: 480px) {
  .music-toggle {
    padding: 0.5rem;
  }
  .music-toggle__label {
    display: none;
  }
}


/* === FORM FIELD (editorial bottom-border style) === */

.form-editorial .field-group {
  position: relative;
  margin-bottom: 1.5rem;
}

.form-editorial .field-group label {
  display: block;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-stone);
  margin-bottom: 0.375rem;
}

.form-editorial .field-group input,
.form-editorial .field-group select,
.form-editorial .field-group textarea {
  width: 100%;
  min-height: var(--tap-target);
  padding: 0.625rem 0.25rem;
  font-size: 1rem;
  font-family: inherit;
  color: var(--color-base-content);
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--color-base-300);
  outline: none;
}

/* Checkboxes and radios are small by nature: exempt them from the tap-target
   floor so they aren't stretched. The hit area lives on their wrapping label.
   Also covers the visually-hidden radios behind .guests__chip / .slotpick__chip. */
.form-editorial .field-group input[type="checkbox"],
.form-editorial .field-group input[type="radio"] {
  min-height: 0;
}

/* Boolean fields read as "[tick] Label" on a single line rather than an
   uppercase label stacked above a stretched checkbox. */
.form-editorial .field-group--inline label {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  margin-bottom: 0;
  font-size: 0.9375rem;
  font-weight: 400;
  text-transform: none;
  letter-spacing: normal;
  color: var(--color-base-content);
  cursor: pointer;
}

.form-editorial .field-group--inline input[type="checkbox"] {
  width: auto;
}

.form-editorial .field-group input:hover,
.form-editorial .field-group select:hover,
.form-editorial .field-group textarea:hover {
  border-bottom-color: var(--color-stone);
}

.form-editorial .field-group input:focus,
.form-editorial .field-group select:focus,
.form-editorial .field-group textarea:focus {
  border-bottom: 2px solid var(--color-primary);
  background: oklch(94% 0.008 240 / 0.5);
  padding-bottom: calc(0.625rem - 1px);
}

.form-editorial .field-group input[aria-invalid="true"],
.form-editorial .field-group.has-error input,
.form-editorial .field-group.has-error select,
.form-editorial .field-group.has-error textarea {
  border-bottom: 2px solid var(--color-error);
  padding-bottom: calc(0.625rem - 1px);
}

.form-editorial .field-group input:disabled,
.form-editorial .field-group select:disabled,
.form-editorial .field-group textarea:disabled {
  background: var(--color-base-200);
  cursor: not-allowed;
  color: var(--color-stone);
}

.form-editorial .field-group input:disabled+label,
.form-editorial .field-group:has(input:disabled) label {
  color: var(--color-base-300);
}

.form-editorial .field-group .field-error {
  display: block;
  margin-top: 0.375rem;
  font-size: 0.75rem;
  color: var(--color-error);
}

.form-editorial .field-group textarea {
  resize: vertical;
  min-height: 4rem;
}

.form-editorial .field-group select {
  cursor: pointer;
}


/* === GRADIENT PLACEHOLDERS (for images not yet sourced) === */

.placeholder-ocean {
  background: linear-gradient(180deg, oklch(65% 0.04 230), oklch(38% 0.08 245));
}

.placeholder-moor {
  background: linear-gradient(180deg, oklch(60% 0.03 250), oklch(42% 0.05 310));
}

.placeholder-sand {
  background: linear-gradient(180deg, oklch(92% 0.03 85), oklch(86% 0.012 240));
}

.placeholder-fire {
  background: linear-gradient(180deg, oklch(40% 0.04 30), oklch(30% 0.03 40));
}

.placeholder-stone {
  background: linear-gradient(180deg, oklch(70% 0.01 240), oklch(55% 0.015 250));
}

.placeholder-tweed {
  background: linear-gradient(135deg, oklch(50% 0.04 55), oklch(42% 0.05 170));
}


/* === BOOKING RANGE CALENDAR === */

.cal__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 0.75rem;
}

.cal__title {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-size: 1.0625rem;
}

.cal__nav {
  width: var(--tap-target);
  height: var(--tap-target);
  display: grid;
  place-items: center;
  border-radius: 9999px;
  color: var(--color-base-content);
  cursor: pointer;
  transition: background-color 150ms ease, color 150ms ease, transform 150ms ease;
}

.cal__nav:not(.is-disabled):hover {
  background: var(--color-base-200);
  color: var(--color-primary);
  transform: scale(1.08);
}

.cal__nav:not(.is-disabled):active {
  transform: scale(0.96);
}

.cal__nav:focus-visible {
  outline: 2px solid var(--color-primary);
  outline-offset: 2px;
}

.cal__nav.is-disabled {
  opacity: 0.3;
  cursor: default;
}

@media (prefers-reduced-motion: reduce) {
  .cal__nav {
    transition: background-color 150ms ease, color 150ms ease;
  }

  .cal__nav:not(.is-disabled):hover,
  .cal__nav:not(.is-disabled):active {
    transform: none;
  }
}

.cal__weekdays,
.cal__grid {
  display: grid;
  /* minmax(0, …) not 1fr: 1fr keeps an auto floor, so the day cells' 44px
     min size makes this grid overflow narrow screens while the text-only
     weekday header shrinks to fit, leaving the two rows misaligned. */
  grid-template-columns: repeat(7, minmax(0, 1fr));
}

.cal__weekdays {
  margin-bottom: 0.25rem;
}

.cal__weekdays span {
  text-align: center;
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-stone);
  padding: 0.25rem 0;
}

.cal__day {
  aspect-ratio: 1;
  min-height: var(--tap-target);
  min-width: 0;
  display: grid;
  place-items: center;
  font-size: 1rem;
  border-radius: 0.45rem;
  color: var(--color-base-content);
}

button.cal__day {
  cursor: pointer;
}

button.cal__day:not(.is-start):not(.is-end):hover {
  background: var(--color-base-200);
}

.cal__day--blank {
  visibility: hidden;
}

.cal__day--off {
  color: var(--color-base-300);
  text-decoration: line-through;
  cursor: not-allowed;
}

/* Checkout-only day: greyed like an off day but without the strikethrough bar,
   with a small "Checkout only" hint on hover, focus, or tap. */
.cal__day--checkout {
  position: relative;
  color: var(--color-base-300);
  cursor: help;
}

.cal__day--checkout:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 1px;
}

.cal__day--checkout::after {
  content: attr(data-tip);
  position: absolute;
  bottom: calc(100% + 0.35rem);
  left: 50%;
  transform: translateX(-50%);
  z-index: 10;
  padding: 0.2rem 0.45rem;
  border-radius: 0.3rem;
  background: var(--color-base-content);
  color: var(--color-base-100);
  font-size: 0.7rem;
  line-height: 1;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.12s ease;
}

.cal__day--checkout:hover::after,
.cal__day--checkout:focus::after,
.cal__day--checkout.is-open::after {
  opacity: 1;
}

.cal__day.is-in-range {
  background: color-mix(in oklch, var(--color-accent) 16%, transparent);
  border-radius: 0;
}

.cal__day.is-start,
.cal__day.is-end {
  background: var(--color-accent);
  color: #fff;
}

.cal__day.is-start {
  border-top-right-radius: 0;
  border-bottom-right-radius: 0;
}

.cal__day.is-end {
  border-top-left-radius: 0;
  border-bottom-left-radius: 0;
}

.cal__summary {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  margin-top: 0.75rem;
  text-align: center;
  font-size: 0.85rem;
  color: var(--color-stone);
}

.cal__price {
  color: var(--color-primary);
}

.cal__clear {
  display: flex;
  align-items: center;
  justify-content: center;
  width: fit-content;
  min-height: var(--tap-target);
  margin: 0.5rem auto 0;
  padding: 0 0.75rem;
  background: none;
  border: 0;
  font-size: 0.8rem;
  color: var(--color-stone);
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.cal__clear:hover {
  color: var(--color-base-content);
}


/* === GUEST PICKER === */

.guests {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
}

.guests__quick {
  display: flex;
  gap: 0.5rem;
}

.guests__chip {
  display: inline-grid;
  place-items: center;
}

.guests__chip input,
.form-editorial .field-group .guests__chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.guests__chip span {
  display: inline-grid;
  place-items: center;
  width: var(--tap-target);
  height: var(--tap-target);
  border-radius: 9999px;
  border: 1px solid var(--color-base-300);
  color: var(--color-base-content);
  cursor: pointer;
}

.guests__chip:hover span,
.guests__chip input:focus-visible + span {
  border-color: var(--color-accent);
}

.guests__chip input:checked + span {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

/* Group heading for field-groups that wrap a control cluster (no single input). */
.form-editorial .field-group__label {
  display: block;
  font-size: 0.75rem;
  font-weight: 500;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-stone);
  margin-bottom: 0.375rem;
}


/* === TOUR SLOT PICKER ===
   Per-slot availability for island tours: a guest who has chosen a date picks
   one of the four fixed times, each showing how many of the 4 places remain.
   Two-line chips (a Fraunces time over a small count) reuse the accent-fill
   selection of .guests__chip; full slots borrow the struck-through, inert look
   of .cal__day--off. The participant chips below reuse .guests/.guests__chip. */

.slotpick {
  display: flex;
  flex-direction: column;
  gap: 1.25rem;
}

.slotpick__group {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
}

.slotpick__slots {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(4.75rem, 1fr));
  gap: 0.5rem;
}

.slotpick__chip {
  display: block;
}

.slotpick__chip > span {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.2rem;
  min-height: 3.5rem;
  padding: 0.45rem 0.4rem;
  border: 1px solid var(--color-base-300);
  border-radius: 0.45rem;
  color: var(--color-base-content);
  cursor: pointer;
}

.slotpick__chip input,
.form-editorial .field-group .slotpick__chip input {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  border: 0;
  opacity: 0;
  pointer-events: none;
}

.slotpick__time {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-size: 1.05rem;
  line-height: 1;
  font-variant-numeric: tabular-nums;
}

.slotpick__places {
  font-size: 0.6rem;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-stone);
}

.slotpick__chip:hover > span,
.slotpick__chip input:focus-visible + span {
  border-color: var(--color-accent);
}

.slotpick__chip input:checked + span {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #fff;
}

.slotpick__chip input:checked + span .slotpick__places {
  color: oklch(100% 0 0 / 0.85);
}

/* Full slot — inert and struck through, echoing .cal__day--off. */
.slotpick__chip--full > span {
  cursor: not-allowed;
  color: var(--color-base-300);
}

.slotpick__chip--full .slotpick__time {
  text-decoration: line-through;
}

.slotpick__chip--full .slotpick__places {
  color: var(--color-base-300);
}

.slotpick__hint {
  font-size: 0.8rem;
  color: var(--color-stone);
}


/* === BOOKING ADD-ONS === */

.addons {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
}

.addon {
  border: 1px solid var(--color-base-300);
  border-radius: 0.5rem;
  padding: 0.75rem 1rem;
}

.form-editorial .field-group .addon__head {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  cursor: pointer;
  flex-wrap: wrap;
}

.form-editorial .field-group .addon__head input[type="checkbox"] {
  width: 1rem;
  height: 1rem;
  padding: 0;
  flex: 0 0 auto;
  margin: 0;
}

.addon__name {
  display: flex;
  align-items: center;
  flex: 1 1 8rem;
  font-weight: 500;
  line-height: 1.25;
  min-width: 0;
  overflow-wrap: anywhere;
}

.addon__price {
  display: flex;
  align-items: center;
  flex: 0 1 auto;
  margin-left: auto;
  font-size: 0.85rem;
  line-height: 1.25;
  color: var(--color-stone);
  text-align: right;
  white-space: normal;
  overflow-wrap: anywhere;
}

.addon__fields {
  display: none;
  margin-top: 0.85rem;
}

.addon.is-open .addon__fields {
  display: block;
}

.addon__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0.75rem;
}

@media (max-width: 480px) {
  .addon__grid {
    grid-template-columns: 1fr;
  }
}

.addon__field {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
}

.addon__field--wide {
  grid-column: 1 / -1;
}

.addon__field > span {
  font-size: 0.7rem;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-stone);
}

.form-editorial .addon__field input,
.form-editorial .addon__field select {
  border: none;
  border-bottom: 1px solid var(--color-base-300);
}

.addon__note {
  margin-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--color-accent);
}

.booking-submit-spinner {
  display: none;
}

.btn-primary-editorial.is-loading {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
}

.btn-primary-editorial.is-loading .booking-submit-spinner {
  display: inline-block;
}

.btn-primary-editorial.is-loading .booking-submit-label {
  display: none;
}

.booking-submit-spinner {
  width: 1rem;
  height: 1rem;
  border: 2px solid currentColor;
  border-right-color: transparent;
  border-radius: 9999px;
  animation: booking-submit-spin 0.7s linear infinite;
}

@keyframes booking-submit-spin {
  to {
    transform: rotate(360deg);
  }
}


/* === HTMX LOADING FEEDBACK ===
   htmx adds .htmx-request to the element named by hx-indicator while a request
   is in flight. Dimming and locking the calendar / slot picker keeps a slow
   month change or date pick from looking frozen, and pointer-events stops a
   second tap racing the first. */

.cal,
.slotpick {
  transition: opacity 0.2s ease;
}

.cal.htmx-request,
.slotpick.htmx-request {
  opacity: 0.55;
  pointer-events: none;
  cursor: wait;
}

/* range-calendar.js serialises clicks on live calendars and needs to receive
   them, so re-enable pointer events there once it has loaded (it marks <html>).
   Without the script, the pointer-events:none above still safely drops a racing
   second click. */
html.js-cal-serialized .cal--live.htmx-request {
  pointer-events: auto;
}

/* A form mid-submit (contact, booking) swaps its submit label for the spinner. */
.form-editorial.htmx-request button[type="submit"] {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  cursor: wait;
}

.form-editorial.htmx-request .booking-submit-spinner {
  display: inline-block;
}

.form-editorial.htmx-request .booking-submit-label {
  display: none;
}


/* === COTTAGE GALLERY ===
   A cross-fading carousel that doubles as the entry point to a full-screen
   lightbox. Editorial treatment: hairline controls, a Fraunces plate-number
   counter, and thin tick indicators rather than dots. */

.gallery__frame {
  position: relative;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  border-radius: 0.5rem;
  background: var(--color-base-200);
  /* Let the page scroll vertically while horizontal drags reach the swipe
     handler rather than triggering the browser's own gestures. */
  touch-action: pan-y;
}

.gallery__slide {
  position: absolute;
  inset: 0;
  z-index: 1;
  opacity: 0;
  transition: opacity 600ms ease;
  pointer-events: none;
}

.gallery__slide[data-active] {
  opacity: 1;
}

.gallery__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Transparent hit-area over the photo; sits above the slides but below the
   arrows so the chevrons keep their own clicks. */
.gallery__zoom {
  position: absolute;
  inset: 0;
  z-index: 2;
  cursor: zoom-in;
  border: 0;
  background: transparent;
}

.gallery__zoom-hint {
  position: absolute;
  top: 0.875rem;
  right: 0.875rem;
  z-index: 4;
  display: grid;
  place-items: center;
  width: 2rem;
  height: 2rem;
  color: #fff;
  background: oklch(20% 0.02 250 / 0.35);
  border-radius: 9999px;
  backdrop-filter: blur(2px);
  pointer-events: none;
  opacity: 0.75;
  transition: opacity 200ms ease;
}

.gallery__frame:hover .gallery__zoom-hint {
  opacity: 1;
}

.gallery__nav {
  position: absolute;
  top: 50%;
  z-index: 4;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  color: #fff;
  background: oklch(20% 0.02 250 / 0.3);
  border: 1px solid oklch(100% 0 0 / 0.45);
  border-radius: 9999px;
  backdrop-filter: blur(2px);
  cursor: pointer;
  transition: background 200ms ease, border-color 200ms ease, color 200ms ease;
}

.gallery__nav:hover {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-accent-content);
}

.gallery__nav:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 2px;
}

.gallery__nav--prev {
  left: 0.875rem;
}

.gallery__nav--next {
  right: 0.875rem;
}

.gallery__nav svg {
  width: 1.1rem;
  height: 1.1rem;
}

.gallery__caption-bar {
  position: absolute;
  inset-inline: 0;
  bottom: 0;
  z-index: 3;
  padding: 2.5rem 1rem 1rem;
  background: linear-gradient(to top, oklch(15% 0.02 250 / 0.78), transparent);
  color: #fff;
  pointer-events: none;
}

.gallery__counter {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-size: 0.8rem;
  letter-spacing: 0.16em;
  color: oklch(100% 0 0 / 0.8);
}

.gallery__caption {
  display: block;
  margin-top: 0.15rem;
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: oklch(100% 0 0 / 0.92);
}

.gallery__ticks {
  display: flex;
  gap: 0.375rem;
  margin-top: 0.75rem;
}

.gallery__tick {
  height: 2px;
  width: 1.5rem;
  background: oklch(100% 0 0 / 0.35);
  transition: background 300ms ease;
}

.gallery__tick[data-active] {
  background: var(--color-accent);
}


/* === LIGHTBOX === */

.lightbox {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3.5rem);
  touch-action: pan-y;
}

.lightbox[hidden] {
  display: none;
}

.lightbox__backdrop {
  position: absolute;
  inset: 0;
  background: oklch(16% 0.02 250 / 0.94);
  backdrop-filter: blur(4px);
}

.lightbox__stage {
  position: relative;
  z-index: 1;
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1rem;
  max-width: 100%;
}

.lightbox__img {
  max-width: min(92vw, 1400px);
  max-height: 80vh;
  object-fit: contain;
  border-radius: 0.25rem;
  box-shadow: 0 24px 60px oklch(0% 0 0 / 0.5);
  animation: lightbox-in 320ms cubic-bezier(0.2, 0.7, 0.2, 1);
}

@keyframes lightbox-in {
  from {
    opacity: 0;
    transform: scale(0.96);
  }
}

.lightbox__meta {
  display: flex;
  align-items: baseline;
  gap: 0.875rem;
  color: oklch(100% 0 0 / 0.85);
}

.lightbox__counter {
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-size: 0.85rem;
  letter-spacing: 0.16em;
}

.lightbox__caption {
  font-size: 0.7rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
}

.lightbox__close {
  position: absolute;
  top: clamp(0.75rem, 2vw, 1.5rem);
  right: clamp(0.75rem, 2vw, 1.5rem);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  color: oklch(100% 0 0 / 0.8);
  background: transparent;
  border: 1px solid oklch(100% 0 0 / 0.25);
  border-radius: 9999px;
  cursor: pointer;
  transition: color 200ms ease, border-color 200ms ease;
}

.lightbox__close:hover {
  color: #fff;
  border-color: oklch(100% 0 0 / 0.7);
}

.lightbox__nav {
  position: absolute;
  top: 50%;
  z-index: 2;
  transform: translateY(-50%);
  display: grid;
  place-items: center;
  width: 3.25rem;
  height: 3.25rem;
  color: oklch(100% 0 0 / 0.7);
  background: transparent;
  border: 0;
  cursor: pointer;
  transition: color 200ms ease, transform 200ms ease;
}

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

.lightbox__nav--prev {
  left: clamp(0.5rem, 3vw, 2rem);
}

.lightbox__nav--next {
  right: clamp(0.5rem, 3vw, 2rem);
}

.lightbox__nav--prev:hover {
  transform: translateY(-50%) translateX(-3px);
}

.lightbox__nav--next:hover {
  transform: translateY(-50%) translateX(3px);
}

.lightbox__nav svg {
  width: 1.75rem;
  height: 1.75rem;
}

.lightbox__close:focus-visible,
.lightbox__nav:focus-visible {
  outline: 2px solid var(--color-accent);
  outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
  .gallery__slide {
    transition: none;
  }

  .lightbox__img {
    animation: none;
  }

  .lightbox__nav,
  .lightbox__nav:hover {
    transform: translateY(-50%);
  }
}


/* === HOSTS (Meet your hosts) === */

.host-tile {
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: 0.5rem;
  overflow: hidden;
  background: var(--color-base-200);
  box-shadow: 0 0 0 1px var(--color-base-300);
}

.host-tile__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Shown when a host has no photo yet: their initials woven over the tweed,
   so the empty state reads as a deliberate detail rather than a blank box. */
.host-tile__monogram {
  position: absolute;
  inset: 0;
  z-index: 1;
  display: grid;
  place-items: center;
  font-family: 'Fraunces', ui-serif, Georgia, serif;
  font-weight: 300;
  font-size: clamp(3.5rem, 12vw, 6rem);
  letter-spacing: 0.05em;
  color: var(--color-base-content);
}

.host-eyebrow {
  font-size: 0.75rem;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--tracking-label);
  color: var(--color-accent);
}