/* ==========================================================================
   CALYCANTO — CORE DESIGN SYSTEM
   Load ONCE per site (Elementor → Custom Code, or theme header).
   Everything is namespaced .cal-* / --cal-* so it cannot collide with
   Elementor, Hello/Astra theme styles, or plugin CSS.
   ========================================================================== */

/* The webfonts are NOT imported here on purpose.
   An @import means the browser has to fetch this stylesheet, parse it, THEN
   discover the font sheet, fetch that, and only then fetch the fonts: three
   round trips in a row before a heading can be drawn. The pages link the
   font sheet in <head> instead, alongside this file, so the two download
   together. See build-preview.py and build-clientpreview.py. */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* Brand palette (from the Calycanto brand kit) */
  --cal-teal:        #1f9ebb;
  --cal-teal-deep:   #17788f;   /* AA-safe teal for text on cream */
  --cal-teal-dark:   #0f5b6d;
  --cal-rust:        #ab3e09;
  --cal-rust-soft:   #c4551d;
  --cal-navy:        #284672;
  --cal-butter:      #fffea6;   /* brand kit value — kept for small accents */
  /* The kit yellow is a highlighter at full-section scale. This is the same
     hue pulled down in chroma for large surfaces. */
  --cal-butter-pale: #f7edc0;
  --cal-cream:       #fffcf8;
  --cal-ink:         #2b2323;

  /* Warm neutrals derived from the palette — the "expensive" middle range */
  --cal-sand:        #f5ede2;
  --cal-sand-deep:   #ece0d0;
  --cal-linen:       #faf4ec;
  --cal-ink-soft:    #5f524b;
  --cal-ink-mute:    #8a7d75;
  --cal-hairline:    rgba(43, 35, 35, .13);
  --cal-hairline-lt: rgba(255, 252, 248, .22);

  /* Type */
  --cal-font-display: 'Lora', 'Iowan Old Style', Georgia, serif;
  --cal-font-punch:   'Big Shoulders Display', 'Haettenschweiler', Impact, sans-serif;
  --cal-font-body:    'Mulish', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;

  /* Shape & surface */
  --cal-r:      18px;
  --cal-r-lg:   28px;
  --cal-r-sm:   12px;
  --cal-pill:   999px;

  /* Warm shadows — brown-tinted, never neutral grey */
  --cal-shadow-sm: 0 1px 2px rgba(74, 55, 45, .04), 0 4px 12px -4px rgba(74, 55, 45, .10);
  --cal-shadow:    0 2px 6px rgba(74, 55, 45, .05), 0 18px 40px -14px rgba(74, 55, 45, .18);
  --cal-shadow-lg: 0 4px 10px rgba(74, 55, 45, .06), 0 40px 80px -28px rgba(74, 55, 45, .28);

  /* Rhythm */
  --cal-gutter:  clamp(20px, 5vw, 64px);
  --cal-max:     1280px;
  --cal-max-narrow: 760px;
  --cal-section: clamp(56px, 7.4vw, 112px);

  /* Motion — understated only */
  --cal-ease:  cubic-bezier(.22, .61, .36, 1);
  --cal-ease-out: cubic-bezier(.16, 1, .3, 1);
  --cal-t:     .45s;

  /* Simplified quatrefoil outline, used as the empty-photo placeholder glyph.
     Deliberately the plain silhouette rather than the full filigree mark —
     the detailed version turns to mud at low opacity. */
  --cal-placeholder-mark:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cg fill='none' stroke='%232b2323' stroke-width='3'%3E%3Ccircle cx='50' cy='27' r='23'/%3E%3Ccircle cx='73' cy='50' r='23'/%3E%3Ccircle cx='50' cy='73' r='23'/%3E%3Ccircle cx='27' cy='50' r='23'/%3E%3C/g%3E%3C/svg%3E");

  /* Fine film grain — keeps large flat areas from looking digitally flat */
  --cal-grain:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.82' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)' opacity='.34'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   2. SCOPED RESET
   Applies only inside .cal-scope wrappers, so the theme keeps its own styles.
   -------------------------------------------------------------------------- */
.cal-scope,
.cal-scope * { box-sizing: border-box; }

.cal-scope {
  font-family: var(--cal-font-body);
  font-size: clamp(16px, .55vw + 14.4px, 17.5px);
  line-height: 1.72;
  font-weight: 400;
  color: var(--cal-ink-soft);
  background: var(--cal-cream);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

/* The :where() goes around the TAG, not around the whole selector.
   ------------------------------------------------------------------------
   These were written as `:where(.cal-scope button)`, which is specificity
   (0,0,0). That was to stop the reset bullying component classes like
   `.cal-notes__arrow` (0,1,0), and on a page with nothing else on it that
   worked perfectly.

   It does not survive WordPress. A theme or a plugin only has to ship a bare
   `button { border: 1px solid; border-radius: 0 }` — specificity (0,0,1) —
   and it beats a zero-specificity reset outright. The result was every
   arrow, pill and carousel dot wearing the theme's border and square
   corners instead of ours.

   Writing it as `.cal-scope :where(button)` puts the weight on the wrapper
   instead: specificity (0,1,0). That is high enough to beat any plain tag
   selector a theme throws at it, and exactly level with our own component
   classes, which are further down this file and therefore still win on
   source order. Both problems solved by moving one bracket.

   `appearance: none` is new and deliberate: without it Safari and iOS keep
   their own button chrome no matter what the border says. */
.cal-scope :where(p) { margin: 0 0 1.15em; }
.cal-scope :where(p:last-child) { margin-bottom: 0; }
.cal-scope :where(img),
.cal-scope :where(svg) { max-width: 100%; }
.cal-scope :where(a) { color: inherit; text-decoration: none; }
.cal-scope :where(ul),
.cal-scope :where(ol) { margin: 0; padding: 0; list-style: none; }
.cal-scope :where(button) {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  border-radius: 0;
  margin: 0;
  padding: 0;
  text-transform: none;
  letter-spacing: inherit;
  box-shadow: none;
  -webkit-appearance: none;
          appearance: none;
  cursor: pointer;
}

/* Stray theme hover styles, without flattening our own controls.
   ------------------------------------------------------------------------
   Two earlier attempts at this were wrong in opposite directions.

   The first was `.cal-scope :where(a, button):hover/:focus` at (0,2,0). It
   beat the theme, and it also beat `.cal-btn--primary` at (0,1,0), so every
   button lost its fill the moment it was clicked. "Check dates" turning into
   white-on-white was that.

   The second narrowed it to `.cal-nav`, which fixed the buttons and left the
   whole booking modal unprotected. The pink came back on the accordion
   headers, which are <button>s that paint no background of their own.

   The real distinction is not WHERE the control is, it is whether it paints
   itself. Controls with their own background need no defending; controls
   without one are the ones a foreign `button:hover` can colour in. The list
   below is every class in this stylesheet that sets a background on an
   interactive element, gathered by reading the file rather than by memory,
   so it can be regenerated when a new one is added. */
/* If anything on this site highlights, it highlights in Calycanto's rust.
   The theme underneath wants to paint a raspberry pink on every :hover and
   :focus it can reach; the rules below have taken the backgrounds away from
   it, which left keyboard users with no visible focus at all. An outline is
   the right tool anyway: it does not fight a background, it cannot be the
   wrong colour against one, and it only shows for :focus-visible, so a mouse
   click does not leave a ring behind. */
.cal-scope :where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--cal-rust);
  outline-offset: 2px;
  border-radius: inherit;
}

