/* ==========================================================================
   Fern & Fable, styles.css
   Consumes design-tokens.css. Layout families per section, responsive,
   accessible focus, reduced-motion safe (reveal items are visible by default;
   GSAP only animates them in, so nothing hides if JS fails).
   ========================================================================== */

/* ---- Reset / base ------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-body);
  font-size: var(--step-body);
  line-height: var(--leading-body);
  color: var(--color-ink);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, svg { display: block; max-width: 100%; }
a { color: var(--color-terracotta); text-decoration: none; }
h1, h2, h3, h4 { font-family: var(--font-head); font-weight: 500; line-height: 1.1; color: var(--color-ink); }
ul, ol { list-style: none; padding: 0; }
button { font: inherit; cursor: pointer; }
:focus-visible { outline: 2px solid var(--color-terracotta); outline-offset: 3px; border-radius: 2px; }
table { border-collapse: collapse; }

.sr-only {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.skip-link {
  position: absolute; left: 16px; top: -60px; z-index: 200;
  background: var(--color-green); color: var(--color-cream);
  padding: 10px 16px; border-radius: var(--radius-sm);
  transition: top var(--dur-hover) var(--ease-hover);
}
.skip-link:focus { top: 12px; }

/* ---- Shared primitives -------------------------------------------------- */
.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-pad); }
section { scroll-margin-top: 96px; }

.eyebrow {
  font-size: var(--step-eyebrow); text-transform: uppercase;
  letter-spacing: var(--tracking-eyebrow); font-weight: 600;
  color: var(--color-terracotta); margin-bottom: var(--space-md);
}
.eyebrow--onDark { color: var(--color-cream); }
.section-title { font-size: var(--step-h2); letter-spacing: -0.01em; text-wrap: balance; }
/* Roman + italic mixed inside one headline: art direction, not emphasis, so the
   italic runs at the 400 weight the variable font actually ships italic at. */
.hero__title em, .section-title em { font-style: italic; font-weight: 400; }
/* Authored line breaks are a desktop composition device; below this the line
   would orphan a single word, so the break stands down and balance takes over. */
@media (max-width: 700px) { .br-lg { display: none; } }
.lead { font-size: var(--step-lead); color: var(--color-ink); }
.muted { color: var(--color-ink-muted); }

.figure-todo {
  font-size: var(--step-small); color: var(--color-ink-muted);
  margin-top: var(--space-sm); font-style: italic;
}
.todo-tag {
  display: inline-block; font-family: var(--font-body); font-style: normal;
  font-size: 0.7rem; font-weight: 600; letter-spacing: 0.04em; text-transform: uppercase;
  color: var(--color-terracotta); background: color-mix(in srgb, var(--color-terracotta) 8%, transparent);
  border: 1px dashed var(--color-terracotta); border-radius: 999px;
  padding: 2px 8px; vertical-align: middle;
}
.todo-tag--onDark { color: var(--color-cream); border-color: var(--color-sage); background: color-mix(in srgb, var(--color-cream) 8%, transparent); }

.link-arrow {
  font-family: var(--font-body); font-weight: 600; font-size: var(--step-small);
  color: var(--color-terracotta); align-self: start;
}
.link-arrow::after { content: " \2192"; transition: margin-left var(--dur-hover) var(--ease-hover); }
.link-arrow:hover::after { margin-left: 4px; }

