/* ==========================================================================
   The Olive Farm — stylesheet
   Hand-written, no framework, no external requests.
   Palette: stone, olive, terracotta, sea.
   ========================================================================== */

:root {
  --olive-900: #2f3a1f;
  --olive-700: #4a5c2e;
  --olive-600: #5c7239;
  --olive-300: #a8b98a;
  --olive-100: #eef1e6;

  --stone-900: #2b2724;
  --stone-700: #4d463f;
  --stone-500: #7a7168;
  --stone-300: #cfc7ba;
  --stone-100: #f7f4ee;
  --stone-50:  #fdfbf7;

  --terracotta: #b4653a;
  --terracotta-dark: #94502c;
  --sea: #2c6c78;

  --text: var(--stone-900);
  --muted: var(--stone-500);
  --border: #e3ddd1;
  --radius: 10px;
  --radius-lg: 16px;

  --shadow-sm: 0 1px 2px rgba(43, 39, 36, .06), 0 2px 8px rgba(43, 39, 36, .05);
  --shadow-md: 0 4px 12px rgba(43, 39, 36, .09), 0 12px 32px rgba(43, 39, 36, .07);

  --wrap: 1140px;
  /* 1.25rem rather than 1rem at the floor: on a 360px phone the old value
     left the hero text only 16px from the edge, which felt cramped. */
  --gutter: clamp(1.25rem, 4vw, 2.5rem);

  --serif: Georgia, 'Iowan Old Style', 'Palatino Linotype', 'Times New Roman', serif;
  --sans: system-ui, -apple-system, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
}

*, *::before, *::after { box-sizing: border-box; }

html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }

/* Readable by a screen reader and by a search engine, invisible on screen. Used
   where a section needs a heading for structure but not for the eye: headings
   are how both of them navigate, so dropping one entirely is not free. */
.visually-hidden {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; border: 0;
  clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: .001ms !important; transition-duration: .001ms !important; }
}

body {
  margin: 0;
  font-family: var(--sans);
  font-size: clamp(1rem, .96rem + .2vw, 1.075rem);
  line-height: 1.65;
  color: var(--text);
  background: var(--stone-50);
  -webkit-font-smoothing: antialiased;
}

img, picture, svg { max-width: 100%; }
picture { display: block; }
img { height: auto; display: block; }

h1, h2, h3, h4 {
  font-family: var(--serif);
  line-height: 1.18;
  color: var(--olive-900);
  margin: 0 0 .6em;
  font-weight: 600;
  text-wrap: balance;
}
h1 { font-size: clamp(2rem, 1.4rem + 3.2vw, 3.5rem); letter-spacing: -.015em; }
h2 { font-size: clamp(1.5rem, 1.2rem + 1.6vw, 2.25rem); letter-spacing: -.01em; }
h3 { font-size: clamp(1.15rem, 1.05rem + .6vw, 1.4rem); }
p  { margin: 0 0 1.1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--terracotta-dark); text-underline-offset: .18em; }
a:hover { color: var(--terracotta); }

ul, ol { margin: 0 0 1.1em; padding-left: 1.15em; }
li { margin-bottom: .35em; }