.cal-scope :where(a, button):not(
    .cal-btn, .cal-scope .cal-btn--ghost, .cal-scope .cal-btn--ink, .cal-scope .cal-btn--light,
    .cal-scope .cal-btn--primary, .cal-scope .cal-btn--rust,
    .cal-scope .cal-cal__navbtn, .cal-scope .cal-carousel__btn,
    .cal-scope .cal-day, .cal-day--booked, .cal-day--in-range, .cal-day--selected,
    .cal-day--today,
    .cal-scope .cal-dot, .cal-scope .cal-gallery-nav,
    .cal-scope .cal-lightbox__close, .cal-scope .cal-lightbox__nav, .cal-scope .cal-link, .cal-scope .cal-modal__close,
    .cal-scope .cal-paybtn--bank, .cal-scope .cal-paybtn--paypal, .cal-scope .cal-paybtn--tilopay,
    .cal-scope .cal-pill, .cal-scope .cal-pill--butter, .cal-scope .cal-pill--ink, .cal-scope .cal-pill--rust,
    .cal-scope .cal-pill--teal,
    .cal-scope .cal-showcase__nav, .cal-scope .cal-stepper__btn
  ):hover,
.cal-scope :where(a, button):not(
    .cal-btn, .cal-scope .cal-btn--ghost, .cal-scope .cal-btn--ink, .cal-scope .cal-btn--light,
    .cal-scope .cal-btn--primary, .cal-scope .cal-btn--rust,
    .cal-scope .cal-cal__navbtn, .cal-scope .cal-carousel__btn,
    .cal-scope .cal-day, .cal-day--booked, .cal-day--in-range, .cal-day--selected,
    .cal-day--today,
    .cal-scope .cal-dot, .cal-scope .cal-gallery-nav,
    .cal-scope .cal-lightbox__close, .cal-scope .cal-lightbox__nav, .cal-scope .cal-link, .cal-scope .cal-modal__close,
    .cal-scope .cal-paybtn--bank, .cal-scope .cal-paybtn--paypal, .cal-scope .cal-paybtn--tilopay,
    .cal-scope .cal-pill, .cal-scope .cal-pill--butter, .cal-scope .cal-pill--ink, .cal-scope .cal-pill--rust,
    .cal-scope .cal-pill--teal,
    .cal-scope .cal-showcase__nav, .cal-scope .cal-stepper__btn
  ):focus,
.cal-scope :where(a, button):not(
    .cal-btn, .cal-scope .cal-btn--ghost, .cal-scope .cal-btn--ink, .cal-scope .cal-btn--light,
    .cal-scope .cal-btn--primary, .cal-scope .cal-btn--rust,
    .cal-scope .cal-cal__navbtn, .cal-scope .cal-carousel__btn,
    .cal-scope .cal-day, .cal-day--booked, .cal-day--in-range, .cal-day--selected,
    .cal-day--today,
    .cal-scope .cal-dot, .cal-scope .cal-gallery-nav,
    .cal-scope .cal-lightbox__close, .cal-scope .cal-lightbox__nav, .cal-scope .cal-link, .cal-scope .cal-modal__close,
    .cal-scope .cal-paybtn--bank, .cal-scope .cal-paybtn--paypal, .cal-scope .cal-paybtn--tilopay,
    .cal-scope .cal-pill, .cal-scope .cal-pill--butter, .cal-scope .cal-pill--ink, .cal-scope .cal-pill--rust,
    .cal-scope .cal-pill--teal,
    .cal-scope .cal-showcase__nav, .cal-scope .cal-stepper__btn
  ):active{ background: none; }

/* --------------------------------------------------------------------------
   3. LAYOUT
   -------------------------------------------------------------------------- */
.cal-section { position: relative; padding: var(--cal-section) 0; overflow: hidden; }
.cal-section--flush  { padding: 0; }
.cal-section--tight  { padding: clamp(52px, 7vw, 104px) 0; }

.cal-wrap {
  width: 100%;
  max-width: calc(var(--cal-max) + var(--cal-gutter) * 2);
  margin-inline: auto;
  padding-inline: var(--cal-gutter);
  position: relative;
  z-index: 1;
}
.cal-wrap--narrow { max-width: calc(var(--cal-max-narrow) + var(--cal-gutter) * 2); }
.cal-wrap--wide   { max-width: 1560px; }

/* Surfaces */
.cal-bg-cream  { background: var(--cal-cream); }
.cal-bg-linen  { background: var(--cal-linen); }
.cal-bg-sand   { background: var(--cal-sand); }
.cal-bg-butter { background: var(--cal-butter-pale); }
.cal-bg-ink    { background: var(--cal-ink); }

/* Dark + butter sections invert the text colour scale */
.cal-bg-ink { color: rgba(255, 252, 248, .78); }
.cal-bg-ink .cal-display,
.cal-bg-ink .cal-h2,
.cal-bg-ink .cal-h3 { color: var(--cal-cream); }
.cal-bg-ink .cal-eyebrow { color: var(--cal-butter); }

.cal-bg-butter { color: #4a3a10; }
.cal-bg-butter .cal-display,
.cal-bg-butter .cal-h2,
.cal-bg-butter .cal-h3 { color: #38290a; }
.cal-bg-butter .cal-eyebrow { color: var(--cal-rust); }

/* --------------------------------------------------------------------------
   4. TYPE SCALE
   -------------------------------------------------------------------------- */
.cal-display,
.cal-h2, .cal-h3, .cal-h4 {
  font-family: var(--cal-font-display);
  color: var(--cal-ink);
  font-weight: 500;
  margin: 0;
  text-wrap: balance;
}

/* Hero — the one place the serif goes truly large */
.cal-display {
  font-size: clamp(3rem, 7.2vw, 6.6rem);
  line-height: .98;
  letter-spacing: -.022em;
  font-weight: 400;
}
.cal-h2 {
  font-size: clamp(1.85rem, 3.5vw, 2.9rem);
  line-height: 1.1;
  letter-spacing: -.018em;
}
.cal-h3 {
  font-size: clamp(1.4rem, 2vw, 1.85rem);
  line-height: 1.18;
  letter-spacing: -.012em;
}
.cal-h4 {
  font-family: var(--cal-font-body);
  font-size: 1.0625rem;
  font-weight: 700;
  line-height: 1.35;
  letter-spacing: -.005em;
  color: var(--cal-ink);
}

/* Eyebrow — Big Shoulders, wide-tracked, always paired with the mark */
.cal-eyebrow {
  font-family: var(--cal-font-punch);
  font-size: clamp(1.02rem, 1.35vw, 1.4rem);
  font-weight: 600;
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--cal-teal-deep);
  margin: 0 0 1.15rem;
  display: flex;
  align-items: center;
  gap: .6em;
  line-height: 1;
}
.cal-eyebrow--center { justify-content: center; }
/* Any bare <svg> dropped in an eyebrow gets sized — an unsized inline SVG
   defaults to filling its container, which is a spectacular failure mode. */
/* Sized in em so the mark always scales with whatever eyebrow it sits in. */
.cal-eyebrow > svg {
  width: 1.5em;
  height: 1.5em;
  flex: none;
  opacity: .9;
}

.cal-lead {
  font-size: clamp(1.05rem, 1.35vw, 1.24rem);
  line-height: 1.65;
  color: var(--cal-ink-soft);
  max-width: 56ch;
}
.cal-lead--center { margin-inline: auto; }

.cal-small {
  font-size: .875rem;
  line-height: 1.6;
  color: var(--cal-ink-mute);
}

/* Big Shoulders utility for punchy numerals / labels */
.cal-punch {
  font-family: var(--cal-font-punch);
  font-weight: 700;
  letter-spacing: .01em;
  line-height: .9;
  color: var(--cal-ink);
}

.cal-serif-italic { font-family: var(--cal-font-display); font-style: italic; font-weight: 400; }

/* --------------------------------------------------------------------------
   5. THE MARK — brand motif as a system
   The quatrefoil lives once in the page as an SVG <symbol> sprite; everything
   below just <use>s it, so it tints with currentColor at any size.
   -------------------------------------------------------------------------- */
.cal-brand-sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

.cal-mark { display: block; width: 100%; height: auto; color: inherit; }
.cal-mark-xs { width: 1.5em; height: 1.5em; opacity: .8; }
.cal-mark-sm { width: 18px; height: 18px; }
.cal-mark-md { width: 34px; height: 34px; }

/* Giant faded watermark, anchored to a section corner */
.cal-watermark {
  position: absolute;
  pointer-events: none;
  color: var(--cal-ink);
  opacity: .035;
  width: clamp(280px, 40vw, 620px);
  aspect-ratio: 1;
  z-index: 0;
}
.cal-watermark--tr { top: -12%; right: -8%; transform: rotate(14deg); }
.cal-watermark--bl { bottom: -16%; left: -10%; transform: rotate(-9deg); }
.cal-watermark--br { bottom: -18%; right: -9%; transform: rotate(22deg); }
.cal-watermark--tl { top: -14%; left: -9%; transform: rotate(-16deg); }

/* Anchored part-way down instead of to a corner.
   The four corner variants are all a long section gets, and on a tall one
   that means the mark sits at the very top and the rest of the section has
   nothing. These take a percentage so a section can place one wherever it
   has room: style="--cal-wm-top: 62%". */
.cal-watermark--l { left: -10%; top: var(--cal-wm-top, 42%); transform: rotate(-9deg); }
.cal-watermark--r { right: -8%; top: var(--cal-wm-top, 42%); transform: rotate(14deg); }
.cal-bg-ink .cal-watermark   { color: var(--cal-butter); opacity: .05; }
.cal-bg-butter .cal-watermark { color: var(--cal-rust); opacity: .07; }

/* Repeating motif tile — textural, never literal */
.cal-motif-field {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: .028;
  color: var(--cal-ink);
  z-index: 0;
}
/* On the dark sections the mark reads much hotter — pull it back further, or
   it stops being texture and becomes wallpaper. */
.cal-bg-ink .cal-motif-field { color: var(--cal-butter); opacity: .022; }

/* Hairline divider with the mark set into it */
.cal-rule {
  display: flex;
  align-items: center;
  gap: 14px;
  color: var(--cal-ink-mute);
}
.cal-rule::before,
.cal-rule::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--cal-hairline);
}
.cal-rule .cal-mark-sm { opacity: .5; flex: none; }
.cal-bg-ink .cal-rule::before,
.cal-bg-ink .cal-rule::after { background: var(--cal-hairline-lt); }