/* ---- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: var(--font-body); font-weight: 600; font-size: var(--step-small);
  line-height: 1; padding: 14px 22px; border: 1.5px solid transparent;
  border-radius: var(--radius-sm); text-decoration: none;
  transition: transform var(--dur-hover) var(--ease-hover),
              box-shadow var(--dur-hover) var(--ease-hover),
              background-color var(--dur-hover) var(--ease-hover),
              color var(--dur-hover) var(--ease-hover),
              border-color var(--dur-hover) var(--ease-hover);
}
.btn--solid { background: var(--color-terracotta); color: var(--color-cream); }
.btn--solid:hover { background: var(--color-terracotta-dark); transform: translateY(-2px); box-shadow: var(--shadow-md); }
.btn--outline { border-color: var(--color-ink); color: var(--color-ink); }
.btn--outline:hover { border-color: var(--color-terracotta); color: var(--color-terracotta); transform: translateY(-2px); }
.btn--ghost { color: var(--color-ink); padding-inline: 6px; }
.btn--ghost:hover { color: var(--color-terracotta); }
.btn--onDark { border-color: var(--color-cream); color: var(--color-cream); }
.btn--onDark:hover { background: var(--color-cream); color: var(--color-green); transform: translateY(-2px); }
.btn--wide { width: 100%; padding-block: 16px; }

/* ---- Header / nav ------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: transparent;
  transition: background var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover), border-color var(--dur-hover) var(--ease-hover);
  border-bottom: 1px solid transparent;
}
.site-header.is-stuck { background: color-mix(in srgb, var(--color-bg) 90%, transparent); backdrop-filter: blur(10px); border-bottom-color: var(--color-border); box-shadow: var(--shadow-sm); }
/* Dark gradient behind the transparent header so cream text stays legible over any hero photo */
.site-header::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-ink) 55%, transparent), transparent); transition: opacity var(--dur-hover) var(--ease-hover); }
.site-header.is-stuck::before { opacity: 0; }
.site-header__inner { display: flex; align-items: center; justify-content: space-between; gap: var(--space-md); min-height: 68px; }

.wordmark { display: inline-flex; align-items: center; gap: 10px; font-family: var(--font-head); font-weight: 600; font-size: 1.35rem; color: var(--color-ink); }
.wordmark__sprig { width: 26px; height: 26px; color: var(--color-green); }
.wordmark--onDark { color: var(--color-cream); }
.wordmark--onDark .wordmark__sprig { color: var(--color-sage); }

.primary-nav { display: flex; align-items: center; gap: var(--space-xl); }
.primary-nav__list { display: flex; align-items: center; gap: var(--space-lg); }
.primary-nav__list a { color: var(--color-ink); font-weight: 500; position: relative; padding-block: 6px; }
.primary-nav__list a::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 0;
  background: var(--color-terracotta); transition: width var(--dur-hover) var(--ease-hover);
}
.primary-nav__list a:hover::after, .primary-nav__list a:focus-visible::after { width: 100%; }