:focus-visible {
  outline: 3px solid var(--terracotta);
  outline-offset: 2px;
  border-radius: 3px;
}

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--olive-900); color: #fff; padding: .7rem 1.1rem;
  border-radius: 0 0 var(--radius) 0; font-weight: 600;
}
.skip-link:focus { left: 0; color: #fff; }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
.narrow { max-width: 46rem; }
.center { text-align: center; }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5em;
  padding: .8rem 1.5rem;
  border-radius: 999px;
  font-weight: 600;
  font-size: 1rem;
  /* Explicit so label placement can never depend on the inherited line box. */
  line-height: 1.25;
  white-space: nowrap;
  text-align: center;
  text-decoration: none;
  border: 2px solid transparent;
  cursor: pointer;
  transition: transform .12s ease, box-shadow .18s ease, background-color .18s ease, color .18s ease;
}
.btn:hover { transform: translateY(-1px); }
.btn--primary { background: var(--terracotta); color: #fff; box-shadow: var(--shadow-sm); }
.btn--primary:hover { background: var(--terracotta-dark); color: #fff; box-shadow: var(--shadow-md); }
.btn--olive { background: var(--olive-700); color: #fff; }
.btn--olive:hover { background: var(--olive-900); color: #fff; }
.btn--ghost { background: transparent; color: var(--olive-900); border-color: var(--stone-300); }
.btn--ghost:hover { border-color: var(--olive-700); background: #fff; color: var(--olive-900); }
.btn--light { background: rgba(255,255,255,.94); color: var(--olive-900); }
.btn--light:hover { background: #fff; color: var(--olive-900); }
.btn--sm { padding: .5rem 1rem; font-size: .9rem; }
.btn--lg { padding: 1rem 2rem; font-size: 1.08rem; }
.btn--block { width: 100%; justify-content: center; }

.btn-row { display: flex; flex-wrap: wrap; gap: .75rem; }

/* ------------------------------------------------------------- offer bar */
.offer-bar {
  background: var(--olive-900);
  color: #eef1e6;
  text-align: center;
  font-size: .9rem;
  padding: .55rem 1rem;
  line-height: 1.4;
}
.offer-bar p { margin: 0; }
.offer-bar strong { color: #fff; }
.offer-bar__sep { opacity: .5; margin: 0 .35em; }

/* ---------------------------------------------------------- site header */
.site-header {
  background: rgba(253, 251, 247, .96);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--border);
  position: sticky; top: 0; z-index: 50;
}

/* Anchor targets have to clear the sticky header themselves. Putting
   scroll-margin-top on the header, which is where it was, does nothing at all:
   the property applies to the element being scrolled to. Without this, every
   jump link — "Ask us a question", "Check dates", the footer links — landed
   with the first line of its section hidden behind the header. 5rem clears the
   header's 4.25rem plus a little air. */
[id] { scroll-margin-top: 5rem; }
.site-header__inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; min-height: 4.25rem;
}
.brand {
  display: inline-flex; align-items: center; gap: .65rem;
  text-decoration: none; color: var(--olive-900);
}
.brand__mark { color: var(--olive-600); display: grid; place-items: center; }
.brand__name { display: block; font-family: var(--serif); font-size: 1.2rem; font-weight: 700; line-height: 1.1; }
.brand__place { display: block; font-size: .72rem; letter-spacing: .08em; text-transform: uppercase; color: var(--muted); }

/* The nav is a flex row: the link list and the CTA button sit side by side and
   are vertically centred together. Without this the button and the <ul> stack
   as separate block-level boxes and the CTA falls outside the nav box. */
.site-nav {
  display: flex; align-items: center; gap: .5rem;
  flex-wrap: wrap; justify-content: flex-end;
}
.site-nav ul {
  display: flex; align-items: center; gap: 1.4rem; flex-wrap: wrap;
  list-style: none; margin: 0; padding: 0;
}
.site-nav a {
  text-decoration: none; color: var(--stone-700); font-size: .95rem; font-weight: 500;
  padding: .35rem 0; border-bottom: 2px solid transparent;
}
.site-nav a:hover { color: var(--olive-900); border-bottom-color: var(--olive-300); }
.site-nav a[aria-current="page"] { color: var(--olive-900); border-bottom-color: var(--terracotta); font-weight: 600; }
/* The CTA button sits inside .site-nav, so ".site-nav a { color: ... }" was winning
   on source order (equal specificity, later rule) and painting the label dark brown
   on terracotta. Pin it with enough specificity that the button colour always wins. */
.site-nav .site-nav__cta,
.site-nav .site-nav__cta:hover {
  color: #fff;
  border-bottom: none;
}
.site-nav__cta {
  margin-left: .5rem;
  border-bottom: none;
  flex: 0 0 auto;
  align-self: center;
}

.nav-toggle-label { display: none; }

@media (max-width: 900px) {
  .nav-toggle-label {
    display: grid; gap: 5px; cursor: pointer; padding: .6rem .4rem;
  }
  .nav-toggle-label span {
    display: block; width: 26px; height: 2px; background: var(--olive-900); border-radius: 2px;
    transition: transform .2s ease, opacity .2s ease;
  }
  .site-nav {
    display: none;
    position: absolute; left: 0; right: 0; top: 100%;
    background: var(--stone-50);
    border-bottom: 1px solid var(--border);
    box-shadow: var(--shadow-md);
    padding: 1rem var(--gutter) 1.5rem;
  }
  .nav-toggle:checked ~ .site-nav { display: block; }
  .nav-toggle:checked ~ .nav-toggle-label span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  .nav-toggle:checked ~ .nav-toggle-label span:nth-child(2) { opacity: 0; }
  .nav-toggle:checked ~ .nav-toggle-label span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  .site-nav ul { flex-direction: column; align-items: flex-start; gap: .2rem; }
  .site-nav a { display: block; padding: .6rem 0; font-size: 1.05rem; border-bottom: none; }
  .site-nav__cta { margin: 1rem 0 0; }
}

/* ----------------------------------------------------------------- hero */
.hero { position: relative; isolation: isolate; background: var(--olive-900); }
.hero__media { position: absolute; inset: 0; z-index: -2; }
/* The photograph fills the hero box and is cropped to fit. This rule was lost
   when the drone slideshow was replaced by a single still: every rule below
   targeted .hero__slide, which no longer exists, so the image was rendering at
   its intrinsic 1400x933 and being clipped with no object-fit at all. */
.hero__media img {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  /* 70% shows the house and garden rather than the canopy above them: the
     photograph's subject sits low in the frame, so the crop is anchored
     towards its foot. */
  object-position: center 88%;
}

/* On a phone the hero box is tall and narrow, so the photograph is cropped
   from the SIDES rather than the top: at 360px only about 37% of the picture's
   width survives. The house sits on the right of the frame, so a centred crop
   loses it and shows only the veranda. Anchoring right keeps the house in. */
@media (max-width: 700px) {
  /* On a phone the photograph is not used as a background at all. The text
     block is roughly five times taller than it is wide, so covering it with a
     3:2 picture crops the picture to a sliver and the house disappears. Instead
     the picture sits on top at its own proportions and the words sit under it,
     on the olive field. */
  .hero { display: flex; flex-direction: column; }
  .hero__media {
    position: relative; inset: auto;
    height: min(46vw, 240px);
    order: -1;
    z-index: auto;
    background: var(--olive-900);
  }
  .hero__media img { object-position: center 62%; }
  .hero::after { display: none; }
  .hero__card::before { display: none; }
  .hero__inner { padding-block: 1.5rem 1.75rem; }
}


.hero::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  /* Was .62 / .34 / .78, which crushed a photo already shot in low light and
     made the hero read as dark and foreboding. The photograph is brightened in
     the build (build/brighten_hero.py), so the overlay can be lighter and every
     text region still clears AA: kicker 5.5:1, headline 6.7:1, body 8.8:1. */
  /* This gradient now does one job only: it darkens the TOP strip for the
     kicker, and the very bottom for the rating line - the two SMALL lines, which
     the text ellipse above does not reach. Measured with the gradient removed
     entirely, the pixels behind the kicker sit at luminance 143 and behind the
     rating at 135: unreadable. Everything the eye reads as "the photo" is now
     handled by the ellipse instead, so this can be far lighter than it was.
     Whole-hero brightness 59 -> 88. */
  background: linear-gradient(180deg,
    rgba(18,24,10,.30) 0%,
    rgba(20,26,12,.16) 30%,
    rgba(24,30,15,.06) 55%,
    rgba(20,26,12,.20) 100%);
}
.hero__inner {
  /* Horizontal padding comes from .wrap. This must not set it to 0: the rule is
     declared after .wrap at the same specificity, so a zero would win and leave
     the hero text about 1px from the edge of a phone screen.

     Top is small because the text sits high in the hero, following the
     photograph: its subject is in the lower part of the frame. Bottom is kept
     tight so the rating line stays above the fold on a short laptop screen. */
  padding-block: clamp(1.5rem, 5vw, 3rem) clamp(1.25rem, 4vw, 2.5rem);
  color: #fff;
}
/* The hero text sits over a photograph whose pixels swing from near-black to
   near-white within a few pixels - a spread of 253 out of 255. Measured
   contrast passes (5.7:1 at worst) but the eye still reads white text as
   fuzzy, because a blur halo over busy detail is what makes it look washed
   out. This soft ellipse darkens ONLY the pixels behind the words and fades to
   nothing before it reaches the house, so the photograph is not darkened and
   there is no visible panel edge. */
.hero__card { max-width: 44rem; position: relative; }
.hero__card::before {
  content: '';
  position: absolute;
  inset: -1.75rem -2.5rem -1.25rem -1.75rem;
  z-index: -1;
  border-radius: 50%;
  background: radial-gradient(ellipse at 32% 42%,
    rgba(16,22,8,.66) 0%,
    rgba(16,22,8,.46) 42%,
    rgba(16,22,8,.16) 68%,
    rgba(16,22,8,0) 84%);
}
.hero h1 { color: #fff; text-shadow: 0 2px 20px rgba(0,0,0,.35); margin-bottom: .5rem; }
.hero__lede {
  font-size: clamp(1.05rem, 1rem + .35vw, 1.3rem); color: #f2efe6; max-width: 38rem;
  /* Was a 12px blur, which spread a grey halo through the letters. A tight
     shadow defines the glyph edge instead of smearing it. */
  text-shadow: 0 1px 3px rgba(0,0,0,.7);
}
.hero .btn-row { margin-top: 1.75rem; }
.hero__rating { display: flex; align-items: center; gap: .5rem; margin-top: 1.5rem; font-size: .95rem; color: #f0ece1; text-shadow: 0 1px 3px rgba(0,0,0,.7); }

/* --------------------------------------------------------------- badges */
.facts {
  background: var(--olive-100);
  border-bottom: 1px solid var(--border);
}
.facts__list {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 1rem 1.5rem; list-style: none; margin: 0; padding: 1.35rem 0;
}
.facts__list li { margin: 0; }
.facts__label {
  display: block; font-size: .72rem; letter-spacing: .1em; text-transform: uppercase;
  color: var(--olive-700); font-weight: 700;
}
.facts__value { display: block; font-family: var(--serif); font-size: 1.15rem; color: var(--olive-900); }

/* ------------------------------------------------------------- sections */
section { padding: clamp(3rem, 7vw, 5.5rem) 0; }
.section--tint { background: var(--stone-100); }
.section--olive { background: var(--olive-900); color: #e9ecdf; }
.section--olive h2, .section--olive h3 { color: #fff; }
.section--olive a { color: #f0d9a8; }

.eyebrow {
  display: block; font-size: .76rem; letter-spacing: .14em; text-transform: uppercase;
  font-weight: 700; color: var(--terracotta); margin-bottom: .7rem;
}
.section--olive .eyebrow { color: var(--olive-300); }

.split {
  display: grid; grid-template-columns: 1fr 1fr; gap: clamp(1.75rem, 5vw, 4rem);
  align-items: center;
}
.split--top { align-items: start; }
@media (max-width: 820px) { .split { grid-template-columns: 1fr; } }

.prose p { color: var(--stone-700); }
.section--olive .prose p { color: #dfe4d2; }

/* Buttons inside a dark section were being caught by the rule above. ".section--olive a"
   is a class and a type selector, so it outranks ".btn--light" and ".btn--primary", which
   are single classes - and the label colour of every button in a dark section was the
   section's link colour: pale gold on a near-white pill for the WhatsApp button, and cream
   on terracotta for the primary one. Found by looking at a screenshot, which is the only
   thing that could have found it: every check in validate reads markup and text. */
.section--olive .btn--light { color: var(--olive-900); }
.section--olive .btn--primary { color: #fff; }
.section--olive .btn--ghost { color: #fff; border-color: rgba(255,255,255,.5); }
.prose p:first-of-type { font-size: 1.08em; }

/* ---------------------------------------------------------------- cards */
.grid { display: grid; gap: 1.5rem; }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); }

.card {
  background: #fff; border: 1px solid var(--border); border-radius: var(--radius-lg);
  padding: 1.5rem; box-shadow: var(--shadow-sm);
}
.card h3 { margin-bottom: .5rem; }
.card ul { margin-bottom: 0; padding-left: 1.1em; }
.card li { color: var(--stone-700); font-size: .96rem; }

.card--highlight {
  border-color: var(--olive-300);
  background: linear-gradient(180deg, #fff 0%, var(--olive-100) 100%);
  border-width: 2px;
}

.distance {
  display: inline-block; font-size: .76rem; font-weight: 700; letter-spacing: .06em;
  text-transform: uppercase; color: var(--sea); background: #e6f0f2;
  border-radius: 999px; padding: .2rem .7rem; margin-bottom: .6rem;
}

/* -------------------------------------------------------------- gallery */
/* One column on a phone, two from 560px, four from 900px, and nothing in
   between.
   One on a phone is the owner's call, made after seeing the alternative: he had
   the grid two across on a phone for an afternoon and asked for it back the way
   it was, because a photograph gets the whole width and they look better that
   way. The section is long on a phone as a result and he is content with that -
   "users are just going to have to scroll past". It is his site and he has looked
   at it on the device that matters. Do not shorten it again without asking.
   The count is pinned rather than left to `auto-fit`, and that part is not
   cosmetic. `auto-fit` with a 220px minimum happened to give four columns on a
   wide laptop and three at tablet widths, because three fits between about 740px
   and 985px, and three columns stranded the last one or two tiles on a line of
   their own. That fault is what the owner reported. Pinning skips three
   altogether, and every band here divides twenty: one, two and four.
   It matches GALLERY_SIZES in `_lib/blocks.mjs`, which asks for the file to suit
   the slot the photograph is drawn in. Change one and change the other. */
.gallery {
  display: grid; gap: .6rem;
  grid-template-columns: 1fr;
}
@media (min-width: 560px) {
  .gallery { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 900px) {
  .gallery { grid-template-columns: repeat(4, 1fr); }
}
.gallery figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--stone-100); }
.gallery img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; transition: transform .4s ease; }
.gallery figure:hover img { transform: scale(1.04); }
/* A ".gallery--wide" variant lived here, making the first photograph full width
   at 21:9. It is gone, and the reason is worth keeping: the tile was told to be
   a quarter of the screen wide by `sizes`, but the CSS stretched it across the
   whole page, so the browser picked the 400px image for an 1100px hole and it
   came out grainy. The owner spotted it. Tiles of one size cannot go wrong that
   way, and the gallery is more compact without a full-width opening. */

/* -------------------------------------------------------------- pricing */
.rates { width: 100%; border-collapse: collapse; background: #fff; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); }
.rates th, .rates td { padding: .9rem 1.1rem; text-align: left; border-bottom: 1px solid var(--border); }
.rates th { background: var(--olive-100); color: var(--olive-900); font-size: .82rem; letter-spacing: .06em; text-transform: uppercase; }
.rates td:last-child, .rates th:last-child { text-align: right; white-space: nowrap; }
.rates tbody tr:last-child td { border-bottom: none; }
.rates .price { font-family: var(--serif); font-size: 1.15rem; font-weight: 700; color: var(--olive-900); }
/* The season's dates and minimum stay, under its name. The row header inherits
   the uppercase and letter-spacing above, which is right for the one-word season
   and wrong for a sentence, so both are undone here. */
.rates-when {
  display: block;
  margin-top: .3rem;
  font-size: .8rem;
  font-weight: 400;
  letter-spacing: normal;
  text-transform: none;
  color: var(--muted);
}
/* A ".rates .was" rule lived here, crossing out a former price beside the new
   one. Nothing has emitted that class for a long time, and the owner does not
   want a strike-through anywhere near a price on this site: the comparison
   table puts the two figures in their own labelled columns instead. Removed so
   that it cannot be picked up again by accident. */
.rates-note { font-size: .9rem; color: var(--muted); margin-top: 1rem; }

.callout {
  border-left: 4px solid var(--terracotta);
  background: #fff8f3;
  padding: 1.25rem 1.5rem;
  border-radius: 0 var(--radius) var(--radius) 0;
}
.callout p:last-child { margin-bottom: 0; }
.callout--warn { border-left-color: #b8860b; background: #fffaf0; }
.callout--ok { border-left-color: var(--olive-600); background: var(--olive-100); }

/* A card that is swapped in for the form needs the hidden attribute to win
   over the card's own display rule, or it shows before the form is sent. */
.card[hidden] { display: none; }

/* The enquiry form's honeypot. Moved off-screen rather than display:none,
   because some bots skip fields that are obviously hidden. A person never
   sees it and a screen reader never reaches it (aria-hidden + tabindex -1). */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-error {
  border-left: 4px solid #a33; background: #fdf3f3; color: #7a1c1c;
  padding: .9rem 1.1rem; border-radius: 0 var(--radius) var(--radius) 0;
  margin: 1rem 0 0; font-size: .95rem;
}

.cal-choice {
  margin-top: 2rem;
  padding: 1.5rem 1.75rem;
  background: #fff;
  border: 1px solid var(--olive-300);
  border-radius: var(--radius);
  box-shadow: 0 1px 3px rgba(0, 0, 0, .06);
}
.cal-choice__dates {
  font-family: var(--serif);
  font-size: 1.2rem;
  margin: 0 0 .35rem;
  color: var(--olive-900);
}
.cal-choice__price { margin: 0 0 1.25rem; color: var(--olive-700); font-weight: 600; }

/* What is owed now and what is owed later. It slots in between the price and
   the buttons, so it is pulled back up into the price's own bottom margin:
   that way the spacing is unchanged on the days when there is no price to
   split, and the terms simply disappear with the [hidden] attribute. */
.cal-choice__terms {
  margin: -.9rem 0 1.25rem;
  font-size: .95rem;
  color: var(--olive-800);
}
.cal-choice__terms[hidden] { display: none; }

.cal-choice__note { margin: 1rem 0 0; font-size: .85rem; color: var(--muted); }

/* A button that should read as a link, for the escape hatch in a row of
   real buttons. Keeps "Change dates" available without competing with
   "Book these dates" for attention. */
.btn--quiet {
  background: transparent; color: var(--muted); border-color: transparent;
  text-decoration: underline; text-underline-offset: 3px; box-shadow: none;
  padding-left: .5rem; padding-right: .5rem;
}
.btn--quiet:hover { color: var(--olive-900); background: transparent; }

/* ------------------------------------------------------------ calendar */
.cal-toolbar {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 1rem; margin-bottom: 1.25rem;
}
.cal-legend { display: flex; flex-wrap: wrap; gap: 1rem; font-size: .85rem; color: var(--muted); list-style: none; margin: 0; padding: 0; }
.cal-legend li { display: flex; align-items: center; gap: .4rem; margin: 0; }
.swatch { width: .85rem; height: .85rem; border-radius: 3px; display: inline-block; border: 1px solid rgba(0,0,0,.12); }
.swatch--free { background: #fff; }
.swatch--booked { background: #d8cfc2; }
.swatch--selected { background: var(--olive-600); }
.swatch--past { background: repeating-linear-gradient(45deg, #efece6, #efece6 3px, #e2ddd4 3px, #e2ddd4 6px); }

.cal-months {
  display: grid; gap: 1.5rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.cal-month { background: #fff; border: 1px solid var(--border); border-radius: var(--radius); padding: 1rem; }
.cal-month h3 { font-size: 1rem; text-align: center; margin-bottom: .75rem; }
.cal-grid { display: grid; grid-template-columns: repeat(7, 1fr); gap: 2px; }
.cal-dow {
  font-size: .68rem; font-weight: 700; text-align: center; color: var(--muted);
  text-transform: uppercase; padding-bottom: .3rem;
}
.cal-day {
  aspect-ratio: 1; display: grid; place-items: center;
  font-size: .82rem; border-radius: 6px; background: #fff;
  border: 1px solid transparent; color: var(--stone-700);
}
.cal-day--empty { background: transparent; }
.cal-day--booked { background: #d8cfc2; color: #6b6259; text-decoration: line-through; }
.cal-day--past { color: #b6ada2; background: repeating-linear-gradient(45deg, #f6f4f0, #f6f4f0 3px, #efece6 3px, #efece6 6px); }
/* A ".cal-day--out" rule lived here, hatching the days either side of the season
   so they could not be clicked. There are none any more: the calendar draws only
   the months in openMonths, so the winter is not shown at all rather than shown
   as four months of hatched days. Removed rather than left, so nothing picks the
   class up again by accident. */
button.cal-day {
  cursor: pointer; font: inherit; font-size: .82rem;
  transition: background-color .12s ease, transform .12s ease;
}
button.cal-day:hover { background: var(--olive-100); border-color: var(--olive-300); }
.cal-day--selected, .cal-day--inrange { background: var(--olive-600); color: #fff; }
.cal-day--selected { font-weight: 700; }
.cal-hint { text-align: center; font-size: .75rem; color: var(--muted); margin: .5rem 0 0; }

/* The line above the calendar. It sticks to the top of the viewport while the
   months scroll underneath, because the alternative was this: click a day near
   the bottom of a very tall calendar, see some days turn green, and have no
   idea whether anything else happened.
   Pale olive on a pale grey section was not enough to be noticed — it read as
   a quiet paragraph rather than as the answer to what you just clicked. So it
   is now a solid dark band with light text, which is also where the price can
   be picked out in the same gold the olive sections already use. The offset
   clears the sticky header, which is 4.25rem plus its border. */
.cal-status {
  position: sticky;
  top: 4.4rem;
  z-index: 5;
  display: flex; flex-wrap: wrap; align-items: center;
  justify-content: space-between; gap: .7rem 1.25rem;
  background: var(--olive-900);
  color: #e9ecdf;
  border-radius: var(--radius);
  padding: .9rem 1.2rem; font-size: .95rem; margin-bottom: 1.25rem;
  box-shadow: 0 4px 16px rgba(47, 58, 31, .22);
}
.cal-status[hidden] { display: none; }
.cal-status__text { margin: 0; flex: 1 1 20rem; }
.cal-status__actions { display: flex; flex-wrap: wrap; gap: .5rem; }
/* A flex container beats the [hidden] attribute on specificity, so this has to
   be restated or the buttons would show before any dates were chosen. */
.cal-status__actions[hidden] { display: none; }
.cal-status strong { color: #fff; }
.cal-status a { color: #f0d9a8; }
.cal-status__price { color: #f0d9a8; font-weight: 700; }
/* On the dark band the ghost button's usual dark text disappears into it. */
.cal-status .btn--ghost {
  color: #fff; border-color: rgba(255, 255, 255, .55); background: transparent;
}
.cal-status .btn--ghost:hover {
  background: rgba(255, 255, 255, .14); color: #fff; border-color: #fff;
}
/* A complete stay: a shade lighter, so finishing reads as progress. */
.cal-status--done { background: var(--olive-700); }
/* A refused click, and a calendar that would not load, are the two states
   worth interrupting for, so they get terracotta rather than olive. */
.cal-status--warn, .cal-status--error { background: #6f3126; color: #fdf1ee; }
.cal-status--warn strong, .cal-status--error strong { color: #fff; }

/* ---------------------------------------------------------------- forms */
.form-grid { display: grid; gap: 1rem; grid-template-columns: 1fr 1fr; }
@media (max-width: 700px) { .form-grid { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: .35rem; }
/* A flex container beats the [hidden] attribute on specificity, so this has to
   be restated or the date fields would stay on screen after the calendar has
   already answered them. */
[data-date-field][hidden] { display: none; }
.field--full { grid-column: 1 / -1; }
.field label { font-weight: 600; font-size: .9rem; color: var(--olive-900); }
.field .hint { font-size: .82rem; color: var(--muted); }
.field input, .field select, .field textarea {
  font: inherit; font-size: 1rem;
  padding: .7rem .85rem;
  border: 1px solid var(--stone-300);
  border-radius: var(--radius);
  background: #fff; color: var(--text);
  width: 100%;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--olive-600); outline: 3px solid rgba(92,114,57,.22); outline-offset: 0;
}
.field textarea { min-height: 8rem; resize: vertical; }
.form-note { font-size: .85rem; color: var(--muted); margin-top: 1rem; }

/* A ".contact-list" block lived here: the email and WhatsApp pair that used to
   sit beside the enquiry form under little uppercase labels. The owner asked for
   them to come out, as they competed with the form and said nothing the footer
   does not already say. The panel behind them is still in the footer. Removed
   rather than left, so nothing picks the classes up again by accident. */

/* ------------------------------------------------------------------ faq */
.faq { border-top: 1px solid var(--border); }
.faq details {
  border-bottom: 1px solid var(--border);
  padding: .35rem 0;
}
.faq summary {
  cursor: pointer; padding: .9rem 2rem .9rem 0; position: relative;
  font-family: var(--serif); font-size: 1.1rem; font-weight: 600; color: var(--olive-900);
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '+'; position: absolute; right: .35rem; top: 50%; transform: translateY(-50%);
  font-size: 1.5rem; font-weight: 400; color: var(--terracotta); line-height: 1;
}
.faq details[open] summary::after { content: '\2212'; }
.faq details > p { padding-right: 2rem; color: var(--stone-700); }

/* --------------------------------------------------------------- stars */
.stars { position: relative; display: inline-block; font-size: 1rem; letter-spacing: .05em; line-height: 1; white-space: nowrap; }
.stars__base { color: rgba(255,255,255,.45); }
.stars__fill { position: absolute; left: 0; top: 0; overflow: hidden; color: #f0b429; }
.stars--dark .stars__base { color: var(--stone-300); }

/* ---------------------------------------------------------------- misc */
.breadcrumb { font-size: .85rem; color: var(--muted); padding-top: 1.25rem; }
.breadcrumb ol { list-style: none; display: flex; flex-wrap: wrap; gap: .4rem; margin: 0; padding: 0; }
.breadcrumb li::after { content: '/'; margin-left: .4rem; opacity: .5; }
.breadcrumb li:last-child::after { content: ''; }
.breadcrumb a { color: var(--muted); }

.page-header { background: var(--olive-100); border-bottom: 1px solid var(--border); padding-bottom: clamp(2rem, 5vw, 3.5rem); }
.page-header h1 { margin-bottom: .5rem; }
.page-header__lede { font-size: 1.15rem; color: var(--stone-700); max-width: 46rem; }

.todo {
  background: #fff8e5; border: 1px dashed #d9b24c; border-radius: var(--radius);
  padding: .85rem 1.15rem; font-size: .9rem; color: #6d5620; margin: 1.25rem 0;
}
.todo strong { color: #4a3a12; }

/* -------------------------------------------------------------- footer */
.site-footer { background: var(--olive-900); color: #d5dcc6; padding: clamp(2.5rem, 6vw, 4rem) 0 1.5rem; font-size: .94rem; }
.site-footer__grid { display: grid; gap: 2rem; grid-template-columns: 1.6fr 1fr 1fr 1.2fr; }
@media (max-width: 900px) { .site-footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .site-footer__grid { grid-template-columns: 1fr; } }
.site-footer__brand { font-family: var(--serif); font-size: 1.35rem; color: #fff; margin-bottom: .5rem; }
.site-footer__blurb { color: #bcc6a8; max-width: 28rem; }
.site-footer__rating { display: flex; align-items: center; gap: .5rem; color: #cfd8bd; }
.site-footer .stars__base { color: rgba(255,255,255,.3); }
.site-footer__head { font-size: .78rem; letter-spacing: .12em; text-transform: uppercase; color: var(--olive-300); margin-bottom: .75rem; font-family: var(--sans); font-weight: 700; }
.site-footer__links { list-style: none; margin: 0; padding: 0; }
.site-footer__links li { margin-bottom: .45rem; }
.site-footer a { color: #d5dcc6; text-decoration: none; border-bottom: 1px solid transparent; }
.site-footer a:hover { color: #fff; border-bottom-color: var(--olive-300); }
.site-footer__bottom {
  margin-top: 2.5rem; padding-top: 1.25rem;
  border-top: 1px solid rgba(255,255,255,.13);
  font-size: .82rem; color: #9aa886;
  display: flex; flex-wrap: wrap; gap: .5rem 2rem; justify-content: space-between;
}

@media print {
  .site-header, .offer-bar, .site-footer, .btn, .cal-months { display: none !important; }
  body { background: #fff; }
}

/* --------------------------------------------- the place, in six views
   Static photographs with words beside them, alternating left and right. This
   replaced a full-width slideshow: at 2s a slide, a wall of panoramic image
   went past before the eye could take any of it in. Here each photograph is
   half the width, its own shape rather than a cropped band, and it stays put. */
.views {
  /* The page's existing tint, not pure white: on white this section read as
     cold and slightly separate from the rest of the page. */
  background: var(--stone-100);
}
.views__rows { margin-top: clamp(1.5rem, 4vw, 3rem); }
.views__row {
  align-items: center;
  padding-block: clamp(1.75rem, 4.5vw, 3.25rem);
}
.views__row + .views__row { border-top: 1px solid var(--border); }

/* The house gallery, between the four passages about the house and the two
   about the surroundings. It sits inside the views section, so it needs its own
   rule above it: the divider above fires only between two .views__row elements
   and this is neither. */
.gallery-block {
  padding-block: clamp(1.75rem, 4.5vw, 3.25rem);
  border-top: 1px solid var(--border);
}
.gallery-block h3 { margin-top: 0; }
.gallery-block .prose { color: var(--stone-700); }
.gallery-block .gallery { margin-top: 1.75rem; }
.gallery-block .btn-row { margin-top: 1.75rem; }
/* The last row carries the area button under its text, so it needs less room
   beneath it than the others - otherwise the button reads as a separate thing
   floating below the row rather than part of it. */
.views__row--last { padding-bottom: clamp(.75rem, 2vw, 1.25rem); }
.views__row--last .btn-row { margin-top: 1.25rem; }
/* Odd rows put the photograph on the right. Column order changes; the DOM
   order does not, so a screen reader and a phone still meet the words first. */
.views__row--flip .views__photo { order: 2; }
.views__photo { margin: 0; }
.views__photo img {
  width: 100%; height: auto; display: block; border-radius: 4px;
  /* Stops a 3:2 photograph becoming 900px tall on a very wide screen, which
     is the "too big" problem the slideshow had. */
  max-height: 520px; object-fit: cover;
}
.views__text h3 { margin-top: 0; }
.views__text p { color: var(--stone-700); }
.views__text p:last-child { margin-bottom: 0; }

/* The closing sunset. Deep olive surrounds the photograph rather than being
   laid over it: the olive is used ONCE on the page as a strong accent, and the
   photograph keeps its own colours instead of being shaded to carry text. */
/* The payoff and the "why it matters" section that follows are both deep
   olive, and they run together as ONE dark passage rather than two blocks with
   a seam between them. This is the only place on the page that goes dark. */
.payoff { background: var(--olive-700); }
.payoff img { width: 100%; height: auto; display: block; }
.payoff__overlay {
  padding-block: clamp(2.25rem, 6vw, 3.5rem) clamp(1.5rem, 4vw, 2.5rem);
  color: #fff;
}
/* the olive section immediately after continues the same field */
.payoff + .section--olive { padding-top: 0; }
.payoff__overlay h2 { color: #fff; margin-bottom: .35rem; }
.payoff__overlay p { color: #dfe6cd; margin: 0; }

@media (max-width: 860px) {
  /* One column. The alternation cannot survive, and does not need to: the
     photograph simply follows its words. */
  .views__row { grid-template-columns: 1fr; gap: 1.25rem; }
  .views__row--flip .views__photo { order: 0; }
}

/* ------------------------------------------------------- the setting band
   The drone stills are 2.1:1. In a tall hero they get force-cropped and the
   house falls off the bottom, so they live here instead, at their own ratio,
   where the whole frame is visible. Nothing is cropped. */
.setting-band { padding-bottom: clamp(2.5rem, 6vw, 4rem); }
.setting-band__strip {
  position: relative;
  margin-top: 2rem;
  width: 100%;
  aspect-ratio: 2.1;
  background: var(--olive-900);
  overflow: hidden;
}
.setting-band__strip .hero__slide { position: absolute; inset: 0; }
.setting-band__strip .hero__slide.is-active { opacity: 1; }
.setting-band__strip img {
  width: 100%; height: 100%;
  object-fit: cover;
  object-position: center center;
  display: block;
}
@media (max-width: 700px) {
  /* On a phone a 2.1:1 band is a sliver, so let it be taller there. */
  .setting-band__strip { aspect-ratio: 1.5; }
}

/* --------------------------------------------------- rate comparison table */
.rates--compare th[scope="row"] { font-weight: 600; }
.rates--compare .cmp-platform { color: var(--muted); }
/* No prefix: the column heading above says what this figure is on a wide
   screen, and on a phone the data-label does the same job. */
/* No prefix on a wide screen: the column heading says what this figure is, and
   'was' was wrong for a platform's price. On a phone the data-label supplies the
   words instead - see the media query at the foot of this file. */
.rates--compare .cmp-platform::before { display: none; }
.rates--compare .cmp-direct { color: var(--olive-900); font-family: var(--serif); font-size: 1.15rem; }
.rates--compare .cmp-save {
  /* Was a nowrap pill holding a single figure. It now carries a nightly and a
     weekly saving on two lines, so the pill is gone: being nowrap, it would
     have forced the table wider than a phone screen. Colour kept, emphasis kept. */
  font-size: .88rem;
  color: var(--terracotta-dark);
  line-height: 1.35;
}
.rates--compare .cmp-save strong { font-weight: 700; }
/* The two figures stack on every screen. Without this they are inline spans and
   run together as 'EUR29 a nightEUR203 a week'. */
.rates--compare .cmp-save__pair { display: block; }
.rates--compare .cmp-save__line { display: block; white-space: nowrap; }
.rates--compare tbody tr:hover { background: var(--olive-100); }

/* --------------------------------------------- live stay total in the form */
.stay-total {
  background: linear-gradient(180deg, #fff 0%, var(--olive-100) 100%);
  border: 2px solid var(--olive-300);
  border-radius: var(--radius-lg);
  padding: 1.1rem 1.25rem;
  /* Sits above the fields now, so it needs room beneath it rather than above. */
  margin: 0 0 1.35rem;
}
.stay-total[hidden] { display: none; }
.stay-total__dates {
  margin: 0 0 .35rem;
  font-weight: 600;
  color: var(--olive-900);
}
.stay-total__figure {
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(1.35rem, 1.2rem + .8vw, 1.75rem);
  font-weight: 700;
  color: var(--olive-900);
  line-height: 1.2;
}
.stay-total__figure .accent { color: var(--terracotta-dark); }

/* Shown only on the booking route. Someone who has only asked a question is
   not being asked for money, so they never see this line at all. */
.stay-total__terms {
  margin: .45rem 0 0;
  font-size: .95rem;
  font-weight: 600;
  color: var(--olive-900);
}
.stay-total__terms[hidden] { display: none; }

.stay-total__note {
  margin: .4rem 0 0;
  font-size: .88rem;
  color: var(--stone-700);
}
/* No "<s>" rule here either: the platform price is stated plainly, not crossed
   out. See the note in site.js where that sentence is written. */

/* ------------------------------------------------ five-guest explanation note */
.five-note {
  background: #fff8f3;
  border-left: 4px solid var(--terracotta);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: .85rem 1.1rem;
  font-size: .93rem;
  color: var(--stone-700);
  margin: 0;
}
.five-note[hidden] { display: none; }
.five-note strong { color: var(--olive-900); }

/* ------------------------------------------------------------ checkboxes */
.check {
  display: flex; align-items: center; gap: .55rem;
  font-weight: 600; font-size: .95rem; color: var(--olive-900);
  cursor: pointer;
}
.check input[type="checkbox"] {
  width: 1.15rem; height: 1.15rem; flex: 0 0 auto;
  accent-color: var(--olive-600); cursor: pointer; margin: 0;
}

/* ------------------------------------------------ hint above the date fields */
.dates-hint {
  margin: 0;
  font-size: .88rem;
  color: var(--stone-700);
  background: var(--olive-100);
  border-radius: var(--radius);
  padding: .6rem .85rem;
}

/* ------------------------------------------------------------- lightbox
   Opened by clicking any gallery photograph. The arrows sit either side of
   the picture so the whole set can be walked through without the mouse
   leaving the middle of the screen. */
.lightbox {
  border: 0; padding: 0;
  width: 100vw; max-width: 100vw;
  height: 100vh; max-height: 100vh;
  background: rgba(12, 15, 8, .95);
  color: #fff;
  overflow: hidden;
}
.lightbox::backdrop { background: rgba(12, 15, 8, .95); }

.lightbox__bar {
  position: fixed; top: 0; left: 0; right: 0;
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; padding: .75rem 1rem;
  z-index: 2;
}
.lightbox__count {
  font-size: .85rem; font-variant-numeric: tabular-nums;
  color: rgba(255,255,255,.75); letter-spacing: .04em;
}
.lightbox__close {
  border: 0; background: transparent; color: #fff;
  font-size: 2rem; line-height: 1; cursor: pointer;
  padding: .25rem .6rem; border-radius: 6px;
}
.lightbox__close:hover { background: rgba(255,255,255,.14); }

.lightbox__stage {
  display: flex; align-items: center; justify-content: center;
  gap: 0;                                  /* the slots carry their own space */
  height: 100%;
  padding: 3.25rem clamp(.5rem, 2vw, 1.5rem) 4rem;
  box-sizing: border-box;
}
/* Each arrow gets a fixed-width slot, so the picture shrinks inside the space
   between them instead of pushing them outwards. Without this the arrows sat
   at anything from 28px to 223px from the window edge, depending only on the
   photograph's aspect ratio - 43 pictures of differing shapes, so they jumped
   on nearly every click. */
.lightbox__nav {
  flex: 0 0 var(--lb-slot, 5.5rem);
  display: grid; place-items: center;
  border: 0; background: transparent; padding: 0;
  cursor: pointer;
  color: #fff;
}
.lightbox__nav svg { width: clamp(2.5rem, 5vw, 3.25rem); height: auto; }
.lightbox__nav circle { fill: rgba(255,255,255,.14); }
.lightbox__nav:hover circle { fill: rgba(255,255,255,.28); }
.lightbox__nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 50%; }

/* The picture takes whatever is left and scales to fit. min-width:0 is what
   lets a flex item shrink below its intrinsic width. */
.lightbox__stage img {
  flex: 1 1 auto; min-width: 0; min-height: 0;
  max-width: 100%; max-height: 100%;
  width: auto; height: auto;
  object-fit: contain; border-radius: 4px;
  cursor: default;
}
.lightbox--single { --lb-slot: 0rem; }
.lightbox--single .lightbox__nav { display: none; }
.lightbox__nav:hover { background: rgba(255,255,255,.28); }
.lightbox__nav:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.lightbox--single .lightbox__nav { display: none; }

.lightbox__caption {
  position: fixed; left: 0; right: 0; bottom: 0;
  margin: 0; padding: 1rem clamp(1rem, 5vw, 3rem) 1.25rem;
  text-align: center; font-size: .9rem;
  color: rgba(255,255,255,.85);
  background: linear-gradient(180deg, rgba(12,15,8,0) 0%, rgba(12,15,8,.85) 60%);
}

@media (max-width: 560px) {
  /* On a phone the arrows are wide but shallow, so the picture still gets the
     width it needs. They stay either side of it rather than moving about. */
  .lightbox { --lb-slot: 2.75rem; }
  .lightbox__nav svg { width: 2.25rem; }
}

/* ------------------------------------------------- rates table on a phone
   Four columns carrying prices and two savings figures do not fit a 360px
   screen: the table measured 441px, so the whole page scrolled sideways. Below
   560px each season becomes a small block instead, with the column headings
   moved onto the values using data-label. */
@media (max-width: 560px) {
  .rates--compare thead { display: none; }
  .rates--compare, .rates--compare tbody, .rates--compare tr, .rates--compare th, .rates--compare td {
    display: block; width: 100%;
  }
  .rates--compare tr {
    border: 1px solid var(--border);
    border-radius: var(--radius);
    margin-bottom: .85rem;
    overflow: hidden;
  }
  .rates--compare th[scope="row"] {
    background: var(--olive-100);
    color: var(--olive-900);
    font-size: .82rem;
    letter-spacing: .06em;
    text-transform: uppercase;
  }
  .rates--compare td {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 1rem;
    text-align: right;
    border-bottom: 1px solid var(--border);
  }
  .rates--compare tr td:last-child { border-bottom: none; }
  .rates--compare td::before {
    content: attr(data-label);
    flex: none;
    color: var(--muted);
    font-size: .82rem;
  }
  /* The two phrases sit at the two ends of the cell, not spread apart with a
     gap in the middle. No data-label: the phrases already read as sentences. */
  /* This row follows the same shape as the two above it: 'You save' as the
     label, and the two figures as the value. The daily saving used to sit where
     a label goes, which made it read as part of the left-hand column.
     Specificity matters here: '.rates td:last-child' above is 0,2,1 and sets
     text-align: right, so this has to outrank it rather than merely follow it. */
  .rates--compare td.cmp-save:last-child { text-align: right; }

  /* The caption sits above the table and must use the full width: without this
     it wraps to about one word per line. */
  .rates--compare caption {
    text-align: left;
    /* A table caption is only as wide as its first column, which wrapped this
       one to a word per line. Take it out of that flow and give it full width. */
    display: block; width: 100%; caption-side: top;
  }
  .rates--compare .cmp-platform::before {
    display: inline;
    content: attr(data-label);
    color: var(--muted);
    font-size: .82rem;
  }
  .rates--compare { box-shadow: none; background: transparent; }
}

/* ----------------------------------------- availability under the dates
   Shown while someone types their dates into the enquiry form, so they learn
   about a clash before sending rather than after. */
.cal-availability {
  margin: .75rem 0 0;
  font-size: .92rem;
  min-height: 1.35em;
}
.cal-availability[data-state="free"] { color: var(--olive-700); font-weight: 600; }
.cal-availability[data-state="warn"] { color: var(--terracotta-dark); font-weight: 600; }
.cal-availability[data-state="checking"] { color: var(--muted); }

/* -------------------------------------------------- the rebuild (villa page) */
/* The photographs here carry their dates under them, which nothing else on the
   site does: the whole point of the pair is that it is the same corner twice, and
   a date typed in a caption is the only way to say so. Side by side at every
   width, because two pictures that must be compared should not be stacked. */
.rebuild__intro { align-items: start; }
.rebuild__date { margin: 0; }
.rebuild__date figcaption,
.beforeafter figcaption,
.film figcaption {
  font-size: .85rem; color: var(--stone-700); margin-top: .5rem; line-height: 1.4;
}
.beforeafter {
  display: grid; grid-template-columns: 1fr 1fr; gap: .6rem;
  margin-top: 2rem; align-items: start;
}
.beforeafter figure { margin: 0; }
/* No fixed aspect ratio and no cropping. Everywhere else on the site the pictures
   are cropped square-ish and told to fill their tile, which is right for a grid of
   one-size photographs. Here the two are a comparison, and cropping a before-and-
   after to a house style throws away the half of the frame that makes the point -
   the field of daisies in front of the ruin, for instance. They keep their own
   shapes and sit at their own heights. */
.beforeafter img { width: 100%; height: auto; display: block; border-radius: var(--radius); }
.film { margin: 2rem 0 0; }
.film video { width: 100%; max-width: 640px; height: auto; border-radius: var(--radius); display: block; }

/* ---------------------------------------------------------------------------
   Places on the Area page. These were cards in a three-column grid until the
   owner decided each place needed room to say something: "Ancient Olympia is
   going to need quite a bit of room itself." So they are single-column blocks,
   ordered nearest first, with the distance above the name - the number is what
   orders the page, and it is the first thing a reader wants.
   --------------------------------------------------------------------------- */
.places { margin-top: 2rem; display: grid; gap: 2.5rem; }
.place { max-width: 46rem; }
.place .distance {
  display: block;
  font-size: 0.8125rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--stone-500, #8a8078);
  margin-bottom: 0.25rem;
}
.place h3 { margin: 0 0 0.5rem; }
.place p { color: var(--stone-700, #4a443e); }
.place p:last-child { margin-bottom: 0; }

/* ------------------------------------------------------- the guest book, on the villa page
   Three photographed pages, one column on a phone and three across from the same
   breakpoint the rest of the site uses. These lived in a <style> block in the body, where
   the screenshot harness removed them along with the siblings above the target, which made
   a working grid photograph as a single column. */
.guestbook-grid { display: grid; grid-template-columns: 1fr; gap: 1.5rem; margin-top: 2rem; }
@media (min-width: 700px) { .guestbook-grid { grid-template-columns: repeat(3, 1fr); } }
.guestbook-grid img { width: 100%; height: auto; display: block; }
.guestbook-grid figcaption { font-size: .88rem; line-height: 1.45; margin-top: .6rem; opacity: .78; }

/* --------------------------------------------------------- the Olive Year, on the oil page
   Two columns per month, a wide row where a month has several photographs, and a caption
   under each. These lived in a <style> block in the body, which the screenshot harness
   strips along with the siblings above whatever it is photographing - so the layout had
   never actually been looked at. */
.olive-year__row { display: grid; grid-template-columns: 1fr 1fr; gap: 2.5rem;
    align-items: center; margin-bottom: 3rem; }
  .olive-year__row:nth-child(even) .olive-year__text { order: 2; }
  .olive-year__text p { max-width: 34rem; }
  .olive-year__photo img { width: 100%; height: auto; display: block; }
  .olive-year__row--wide { grid-template-columns: 1fr; }
  .olive-year__row--wide .olive-year__text p { max-width: 52rem; }
  .olive-year__row--wide .olive-year__photo { display: grid;
    grid-template-columns: repeat(3, 1fr); gap: 1rem; margin-top: 1.5rem; }
  @media (max-width: 820px) {
    .olive-year__row, .olive-year__row--wide .olive-year__photo { grid-template-columns: 1fr; }
    .olive-year__row:nth-child(even) .olive-year__text { order: 0; }
  }