/* Mark as a list bullet */
.cal-list { display: grid; gap: .7rem; }
.cal-list li {
  display: grid;
  grid-template-columns: 15px 1fr;
  gap: .8rem;
  align-items: start;
}
.cal-list li > svg { width: 11px; height: 11px; margin-top: .52em; color: var(--cal-teal); opacity: .8; }

/* --------------------------------------------------------------------------
   6. BUTTONS & PILLS
   -------------------------------------------------------------------------- */
.cal-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  padding: 1.02em 2.05em;
  border-radius: var(--cal-pill);
  font-family: var(--cal-font-body);
  font-size: .975rem;
  font-weight: 600;
  letter-spacing: .004em;
  line-height: 1;
  text-align: center;
  cursor: pointer;
  border: 1px solid transparent;
  transition: transform var(--cal-t) var(--cal-ease),
              box-shadow var(--cal-t) var(--cal-ease),
              background-color var(--cal-t) var(--cal-ease),
              color var(--cal-t) var(--cal-ease),
              border-color var(--cal-t) var(--cal-ease);
  will-change: transform;
}
.cal-btn:hover { transform: scale(1.032); }
.cal-btn:active { transform: scale(.995); }
.cal-btn:focus-visible { outline: 2px solid var(--cal-teal); outline-offset: 3px; }

.cal-scope .cal-btn--primary{ background: var(--cal-teal); color: #fff; box-shadow: 0 10px 26px -12px rgba(31,158,187,.7); }
.cal-scope .cal-btn--primary:hover{ background: var(--cal-teal-dark); box-shadow: 0 16px 34px -12px rgba(31,158,187,.62); }

.cal-scope .cal-btn--rust{ background: var(--cal-rust); color: #fff; box-shadow: 0 10px 26px -12px rgba(171,62,9,.66); }
.cal-scope .cal-btn--rust:hover{ background: #8f3207; }

.cal-scope .cal-btn--ink{ background: var(--cal-ink); color: var(--cal-cream); }
.cal-scope .cal-btn--ink:hover{ background: #1b1515; }

.cal-scope .cal-btn--ghost{ border-color: var(--cal-hairline); color: var(--cal-ink); background: transparent; }
.cal-scope .cal-btn--ghost:hover{ border-color: var(--cal-ink); background: rgba(43,35,35,.03); }

.cal-scope .cal-btn--light{ background: transparent; color: #fff; border-color: rgba(255,255,255,.55); }
.cal-scope .cal-btn--light:hover{ background: var(--cal-cream); color: var(--cal-ink); border-color: var(--cal-cream); }

.cal-btn--sm { padding: .78em 1.5em; font-size: .875rem; }

/* Micro pill — secondary "discover" actions. Small caps in the condensed
   display face reads more considered than a shrunken body-text button, and
   never wraps to a second line. */
.cal-btn--micro {
  padding: .72em 1.3em;
  gap: .5em;
  font-family: var(--cal-font-punch);
  font-size: .88rem;
  font-weight: 600;
  letter-spacing: .15em;
  text-transform: uppercase;
  white-space: nowrap;
}
.cal-btn--micro svg.cal-arrow { width: 11px; height: 11px; }

/* Text link with a rule that draws in on hover */
.cal-link {
  display: inline-flex;
  align-items: center;
  gap: .55em;
  font-weight: 600;
  font-size: .975rem;
  color: var(--cal-ink);
  position: relative;
  padding-bottom: 3px;
}
.cal-scope .cal-link::after{
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--cal-t) var(--cal-ease);
}
.cal-link:hover::after { transform: scaleX(1); }
/* Sized on the class itself. Scoped only to .cal-link, this arrow rendered at
   60x60 inside a .cal-btn and blew the button out to 84px tall. */
.cal-arrow {
  width: 15px;
  height: 15px;
  flex: none;
  transition: transform var(--cal-t) var(--cal-ease);
}
.cal-link:hover svg.cal-arrow,
.cal-btn:hover svg.cal-arrow { transform: translateX(3px); }
.cal-link--teal { color: var(--cal-teal-deep); }

/* Pill tags / sub-option bubbles */
.cal-pills { display: flex; flex-wrap: wrap; gap: .5rem; }
.cal-scope .cal-pill{
  display: inline-flex;
  align-items: center;
  gap: .45em;
  padding: .5em 1.05em;
  border-radius: var(--cal-pill);
  background: var(--cal-sand);
  color: var(--cal-ink);
  font-size: .85rem;
  font-weight: 600;
  letter-spacing: .002em;
  line-height: 1.3;
  border: 1px solid transparent;
  transition: background-color var(--cal-t) var(--cal-ease),
              transform var(--cal-t) var(--cal-ease),
              border-color var(--cal-t) var(--cal-ease);
}
.cal-scope a.cal-pill:hover, .cal-scope button.cal-pill:hover{ background: var(--cal-sand-deep); transform: translateY(-2px); }
.cal-scope .cal-pill--teal{ background: rgba(31,158,187,.13); color: var(--cal-teal-dark); }
.cal-scope .cal-pill--rust{ background: rgba(171,62,9,.10);  color: var(--cal-rust); }
.cal-scope .cal-pill--ink{ background: var(--cal-ink); color: var(--cal-cream); }
.cal-scope .cal-pill--butter{ background: var(--cal-butter); color: #4a3a10; }
.cal-pill--outline { background: transparent; border-color: var(--cal-hairline); }

/* --------------------------------------------------------------------------
   7. IMAGE SYSTEM
   Every photo slot is a fixed-ratio frame. With no photo yet it renders a warm
   branded placeholder; dropping a real image in never changes the layout.
   -------------------------------------------------------------------------- */
.cal-img {
  position: relative;
  display: block;
  margin: 0;
  overflow: hidden;
  border-radius: var(--cal-r);
  background:
    radial-gradient(120% 100% at 30% 0%, var(--cal-linen) 0%, var(--cal-sand) 55%, var(--cal-sand-deep) 100%);
  aspect-ratio: var(--cal-ar, 3 / 2);
  isolation: isolate;
}
.cal-img > img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--cal-focal, center);
  display: block;
  z-index: 1;
  transition: transform 1.1s var(--cal-ease-out);
}
/* placeholder glyph — only visible while the slot is empty */
.cal-img::after {
  content: '';
  position: absolute;
  inset: 0;
  background-image: var(--cal-placeholder-mark);
  background-repeat: no-repeat;
  background-position: center;
  background-size: 22% auto;
  opacity: .16;
  z-index: 0;
}
.cal-img.is-filled::after { display: none; }
.cal-img[data-cal-caption]::before {
  content: attr(data-cal-caption);
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, 2.6em);
  z-index: 0;
  font-family: var(--cal-font-punch);
  font-size: .72rem;
  font-weight: 600;
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--cal-ink-mute);
  white-space: nowrap;
}
.cal-img.is-filled[data-cal-caption]::before { display: none; }

/* Ratios */
.cal-img--1x1  { --cal-ar: 1 / 1; }
.cal-img--4x3  { --cal-ar: 4 / 3; }
.cal-img--3x2  { --cal-ar: 3 / 2; }
.cal-img--16x9 { --cal-ar: 16 / 9; }
.cal-img--21x9 { --cal-ar: 21 / 9; }
.cal-img--4x5  { --cal-ar: 4 / 5; }
.cal-img--3x4  { --cal-ar: 3 / 4; }
.cal-img--2x3  { --cal-ar: 2 / 3; }
.cal-img--tall { --cal-ar: 9 / 16; }

.cal-img--square-edge { border-radius: 0; }

/* Butter-yellow duotone wash — the brand's photo-overlay accent */
.cal-img--wash::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 2;
  background: linear-gradient(200deg, rgba(255,254,166,.30) 0%, rgba(255,254,166,0) 58%);
  mix-blend-mode: multiply;
  pointer-events: none;
}