.nav-toggle { display: none; flex-direction: column; gap: 5px; padding: 10px; background: none; border: 0; }
.nav-toggle__bar { width: 24px; height: 2px; background: var(--color-ink); transition: transform var(--dur-hover) var(--ease-hover), opacity var(--dur-hover) var(--ease-hover); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { transform: rotate(-45deg); }

/* ---- Persistent enquiry pill (mobile only) ------------------------------ */
.order-pill {
  position: fixed; right: 16px; bottom: 16px; z-index: 200;
  display: none; align-items: center; min-height: 48px;
  background: var(--color-terracotta); color: var(--color-cream);
  font-family: var(--font-body); font-weight: 600; font-size: var(--step-small);
  padding: 14px 22px; border-radius: 999px; box-shadow: var(--shadow-md);
  opacity: 0; transform: translateY(12px); pointer-events: none; visibility: hidden;
  transition: opacity var(--dur-hover) var(--ease-hover), transform var(--dur-hover) var(--ease-hover), visibility var(--dur-hover) var(--ease-hover);
}
.order-pill.is-visible { opacity: 1; transform: none; pointer-events: auto; visibility: visible; }
@media (max-width: 768px) { .order-pill { display: inline-flex; } }

/* ---- Hero (full-bleed photograph + overlay) ---------------------------- */
/* The ground colour matters before the hero photograph paints: without it the
   cream headline sits on white and is invisible until a 1.1MB image arrives. */
.hero { position: relative; min-height: 92vh; min-height: 92dvh; display: flex; align-items: flex-end; overflow: hidden; background: var(--color-green); }
.hero__bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.hero__scrim { position: absolute; inset: 0; z-index: 1;
  /* The old midpoint dropped to 10% ink at 34%, which is exactly where the copy
     block starts, so the 12px eyebrow measured as low as 1.24:1 over pale
     petals. Two layers now: a horizontal wash that inks only the left column
     where the words are, over a vertical scrim. That buys the copy its 4.5:1
     without flattening the photograph on the right, which is the whole hero. */
  background:
    linear-gradient(90deg, color-mix(in srgb, var(--color-ink) 62%, transparent) 0%, color-mix(in srgb, var(--color-ink) 50%, transparent) 52%, transparent 82%),
    linear-gradient(180deg, color-mix(in srgb, var(--color-ink) 42%, transparent) 0%, color-mix(in srgb, var(--color-ink) 22%, transparent) 24%, color-mix(in srgb, var(--color-ink) 62%, transparent) 52%, color-mix(in srgb, var(--color-ink) 82%, transparent) 100%); }
/* z-index 0 puts the petal canvas *under* the scrim, not over it. It still
   paints above the photograph (same level, later in DOM), but the scrim at
   z-index 1 now dims petals and photo alike, so the contrast the scrim
   guarantees for the copy is structural instead of frame-dependent. */
.hero__fx { position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0; pointer-events: none; }
.hero__inner { position: relative; z-index: 2; padding-block: clamp(56px, 10vw, 120px); max-width: 60rem; }
.hero .eyebrow--onDark { margin-bottom: var(--space-sm); }
.hero__title { font-size: var(--step-hero); line-height: 1.0; letter-spacing: -0.02em; color: var(--color-cream); margin-bottom: var(--space-md); text-wrap: balance; }
.hero__sub { max-width: 44ch; font-size: var(--step-lead); color: color-mix(in srgb, var(--color-cream) 92%, transparent); margin-bottom: var(--space-xl); }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-md); }

/* Header sits over the hero photo: cream until scrolled past it (.is-stuck) */
.site-header .wordmark, .site-header .primary-nav__list a { color: var(--color-cream); }
.site-header .wordmark__sprig { color: var(--color-cream); }
.site-header .primary-nav__list a::after { background: var(--color-cream); }
.site-header .btn--outline { border-color: var(--color-cream); color: var(--color-cream); }
.site-header .btn--outline:hover { background: var(--color-cream); color: var(--color-green); border-color: var(--color-cream); }
.site-header .nav-toggle__bar { background: var(--color-cream); }
.site-header.is-stuck .wordmark, .site-header.is-stuck .primary-nav__list a { color: var(--color-ink); }
.site-header.is-stuck .wordmark__sprig { color: var(--color-green); }
.site-header.is-stuck .primary-nav__list a::after { background: var(--color-terracotta); }
.site-header.is-stuck .btn--outline { border-color: var(--color-ink); color: var(--color-ink); }
.site-header.is-stuck .btn--outline:hover { border-color: var(--color-terracotta); color: var(--color-terracotta); background: transparent; }
.site-header.is-stuck .nav-toggle__bar { background: var(--color-ink); }

/* ---- Services (sticky intro + specimen grid) --------------------------- */
.services__inner { display: grid; grid-template-columns: minmax(220px, 0.85fr) 2fr; gap: clamp(32px, 5vw, 72px); align-items: start; }
.services__intro { position: sticky; top: 104px; }
.services__lede { max-width: 34ch; margin-top: var(--space-md); }