.cal-zoom:hover .cal-img > img,
.cal-img.cal-zoom:hover > img { transform: scale(1.055); }

/* --------------------------------------------------------------------------
   8. CARDS
   -------------------------------------------------------------------------- */
.cal-card {
  position: relative;
  background: var(--cal-cream);
  border-radius: var(--cal-r-lg);
  box-shadow: var(--cal-shadow);
  overflow: hidden;
  display: flex;
  flex-direction: column;
  transition: transform var(--cal-t) var(--cal-ease), box-shadow var(--cal-t) var(--cal-ease);
}
.cal-card:hover { transform: translateY(-6px); box-shadow: var(--cal-shadow-lg); }
.cal-card__body { padding: clamp(24px, 2.6vw, 40px); display: flex; flex-direction: column; gap: 1rem; flex: 1; }
.cal-card__body > :last-child { margin-top: auto; }
.cal-card--flat { box-shadow: none; border: 1px solid var(--cal-hairline); }
.cal-card--flat:hover { box-shadow: var(--cal-shadow); }

/* --------------------------------------------------------------------------
   9. MARQUEE
   Duplicated track, transform-driven, gap-safe. Pauses on hover and honours
   reduced-motion.
   -------------------------------------------------------------------------- */
.cal-marquee {
  position: relative;
  overflow: hidden;
  width: 100%;
  --cal-marquee-dur: 42s;
}
.cal-marquee__track {
  display: flex;
  width: max-content;
  will-change: transform;
  animation: cal-marquee-scroll var(--cal-marquee-dur) linear infinite;
}
.cal-marquee--reverse .cal-marquee__track { animation-direction: reverse; }
.cal-marquee:hover .cal-marquee__track { animation-play-state: paused; }
.cal-marquee__group { display: flex; align-items: center; flex: none; }

@keyframes cal-marquee-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* Soft edge fade so items don't hard-cut at the viewport edge */
.cal-marquee--fade {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}

/* Value-prop marquee item: thin dividers, no numbers */
.cal-vprop {
  display: flex;
  align-items: center;
  gap: clamp(18px, 2.4vw, 34px);
  padding: 0 clamp(22px, 3vw, 44px);
  border-left: 1px solid var(--cal-hairline);
  white-space: nowrap;
}
/* Scales with the item so it reads as a full-height brand element, not a bullet. */
.cal-vprop__mark { width: clamp(46px, 5.2vw, 66px); height: clamp(46px, 5.2vw, 66px);
  color: var(--cal-teal); opacity: .8; flex: none; }
.cal-vprop__title {
  font-family: var(--cal-font-punch);
  font-size: clamp(1.35rem, 2.1vw, 1.95rem);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  color: var(--cal-ink);
  line-height: 1;
}
.cal-vprop__note { font-size: .9rem; color: var(--cal-ink-mute); }

/* --------------------------------------------------------------------------
   10. SCROLL REVEAL — fades and translation only, no bounce
   -------------------------------------------------------------------------- */
.cal-reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity .85s var(--cal-ease-out), transform .85s var(--cal-ease-out);
  transition-delay: var(--cal-delay, 0ms);
}
.cal-reveal.is-in { opacity: 1; transform: none; }

/* --------------------------------------------------------------------------
   11. FORM CONTROLS
   -------------------------------------------------------------------------- */
.cal-field { display: grid; gap: .45rem; }
.cal-label {
  font-family: var(--cal-font-punch);
  font-size: .78rem;
  font-weight: 600;
  letter-spacing: .17em;
  text-transform: uppercase;
  color: var(--cal-ink-mute);
}
.cal-input,
.cal-select,
.cal-textarea {
  font-family: var(--cal-font-body);
  font-size: 1rem;
  color: var(--cal-ink);
  background: var(--cal-cream);
  border: 1px solid var(--cal-hairline);
  border-radius: var(--cal-r-sm);
  padding: .92em 1.05em;
  width: 100%;
  transition: border-color var(--cal-t) var(--cal-ease), box-shadow var(--cal-t) var(--cal-ease);
}
.cal-input:focus,
.cal-select:focus,
.cal-textarea:focus {
  outline: none;
  border-color: var(--cal-teal);
  box-shadow: 0 0 0 3px rgba(31,158,187,.16);
}
.cal-textarea { min-height: 130px; resize: vertical; }

/* --------------------------------------------------------------------------
   12. UTILITIES
   -------------------------------------------------------------------------- */