.specimen-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: var(--space-lg); }
.specimen {
  display: flex; flex-direction: column; gap: var(--space-xs);
  background: var(--color-surface); border: 1px solid var(--color-border);
  border-radius: var(--radius-md); padding: var(--space-md);
  box-shadow: var(--shadow-sm); transition: transform var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover);
}
.specimen:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.specimen__no { font-family: var(--font-body); font-size: var(--step-eyebrow); letter-spacing: 0.14em; text-transform: uppercase; color: var(--color-ink-muted); }
.specimen__photo { display: block; aspect-ratio: 4 / 3; overflow: hidden; border-radius: var(--radius-sm); margin-bottom: var(--space-2xs); background: var(--color-surface-alt); }
.specimen__photo img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease-hover); }
.specimen:hover .specimen__photo img { transform: scale(1.05); }
.specimen__name { font-size: var(--step-h4); }
.specimen__blurb { color: var(--color-ink-muted); font-size: var(--step-small); flex: 1; }
.specimen__price { font-variant-numeric: tabular-nums; font-weight: 600; font-size: var(--step-small); display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }

/* ---- About (photo + editorial text) ------------------------------------ */
.about__inner { display: grid; grid-template-columns: 0.85fr 1.15fr; gap: clamp(32px, 5vw, 80px); align-items: center; }
.about__figure { margin: 0; overflow: hidden; border-radius: var(--radius-torn); box-shadow: var(--shadow-md); aspect-ratio: 4 / 5; }
.about__figure img { width: 100%; height: 100%; object-fit: cover; display: block; }
.about__body { max-width: var(--measure); }
.about__body p { margin-top: var(--space-md); color: var(--color-ink); }
.pullquote {
  font-family: var(--font-head); font-style: italic; font-weight: 400;
  font-size: var(--step-h3); line-height: 1.25; color: var(--color-green);
  border-left: 3px solid var(--color-sage); padding-left: var(--space-md);
  margin-block: var(--space-lg);
}

/* ---- Gallery (portfolio) ----------------------------------------------- */
.gallery { background: var(--color-surface-alt); }
.gallery__head { margin-bottom: var(--space-xl); max-width: var(--measure); }
.gallery__grid { display: grid; grid-template-columns: repeat(3, 1fr); grid-auto-rows: 17rem; grid-auto-flow: dense; gap: var(--space-sm); }
.gallery__item { margin: 0; overflow: hidden; border-radius: var(--radius-md); box-shadow: var(--shadow-sm); }
.gallery__item--tall { grid-row: span 2; }
.gallery__item--wide { grid-column: span 2; }
.gallery__item img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 0.6s var(--ease-hover); }
.gallery__item:hover img { transform: scale(1.05); }

/* ---- Social proof (green band) ----------------------------------------- */
.proof { background: var(--color-green); color: var(--color-cream); padding-block: var(--section-pad); text-align: center; }
.proof :focus-visible { outline-color: var(--color-cream); }
.proof__inner { max-width: 62ch; }
.proof__divider { width: 30px; height: 30px; color: var(--color-sage); margin: var(--space-md) auto var(--space-lg); }
.proof__quote { font-family: var(--font-head); font-style: italic; font-size: var(--step-h3); line-height: 1.35; }
.proof__quote[hidden] { display: none; }
.proof__quote cite { display: block; font-family: var(--font-body); font-style: normal; font-size: var(--step-small); font-weight: 600; color: var(--color-cream); margin-top: var(--space-md); }
.proof__dots { display: flex; justify-content: center; gap: 12px; margin-top: var(--space-xl); }
.proof__dot { width: 12px; height: 12px; border-radius: 999px; border: 1.5px solid var(--color-cream); background: transparent; padding: 0; transition: background var(--dur-hover) var(--ease-hover); }
.proof__dot.is-active { background: var(--color-cream); border-color: var(--color-cream); }