.cal-center { text-align: center; }
.cal-center .cal-lead { margin-inline: auto; }
.cal-stack   { display: grid; gap: 1.5rem; }
.cal-stack-sm { display: grid; gap: .75rem; }
.cal-actions { display: flex; flex-wrap: wrap; gap: .8rem; align-items: center; }
.cal-actions--center { justify-content: center; }
.cal-mt-lg { margin-top: clamp(40px, 5vw, 72px); }
.cal-sr {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.cal-hide { display: none !important; }
.cal-grain::before {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 2;
  opacity: .5;
  background-image: var(--cal-grain);
  mix-blend-mode: soft-light;
}

/* Two-column editorial split, deliberately asymmetric */
.cal-split {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  gap: clamp(32px, 5.5vw, 96px);
  align-items: center;
}
.cal-split--reverse > :first-child { order: 2; }
.cal-split--offset > :last-child { padding-top: clamp(0px, 4vw, 56px); }

@media (max-width: 860px) {
  .cal-split { grid-template-columns: 1fr; }
  .cal-split--reverse > :first-child { order: 0; }
  .cal-split--offset > :last-child { padding-top: 0; }
}

/* --------------------------------------------------------------------------
   13. REDUCED MOTION
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .cal-scope *,
  .cal-scope *::before,
  .cal-scope *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .cal-reveal { opacity: 1; transform: none; }
  .cal-marquee__track { animation: none; }
}

/* ==========================================================================
   14. SHARED PAGE COMPONENTS
   Used by more than one page, so they live in the design system rather than
   being copy-pasted into six section files.
   ========================================================================== */

/* --- Interior page hero (every page except Home) ------------------------ */
.cal-phero {
  position: relative;
  min-height: clamp(340px, 48vh, 500px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--cal-ink);
  isolation: isolate;
}
.cal-phero__media { position: absolute; inset: 0; z-index: 0; }
.cal-phero__media .cal-img { width: 100%; height: 100%; border-radius: 0; aspect-ratio: auto; }
.cal-phero__media .cal-img:not(.is-filled) {
  background: radial-gradient(130% 110% at 26% 8%, #35564e 0%, #23393a 46%, #1a2528 100%);
}
.cal-phero__media .cal-img:not(.is-filled)::after { filter: invert(1); opacity: .08; background-size: 190px auto; }
.cal-phero__media .cal-img[data-cal-caption]::before { color: rgba(255,255,255,.32); left: auto; right: 5%; top: 14%; transform: none; }

.cal-phero__scrim {
  position: absolute; inset: 0; z-index: 1;
  /* Lighter than the Home hero — these photos carry less type over them, and
     the property should stay readable through the scrim. */
  background:
    linear-gradient(to right, rgba(20,14,12,.46) 0%, rgba(20,14,12,.22) 34%, rgba(20,14,12,0) 66%),
    linear-gradient(to top, rgba(24,17,15,.70) 0%, rgba(24,17,15,.28) 44%, rgba(24,17,15,.04) 70%, rgba(24,17,15,.26) 100%);
}
.cal-phero__inner {
  position: relative; z-index: 2;
  width: 100%;
  max-width: calc(var(--cal-max) + var(--cal-gutter) * 2);
  margin-inline: auto;
  padding: 0 var(--cal-gutter) clamp(26px, 3.4vw, 46px);
  color: #fff;
}
.cal-phero .cal-eyebrow { color: rgba(255,255,255,.88); }
.cal-phero__title {
  font-family: var(--cal-font-display);
  font-weight: 400;
  font-size: clamp(2rem, min(4.6vw, 6.6vh), 3.7rem);
  line-height: 1.04;
  letter-spacing: -.024em;
  color: #fff;
  margin: 0;
  max-width: 16ch;
}
.cal-phero__sub {
  margin: 1.15rem 0 0;
  font-size: clamp(1rem, 1.3vw, 1.18rem);
  line-height: 1.6;
  color: rgba(255,255,255,.88);
  max-width: 48ch;
}
.cal-phero__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: .55rem;
  margin-top: 1.6rem;
}
.cal-scope .cal-phero__meta .cal-pill{
  background: rgba(255,255,255,.14);
  color: #fff;
  border-color: rgba(255,255,255,.30);
  backdrop-filter: blur(6px);
}

/* --- Section header ------------------------------------------------------ */
.cal-secthead { margin-bottom: clamp(26px, 3.4vw, 46px); max-width: 44ch; }
.cal-secthead--center { margin-inline: auto; text-align: center; }
.cal-secthead--center .cal-lead { margin-inline: auto; }
.cal-secthead .cal-lead { margin-top: 1.15rem; }
.cal-secthead--split {
  max-width: none;
  display: flex; align-items: flex-end; justify-content: space-between;
  gap: 2rem; flex-wrap: wrap;
}
.cal-secthead--split > div:first-child { max-width: 40ch; }

/* --- Spec row (bedrooms / beds / baths / guests) -------------------------- */
.cal-specs {
  display: flex;
  flex-wrap: wrap;
  gap: 0;
  border-top: 1px solid var(--cal-hairline);
  border-bottom: 1px solid var(--cal-hairline);
  margin: 1.6rem 0;
}
.cal-spec {
  flex: 1 1 auto;
  min-width: 108px;
  padding: 1.05rem 1.25rem 1.05rem 0;
  display: grid;
  gap: .1rem;
}
.cal-spec + .cal-spec { padding-left: 1.25rem; border-left: 1px solid var(--cal-hairline); }
.cal-spec__num {
  font-family: var(--cal-font-punch);
  font-size: 1.65rem;
  font-weight: 700;
  line-height: 1;
  color: var(--cal-ink);
  letter-spacing: .01em;
}
.cal-spec__label {
  font-size: .8rem;
  letter-spacing: .04em;
  color: var(--cal-ink-mute);
}
.cal-bg-ink .cal-specs { border-color: var(--cal-hairline-lt); }
.cal-bg-ink .cal-spec + .cal-spec { border-left-color: var(--cal-hairline-lt); }
.cal-bg-ink .cal-spec__num { color: var(--cal-cream); }

/* --- Gallery grid --------------------------------------------------------- */
.cal-gallery { display: grid; gap: clamp(10px, 1.2vw, 18px); }
.cal-gallery--3 { grid-template-columns: repeat(3, 1fr); }
.cal-gallery--2 { grid-template-columns: repeat(2, 1fr); }
/* One tall lead image plus a stacked pair — the editorial default */
.cal-gallery--lead {
  grid-template-columns: 1.35fr 1fr;
  grid-template-rows: 1fr 1fr;
}
.cal-gallery--lead > :first-child { grid-row: 1 / 3; }
.cal-gallery--lead > :first-child .cal-img { height: 100%; aspect-ratio: auto; }
@media (max-width: 760px) {
  .cal-gallery--3, .cal-gallery--lead { grid-template-columns: 1fr 1fr; grid-template-rows: auto; }
  .cal-gallery--lead > :first-child { grid-row: auto; grid-column: 1 / -1; }
  .cal-gallery--lead > :first-child .cal-img { aspect-ratio: 3 / 2; }
}

/* --- Photo carousel (Booking cards) --------------------------------------- */
.cal-carousel { position: relative; border-radius: var(--cal-r); overflow: hidden; }
.cal-carousel__track { display: grid; }
.cal-carousel__slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity .55s var(--cal-ease), visibility .55s;
}
.cal-carousel__slide.is-active { opacity: 1; visibility: visible; }
.cal-carousel__slide .cal-img { border-radius: var(--cal-r); }

.cal-scope .cal-carousel__btn{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 4;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  border-radius: var(--cal-pill);
  background: rgba(255, 252, 248, .92);
  color: var(--cal-ink);
  box-shadow: var(--cal-shadow-sm);
  opacity: 0;
  transition: opacity .35s var(--cal-ease), transform .35s var(--cal-ease), background-color .35s var(--cal-ease);
}
.cal-carousel:hover .cal-carousel__btn,
.cal-carousel__btn:focus-visible { opacity: 1; }
.cal-scope .cal-carousel__btn:hover{ background: #fff; transform: translateY(-50%) scale(1.08); }
.cal-carousel__btn--prev { left: 12px; }
.cal-carousel__btn--next { right: 12px; }
.cal-carousel__btn svg { width: 14px; height: 14px; }

.cal-carousel__dots {
  position: absolute;
  left: 0; right: 0; bottom: 12px;
  z-index: 4;
  display: flex;
  justify-content: center;
  gap: .45rem;
  color: #fff;
}
.cal-carousel__dots .cal-dot { box-shadow: 0 1px 3px rgba(0,0,0,.35); }
.cal-carousel__count {
  position: absolute;
  top: 12px; right: 12px;
  z-index: 4;
  padding: .2em .65em;
  border-radius: var(--cal-pill);
  background: rgba(24,17,15,.55);
  backdrop-filter: blur(6px);
  color: #fff;
  font-family: var(--cal-font-punch);
  font-size: .68rem;
  font-weight: 600;
  letter-spacing: .1em;
}

/* --- Prose (Blog post / About long-form) ---------------------------------- */
.cal-prose { max-width: 68ch; }
.cal-prose > * + * { margin-top: 1.15em; }
.cal-prose h2 {
  font-family: var(--cal-font-display);
  font-size: clamp(1.6rem, 2.6vw, 2.15rem);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: -.016em;
  color: var(--cal-ink);
  margin-top: 2.1em;
}
.cal-prose h3 {
  font-family: var(--cal-font-body);
  font-size: 1.1rem;
  font-weight: 700;
  color: var(--cal-ink);
  margin-top: 1.9em;
}
.cal-prose blockquote {
  margin: 2em 0;
  padding-left: 1.5rem;
  border-left: 2px solid var(--cal-teal);
  font-family: var(--cal-font-display);
  font-style: italic;
  font-size: 1.25rem;
  line-height: 1.5;
  color: var(--cal-ink);
}
.cal-prose figure { margin: 2.2em 0; }
.cal-prose figcaption { margin-top: .7rem; font-size: .84rem; color: var(--cal-ink-mute); }
.cal-prose ul { display: grid; gap: .6rem; padding-left: 0; }
.cal-prose ul li { display: grid; grid-template-columns: 14px 1fr; gap: .8rem; align-items: start; }
.cal-prose ul li::before {
  content: '';
  width: 6px; height: 6px;
  margin-top: .68em;
  border-radius: 50%;
  background: var(--cal-teal);
  opacity: .7;
}

/* ==========================================================================
   15. PROPERTY GALLERY
   Arrows on both sides, a variation badge, and pills that select a variation.
   Behaviour lives in calycanto-core.js §9b.
   ========================================================================== */
.cal-gallery-stage {
  position: relative;
  border-radius: var(--cal-r-lg);
  overflow: hidden;
  display: grid;
  background: var(--cal-sand);
}
.cal-gallery-slide {
  grid-area: 1 / 1;
  opacity: 0;
  visibility: hidden;
  transition: opacity .5s var(--cal-ease), visibility .5s;
}
.cal-gallery-slide.is-active { opacity: 1; visibility: visible; }
.cal-gallery-slide .cal-img { border-radius: var(--cal-r-lg); }

/* Arrows — always visible, one on each side */
.cal-scope .cal-gallery-nav{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 5;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border-radius: var(--cal-pill);
  background: rgba(255, 252, 248, .9);
  color: var(--cal-ink);
  box-shadow: var(--cal-shadow-sm);
  backdrop-filter: blur(8px);
  transition: background-color var(--cal-t) var(--cal-ease),
              transform var(--cal-t) var(--cal-ease);
}
.cal-scope .cal-gallery-nav:hover{ background: #fff; transform: translateY(-50%) scale(1.09); }
.cal-gallery-nav:focus-visible { outline: 2px solid var(--cal-teal); outline-offset: 3px; }
.cal-gallery-nav--prev { left: 14px; }
.cal-gallery-nav--next { right: 14px; }
.cal-gallery-nav svg { width: 16px; height: 16px; }

/* Variation badge, top right */
.cal-gallery-badge {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 5;
  padding: .5em 1.05em;
  border-radius: var(--cal-pill);
  background: rgba(43, 35, 35, .72);
  backdrop-filter: blur(8px);
  color: var(--cal-cream);
  font-family: var(--cal-font-punch);
  font-size: .84rem;
  font-weight: 600;
  letter-spacing: .14em;
  text-transform: uppercase;
  line-height: 1.3;
  white-space: nowrap;
}

.cal-gallery-count {
  position: absolute;
  left: 16px;
  bottom: 16px;
  z-index: 5;
  padding: .3em .8em;
  border-radius: var(--cal-pill);
  background: rgba(43, 35, 35, .55);
  backdrop-filter: blur(6px);
  color: #fff;
  font-family: var(--cal-font-punch);
  font-size: .74rem;
  font-weight: 600;
  letter-spacing: .12em;
}

/* Selected variation pill */
.cal-scope .cal-pill.is-selected{
  background: var(--cal-teal);
  color: #fff;
  border-color: var(--cal-teal);
}
.cal-scope .cal-pill.is-selected:hover{ background: var(--cal-teal-dark); }

/* ==========================================================================
   16. PROPERTY DETAIL LAYOUT
   A photo stack (one wide lead over two halves) beside a text column that is
   pinned to the same height, so the copy runs title-to-button exactly against
   the photo block. Horizontal photography sits far better this way than in the
   old tall lead-and-column grid.
   ========================================================================== */
.cal-detail {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.12fr);
  gap: clamp(28px, 4vw, 68px);
  align-items: stretch;            /* both columns share a height */
}
.cal-detail--reverse > :first-child { order: 2; }

/* Text runs from the top of the photo block to its bottom edge. */
.cal-detail__body {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  min-width: 0;
}
.cal-detail__body > :last-child { margin-top: auto; padding-top: 1.2rem; }

/* Tighter type so the column can actually match the photo height. */
.cal-detail__body .cal-h2 { font-size: clamp(1.75rem, 2.9vw, 2.5rem); }
.cal-detail__body .cal-specs { margin: 1.1rem 0; }
.cal-detail__body .cal-spec { padding-block: .8rem; }
.cal-detail__body .cal-spec__num { font-size: 1.4rem; }
.cal-detail__body .cal-spec__label { font-size: .76rem; }
.cal-detail__body .cal-list { gap: .5rem; font-size: .95rem; }
.cal-detail__body .cal-list li > svg { margin-top: .48em; }

/* Photo stack: one wide image, two below it. */
.cal-stack {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(8px, 1vw, 14px);
  align-content: start;
}
.cal-stack > :first-child { grid-column: 1 / -1; }

@media (max-width: 900px) {
  .cal-detail { grid-template-columns: 1fr; gap: clamp(24px, 5vw, 40px); }
  .cal-detail--reverse > :first-child { order: 0; }
  .cal-detail__body > :last-child { margin-top: 1.4rem; }
}

/* ==========================================================================
   17. LOCATION MAP
   A Google Maps embed in a branded frame. No API key needed — the plain
   ?output=embed endpoint works anywhere, including inside WordPress.
   To repoint it, change the `q=` value in the iframe src.
   ========================================================================== */
/* Sand, not linen — the Arboretum map follows a linen section and the two
   used to melt into one continuous beige block. The hairline seals the seam. */
.cal-map {
  background: var(--cal-sand);
  border-top: 1px solid var(--cal-hairline);
  border-bottom: 1px solid var(--cal-hairline);
}

.cal-map__grid {
  display: grid;
  grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr);
  gap: clamp(26px, 3.6vw, 60px);
  align-items: center;
}
.cal-map__facts { display: grid; gap: .7rem; margin: 1.2rem 0 1.5rem; }
.cal-map__fact {
  display: flex;
  align-items: flex-start;
  gap: .75rem;
  font-size: .97rem;
  line-height: 1.5;
  color: var(--cal-ink-soft);
}
.cal-map__fact svg { width: 13px; height: 13px; color: var(--cal-teal); flex: none; margin-top: .38em; }
.cal-map__fact strong { color: var(--cal-ink); font-weight: 700; }