/* ---- Visit (split utility panel, offset card) -------------------------- */
.visit { background: var(--color-surface-alt); }
.visit__inner { display: grid; grid-template-columns: 1fr 1fr; align-items: center; gap: var(--space-xl); }
.visit__media { margin: 0; overflow: hidden; border-radius: var(--radius-lg); box-shadow: var(--shadow-md); aspect-ratio: 5 / 4; }
.visit__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.visit__card { background: var(--color-surface); border: 1px solid var(--color-border); border-radius: var(--radius-lg); box-shadow: var(--shadow-lg); padding: clamp(24px, 3vw, 40px); }
.visit__address { margin-block: var(--space-sm) var(--space-md); color: var(--color-ink-muted); }
.hours { width: 100%; font-variant-numeric: tabular-nums; margin-bottom: var(--space-2xs); }
.hours th, .hours td { padding: 10px 0; border-bottom: 1px solid var(--color-border); text-align: left; font-weight: 500; }
.hours td { text-align: right; color: var(--color-ink-muted); }
.hours__note { margin-bottom: var(--space-md); }
.visit__actions { display: flex; flex-wrap: wrap; gap: var(--space-sm); margin-top: var(--space-md); }

/* ---- Contact (centered invitation on textured bone) -------------------- */
.contact { position: relative; padding-block: var(--section-pad); text-align: center; overflow: hidden; }
.contact::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: radial-gradient(circle at 1px 1px, var(--color-clay) 1px, transparent 0);
  background-size: 22px 22px; opacity: 0.05;
}
/* Same trap as the section heads: a ch measure on the element that also carries
   .container beats .container's own max-width and collapses the box (gutters
   included), which had squeezed the enquiry form to a quarter of the viewport.
   The measure goes on the prose; the form gets room to work. */
.contact__inner { position: relative; z-index: 1; }
.contact__inner > .eyebrow, .contact__inner > .section-title, .contact__lede { max-width: 56ch; margin-inline: auto; }
.contact-form, .booking__success { max-width: 42rem; margin-inline: auto; }
.contact__lede { color: var(--color-ink-muted); margin-block: var(--space-md) var(--space-xl); }
.contact-form { display: grid; grid-template-columns: 1fr 1fr; gap: var(--space-md); text-align: left; }
.field { display: flex; flex-direction: column; gap: 6px; }
.field--full { grid-column: 1 / -1; }
.field label { font-size: var(--step-small); font-weight: 600; }
.field input, .field textarea, .field select {
  font: inherit; font-size: var(--step-small); color: var(--color-ink);
  background: var(--color-surface); border: 1px solid var(--color-field-border);
  border-radius: var(--radius-sm); padding: 12px 14px; width: 100%; resize: vertical;
  min-height: 48px;
  transition: border-color var(--dur-hover) var(--ease-hover), box-shadow var(--dur-hover) var(--ease-hover);
}
/* A UA-rendered select would be the one untokenized control on the page, in
   Arial at 13px and 19px tall: a banned face and under the 24px target size. */
.field select { appearance: none; padding-right: 40px; }
/* The chevron is a *mask*, so its colour is painted by the token rather than
   frozen as a hex copy inside the data-URI (a data-URI cannot read a custom
   property). The SVG carries geometry only: no fill attribute means opaque,
   and mask-mode match-source reads that as alpha. */
.select-shell { position: relative; display: block; }
.select-shell::after {
  content: ""; position: absolute; right: 16px; top: 50%; margin-top: -4px;
  width: 12px; height: 8px; pointer-events: none;
  background-color: var(--color-ink-muted);
  -webkit-mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='8'%20viewBox='0%200%2012%208'%3E%3Cpath%20d='M1.06%200.94L6%205.88L10.94%200.94L12%202L6%208L0%202Z'/%3E%3C/svg%3E");
          mask-image: url("data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20width='12'%20height='8'%20viewBox='0%200%2012%208'%3E%3Cpath%20d='M1.06%200.94L6%205.88L10.94%200.94L12%202L6%208L0%202Z'/%3E%3C/svg%3E");
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: 12px 8px; mask-size: 12px 8px;
}
.field input:focus, .field textarea:focus, .field select:focus { outline: none; border-color: var(--color-terracotta); box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-terracotta) 18%, transparent); }
.contact-form .btn--wide { grid-column: 1 / -1; }
.form-note { grid-column: 1 / -1; text-align: center; color: var(--color-ink-muted); font-size: var(--step-small); }