.cal-map__frame {
  position: relative;
  border-radius: var(--cal-r-lg);
  overflow: hidden;
  box-shadow: var(--cal-shadow);
  aspect-ratio: 4 / 3;
  background: var(--cal-sand);
}
.cal-map__frame iframe {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

@media (max-width: 900px) {
  .cal-map__grid { grid-template-columns: 1fr; }
  .cal-map__frame { aspect-ratio: 3 / 2; }
}

/* ==========================================================================
   LIGHTBOX
   A closer look, not a different place: the photograph sits large in the
   middle with the site dimmed but still there behind it.
   ========================================================================== */
.cal-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9500;
  display: grid;
  place-items: center;
  padding: clamp(16px, 4vw, 48px);
  opacity: 0;
  transition: opacity .22s var(--cal-ease);
}
.cal-lightbox.is-open { opacity: 1; }
.cal-lightbox[hidden] { display: none !important; }

/* Dark enough to take attention off the page, light enough that the page is
   plainly still underneath. */
.cal-lightbox__scrim {
  position: absolute;
  inset: 0;
  background: rgba(14, 44, 52, .82);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  cursor: zoom-out;
}

.cal-lightbox__frame {
  position: relative;
  /* Deliberately not the whole viewport. Big enough to see, small enough to
     keep the site framing it.

     A fixed width, not a maximum: the arrows are pinned to this box, and a
     box that resized itself around each photograph moved them every time a
     picture had a different shape or a smaller original. */
  width: min(1100px, 82vw);
  display: grid;
  place-items: center;
  max-height: 82vh;
  transform: scale(.97);
  transition: transform .26s var(--cal-ease-out);
}
.cal-lightbox.is-open .cal-lightbox__frame { transform: none; }

.cal-lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 82vh;
  width: auto;
  height: auto;
  border-radius: var(--cal-r);
  box-shadow: 0 24px 70px rgba(0, 0, 0, .45);
}

.cal-scope .cal-lightbox__close{
  position: absolute;
  top: -14px; right: -14px;
  z-index: 2;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 0; border-radius: 50%;
  background: var(--cal-cream);
  color: var(--cal-ink);
  cursor: pointer;
  box-shadow: 0 4px 14px rgba(0, 0, 0, .3);
  transition: transform var(--cal-t) var(--cal-ease);
}
.cal-lightbox__close:hover { transform: scale(1.06); }
.cal-lightbox__close svg { width: 18px; height: 18px; }

.cal-scope .cal-lightbox__nav{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid; place-items: center;
  width: 46px; height: 46px;
  border: 0; border-radius: 50%;
  background: rgba(20, 78, 92, .72);
  color: #fffcf8;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background-color var(--cal-t) var(--cal-ease);
}
.cal-scope .cal-lightbox__nav:hover{ background: rgba(20, 78, 92, .92); }
.cal-lightbox__nav[hidden] { display: none !important; }
.cal-lightbox__nav svg { width: 22px; height: 22px; }
/* Pinned to a frame that is always the same width, so the arrows sit in the
   same place on every photograph.

   They used to hang off the edge of the picture itself. The frame shrinks to
   whatever it holds, so a photograph with a smaller original drew a narrower
   frame and pulled both arrows inward with it; a visitor clicking steadily
   through a gallery would suddenly hit the backdrop and close the lightbox.
   One low-resolution file in a set of thirty-two was enough to do it. */
.cal-lightbox__nav--prev { left: -22px; }
.cal-lightbox__nav--next { right: -22px; }

/* Inside the frame on a pill, not hanging below it. Below looks tidier until
   a tall photograph pushes the frame to the full 82vh and the number lands
   off the bottom of the screen. */
.cal-lightbox__count {
  position: absolute;
  left: 50%; bottom: 14px;
  transform: translateX(-50%);
  padding: .3em .8em;
  border-radius: 999px;
  background: rgba(20, 78, 92, .72);
  color: #fffcf8;
  font-family: var(--cal-font-punch);
  font-size: .78rem;
  font-weight: 700;
  letter-spacing: .08em;
  white-space: nowrap;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.cal-lightbox__count[hidden] { display: none; }

/* The page behind must not scroll away under the photograph. */
body.cal-lightbox-open { overflow: hidden; }

/* A photograph that opens should look like one. */
.cal-showcase__main img,
.cal-gallery-stage img,
.cal-carousel img,
.cal-stack img { cursor: zoom-in; }
.cal-showcase__thumb img { cursor: pointer; }

@media (max-width: 640px) {
  /* No room to hang the controls outside the frame on a phone. */
  .cal-lightbox__frame { max-width: 94vw; }
  .cal-lightbox__close { top: 8px; right: 8px; }
  .cal-lightbox__nav--prev { left: 6px; }
  .cal-lightbox__nav--next { right: 6px; }
  .cal-scope .cal-lightbox__nav{ width: 40px; height: 40px; background: rgba(20, 78, 92, .8); }
  .cal-lightbox__count { bottom: 10px; }
}

/* ==========================================================================
   SHOWCASE
   One big photograph, two small ones under it, arrows that rotate the set.
   Built by calycanto-core.js; before that runs this is a plain column of
   figures, which is exactly what it should look like with no JavaScript.
   ========================================================================== */
.cal-showcase { display: grid; gap: 10px; }
.cal-showcase:focus { outline: none; }
.cal-showcase:focus-visible { outline: 2px solid var(--cal-teal); outline-offset: 4px; border-radius: var(--cal-r); }

.cal-showcase__main { position: relative; }

/* The arrows sit on the photograph. Dark translucent rather than solid
   white, so they read on a bright sky and on a dark interior alike. */
.cal-scope .cal-showcase__nav{
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 0;
  border-radius: 50%;
  background: rgba(20, 78, 92, .62);
  color: #fffcf8;
  cursor: pointer;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background-color var(--cal-t) var(--cal-ease), transform var(--cal-t) var(--cal-ease);
}
.cal-scope .cal-showcase__nav:hover{ background: rgba(20, 78, 92, .86); }
.cal-showcase__nav:active { transform: translateY(-50%) scale(.94); }
.cal-showcase__nav svg { width: 20px; height: 20px; }
.cal-showcase__nav--prev { left: 12px; }
.cal-showcase__nav--next { right: 12px; }

.cal-showcase__count {
  position: absolute;
  right: 12px; bottom: 12px;
  z-index: 2;
  padding: .28em .7em;
  border-radius: 999px;
  background: rgba(20, 78, 92, .62);
  color: #fffcf8;
  font-family: var(--cal-font-punch);
  font-size: .76rem;
  font-weight: 700;
  letter-spacing: .06em;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}

.cal-showcase__thumbs { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }

/* --- moving between photographs -------------------------------------------
   The three slots have to change TOGETHER. They used to change one at a
   time, and because an <img> keeps painting its old frame until the new file
   arrives, the photograph that had just been promoted to the big slot was
   still sitting in a thumbnail underneath it. That is the "stuck" duplicate.

   So: the set fades out, all three sources are swapped while nothing is
   visible, and it fades back in. A slow file can now only ever arrive late
   into an empty slot, which shows the warm placeholder behind it and reads
   as loading. It can never show the wrong photograph.

   The travel direction leans the set the way it is going, so a click always
   produces movement even before the next picture is ready.

   Durations here are the contract: calycanto-core.js swaps at SHIFT_MS and
   the two must match. --------------------------------------------------- */
.cal-showcase__main .cal-img > img,
.cal-showcase__thumb .cal-img > img {
  transition: opacity .26s ease, transform .26s cubic-bezier(.22, .61, .36, 1);
}
.cal-showcase__thumbs { transition: transform .26s cubic-bezier(.22, .61, .36, 1); }

.cal-showcase.is-shifting .cal-showcase__main .cal-img > img,
.cal-showcase.is-shifting .cal-showcase__thumb .cal-img > img,
.cal-showcase.is-shifting .cal-showcase__thumbs { transition-duration: .17s; }

.cal-showcase.is-shifting .cal-showcase__main .cal-img > img,
.cal-showcase.is-shifting .cal-showcase__thumb .cal-img > img { opacity: 0; }

.cal-showcase.is-shift-next .cal-showcase__thumbs { transform: translateX(-7%); }
.cal-showcase.is-shift-prev .cal-showcase__thumbs { transform: translateX(7%); }
.cal-showcase.is-shift-next .cal-showcase__main .cal-img > img { transform: translateX(-2%) scale(1.02); }
.cal-showcase.is-shift-prev .cal-showcase__main .cal-img > img { transform: translateX(2%) scale(1.02); }

@media (prefers-reduced-motion: reduce) {
  .cal-showcase__main .cal-img > img,
  .cal-showcase__thumb .cal-img > img,
  .cal-showcase__thumbs { transition-duration: .01ms; }
  .cal-showcase.is-shift-next .cal-showcase__thumbs,
  .cal-showcase.is-shift-prev .cal-showcase__thumbs,
  .cal-showcase.is-shift-next .cal-showcase__main .cal-img > img,
  .cal-showcase.is-shift-prev .cal-showcase__main .cal-img > img { transform: none; }
}
.cal-showcase__thumb {
  display: block;
  padding: 0;
  border: 0;
  background: none;
  cursor: pointer;
  border-radius: var(--cal-r);
  overflow: hidden;
  transition: transform var(--cal-t) var(--cal-ease);
}
.cal-showcase__thumb:hover { transform: translateY(-2px); }
.cal-showcase__thumb figure { margin: 0; }

@media (max-width: 560px) {
  .cal-showcase__nav { width: 36px; height: 36px; }
  .cal-showcase__nav--prev { left: 8px; }
  .cal-showcase__nav--next { right: 8px; }
}

/* --------------------------------------------------------------------------
   PROMOTIONAL PRICE
   The old price and the new one sit on the same line. The old one is quieter
   and smaller as well as struck through: the line alone is easy to miss at a
   glance, and the point of the pair is that the eye lands on the new figure.
   -------------------------------------------------------------------------- */
.cal-scope .cal-was{
  color: var(--cal-ink-mute);
  font-size: .82em;
  font-weight: 400;
  margin-right: .18em;
  text-decoration-thickness: .08em;
}
.cal-scope .cal-now{ color: var(--cal-rust); }

/* --------------------------------------------------------------------------
   THE LITTLE CONFIRMATION
   Sent a note, and told so without leaving the page. Deliberately small: a
   whole screen of celebration for a one-line enquiry is too much, and losing
   their place on the page to read it is worse.
   -------------------------------------------------------------------------- */
.cal-say{
  position: fixed; inset: 0; z-index: 1200;
  display: grid; place-items: center;
  padding: 20px;
  background: rgba(43, 35, 35, .46);
  opacity: 0;
  transition: opacity var(--cal-t) var(--cal-ease);
}
.cal-say.is-open{ opacity: 1; }
.cal-say[hidden]{ display: none; }
.cal-say__box{
  background: var(--cal-cream);
  border-radius: 18px;
  padding: clamp(26px, 3.4vw, 38px) clamp(24px, 3vw, 40px) clamp(22px, 2.8vw, 32px);
  max-width: 430px; width: 100%;
  text-align: center;
  box-shadow: 0 18px 48px rgba(43, 35, 35, .22);
  transform: translateY(10px) scale(.985);
  transition: transform var(--cal-t) var(--cal-ease);
}
.cal-say.is-open .cal-say__box{ transform: none; }
.cal-say__mark{ width: 46px; height: 46px; margin: 0 auto .9rem; color: var(--cal-teal); display: block; }
.cal-say__title{
  font-family: var(--cal-font-display);
  font-size: clamp(1.4rem, 2.4vw, 1.75rem);
  font-weight: 500; line-height: 1.2; letter-spacing: -.01em;
  color: var(--cal-ink); margin: 0 0 .6rem;
}
.cal-say__body{ font-size: 1rem; line-height: 1.6; color: var(--cal-ink-soft); margin: 0 0 1.4rem; }
@media (prefers-reduced-motion: reduce){
  .cal-say, .cal-say__box{ transition: none; }
}

/* --------------------------------------------------------------------------
   THE ENQUIRY FORM
   The same form now sits at the foot of Book now and on Contact, so what it
   needs lives here rather than in either section's own style block. The
   fields themselves (.cal-field, .cal-input, .cal-select, .cal-textarea) are
   already defined above and are shared with the booking modal.
   -------------------------------------------------------------------------- */
.cal-contact__form { display: grid; gap: 1.1rem; }
.cal-contact__row  { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 860px) {
  .cal-contact__row { grid-template-columns: 1fr; }
}
/* What the form says when it will not send. */
.cal-contact__err{
  margin: 0;
  color: var(--cal-rust);
  font-size: .95rem;
  font-weight: 600;
}
.cal-contact__err[hidden]{ display: none; }
/* The date boxes while "not sure yet" is ticked. */
.cal-scope .cal-input:disabled{ opacity: .45; cursor: not-allowed; }

/* --------------------------------------------------------------------------
   THE DATE RANGE FIELD
   One control for both dates, in the shape of the booking calendar. The
   calendar inside it is styled by calycanto-booking.css, which every page
   loads, so only the field and the popover are described here.
   -------------------------------------------------------------------------- */
.cal-rangepick { position: relative; }
.cal-scope .cal-rangepick__field{
  display: block;
  width: 100%;
  text-align: left;
  font: inherit;
  font-size: 1rem;
  padding: .82em 1em;
  border: 1px solid var(--cal-hairline);
  border-radius: var(--cal-r-sm, 12px);
  background: var(--cal-cream);
  color: var(--cal-ink-mute);
  cursor: pointer;
  transition: border-color var(--cal-t) var(--cal-ease),
              box-shadow var(--cal-t) var(--cal-ease);
}
.cal-scope .cal-rangepick__field.is-set{ color: var(--cal-ink); font-weight: 600; }
.cal-scope .cal-rangepick__field:hover{ border-color: var(--cal-teal); }
.cal-scope .cal-rangepick__field[aria-expanded="true"]{
  border-color: var(--cal-teal);
  box-shadow: 0 0 0 3px rgba(31, 158, 187, .16);
}

.cal-rangepick__pop{
  position: absolute;
  z-index: 60;
  top: calc(100% + 8px);
  left: 0;
  min-width: min(620px, 92vw);
  background: var(--cal-cream);
  border: 1px solid var(--cal-hairline);
  border-radius: 16px;
  box-shadow: 0 16px 44px rgba(43, 35, 35, .18);
  padding: clamp(14px, 2vw, 20px);
}
.cal-rangepick__pop[hidden]{ display: none; }
/* On a narrow screen it would otherwise run off the right-hand edge. */
@media (max-width: 700px){
  .cal-rangepick__pop{ left: 50%; transform: translateX(-50%); min-width: min(360px, 94vw); }
}
.cal-rangepick__foot{
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: .9rem;
  padding-top: .9rem;
  border-top: 1px solid var(--cal-hairline);
}
.cal-scope .cal-btn--sm{ padding: .6em 1.3em; font-size: .92rem; }
/* While "not sure yet" is ticked the field is out of play and says so. */
.cal-scope .cal-rangepick__field:disabled{
  opacity: .5;
  cursor: not-allowed;
  border-color: var(--cal-hairline);
  box-shadow: none;
}