/* ---- Booking module hooks (library/booking-form) ------------------------ */
/* Honeypot: removed visually and from the accessibility tree (aria-hidden in
   the markup), so only a bot can fill it. */
.booking__hp { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

.booking__hint { font-weight: 400; color: var(--color-ink-muted); }
.booking__error { font-size: var(--step-small); color: var(--color-error); display: none; margin-top: 4px; }
.booking__field.is-invalid .booking__error { display: block; }
.booking__field.is-invalid input, .booking__field.is-invalid textarea, .booking__field.is-invalid select { border-color: var(--color-error); }

.booking__summary {
  grid-column: 1 / -1; display: none;
  border: 1px solid var(--color-error); border-left-width: 4px; border-radius: var(--radius-sm);
  padding: 12px 14px; font-size: var(--step-small); color: var(--color-error);
  background: color-mix(in srgb, var(--color-error) 7%, var(--color-surface));
  text-align: left;
}
.booking__summary.is-visible { display: block; }

.booking__turnstile { grid-column: 1 / -1; }
.booking__turnstile:empty { display: none; }

.booking__success {
  display: none; text-align: center; padding: var(--space-2xl) var(--space-lg);
  border: 1px solid color-mix(in srgb, var(--color-ok) 40%, transparent);
  border-radius: var(--radius-md);
  background: color-mix(in srgb, var(--color-ok) 6%, var(--color-surface));
}
.booking__success.is-visible { display: block; }
.booking__success h3 { font-family: var(--font-head); font-size: var(--step-h3); color: var(--color-ok); margin-bottom: var(--space-2xs); }
.booking__success p { color: var(--color-ink-muted); }
.booking.is-done .contact-form { display: none; }

/* The contact section centers its text; the form fields stay left aligned. */
.contact .booking__field { text-align: left; }

/* ---- Footer (deep green multicolumn) ----------------------------------- */
.site-footer { background: var(--color-green); color: var(--color-cream); padding-block: var(--space-3xl) var(--space-xl); }
.site-footer :focus-visible { outline-color: var(--color-cream); }
.site-footer__inner { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1.4fr; gap: var(--space-xl); }
.site-footer__brand p { color: color-mix(in srgb, var(--color-cream) 82%, transparent); margin-top: var(--space-sm); max-width: 32ch; }
.site-footer__h { font-family: var(--font-body); font-size: var(--step-eyebrow); text-transform: uppercase; letter-spacing: 0.14em; color: var(--color-cream); margin-bottom: var(--space-md); }
.site-footer__col ul { display: flex; flex-direction: column; gap: 10px; }
.site-footer__col a, .site-footer__col li { color: var(--color-cream); }
.site-footer__col a { position: relative; }
.site-footer__col a:hover { text-decoration: underline; text-decoration-color: var(--color-sage); text-underline-offset: 4px; }
.site-footer__col .btn { margin-top: var(--space-xs); }
.site-footer__social { margin-top: var(--space-md); }
.site-footer__base {
  max-width: var(--container); margin: var(--space-2xl) auto 0; padding: var(--space-md) var(--gutter) 0;
  border-top: 1px solid color-mix(in srgb, var(--color-sage) 40%, transparent);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: var(--space-sm);
  font-size: var(--step-small); color: color-mix(in srgb, var(--color-cream) 78%, transparent);
}

/* ---- Responsive --------------------------------------------------------- */
@media (max-width: 1024px) {
  .services__inner { grid-template-columns: 1fr; }
  .services__intro { position: static; }
  .about__inner { grid-template-columns: 1fr; }
  .about__figure { aspect-ratio: 16 / 10; max-width: 620px; }
  .site-footer__inner { grid-template-columns: 1fr 1fr; gap: var(--space-xl); }
}

/* Gallery, tablet band: the fixed row track and the column spans are both
   3-column devices. Rather than flatten every photograph into one repeated
   rectangle, the grid becomes a real two-column masonry and each arrangement
   is shown at its own height, uncropped. Five of the six sources are portrait,
   so this is also the only treatment that does not throw away the flowers. */
@media (max-width: 1024px) and (min-width: 561px) {
  .gallery__grid { display: block; columns: 2; column-gap: var(--space-sm); }
  .gallery__item { break-inside: avoid; margin-bottom: var(--space-sm); border-radius: var(--radius-md); }
  .gallery__item img { height: auto; }
}

@media (max-width: 768px) {
  .nav-toggle { display: flex; }
  .primary-nav {
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: var(--space-md);
    background: var(--color-bg); border-bottom: 1px solid var(--color-border);
    padding: var(--space-md) var(--gutter) var(--space-lg);
    box-shadow: var(--shadow-md);
    clip-path: inset(0 0 100% 0); opacity: 0; pointer-events: none; visibility: hidden;
    transition: clip-path var(--dur-hover) var(--ease-hover), opacity var(--dur-hover) var(--ease-hover), visibility 0s linear var(--dur-hover);
  }
  .primary-nav.is-open { clip-path: inset(0 0 0 0); opacity: 1; pointer-events: auto; visibility: visible; transition: clip-path var(--dur-hover) var(--ease-hover), opacity var(--dur-hover) var(--ease-hover), visibility 0s; }
  .primary-nav__list { flex-direction: column; align-items: stretch; gap: var(--space-sm); }
  /* Narrow: the copy spans the full column width, so a left-weighted wash
     cannot cover its right edge (measured: the eyebrow's last words fell to
     2.97:1 at 375). The scrim goes purely vertical and is already at 0.74 ink
     where the copy starts at 31% of the hero, which holds 4.5:1 for cream text
     even over a pure-white pixel, so it survives whatever photograph replaces
     the placeholder at launch. */
  .hero__scrim {
    background: linear-gradient(180deg,
      color-mix(in srgb, var(--color-ink) 36%, transparent) 0%,
      color-mix(in srgb, var(--color-ink) 15%, transparent) 15%,
      color-mix(in srgb, var(--color-ink) 42%, transparent) 24%,
      color-mix(in srgb, var(--color-ink) 74%, transparent) 31%,
      color-mix(in srgb, var(--color-ink) 80%, transparent) 60%,
      color-mix(in srgb, var(--color-ink) 90%, transparent) 100%);
  }
  /* nav sheet is bone: force ink text regardless of the over-hero header state */
  .site-header .primary-nav__list a { color: var(--color-ink); }
  .site-header .primary-nav__list a::after { display: none; }
  .site-header .btn--outline { border-color: var(--color-ink); color: var(--color-ink); }
  .specimen-grid { grid-template-columns: 1fr; }
  .visit__inner { grid-template-columns: 1fr; }
  .contact-form { grid-template-columns: 1fr; }
  .site-footer__inner { grid-template-columns: 1fr; gap: var(--space-lg); }
}

/* Gallery, phone: one column, but the tiles alternate shape so the section
   never reads as the same rectangle six times. The portraits stay portrait,
   and the one landscape source keeps its own 3:2. */
@media (max-width: 560px) {
  .gallery__grid { grid-template-columns: 1fr; grid-auto-rows: auto; }
  .gallery__item { aspect-ratio: 4 / 5; grid-row: auto; grid-column: auto; }
  .gallery__item:nth-child(even) { aspect-ratio: 1 / 1; }
  .gallery__item.gallery__item--wide { aspect-ratio: 3 / 2; }
}

/* ---- Reveal on scroll (JS-gated so no-JS shows everything) -------------- */
.js [data-reveal-item] { opacity: 0; transform: translateY(24px); transition: opacity 0.7s ease, transform 0.7s ease; }
.js [data-reveal-item].is-in { opacity: 1; transform: none; }

/* ---- Reduced motion ----------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
  .js [data-reveal-item] { opacity: 1 !important; transform: none !important; animation: none !important; }
}
