/* ==========================================================================
   Shoreline Design — site styles
   --------------------------------------------------------------------------
   The colours below are the ONLY place colours are defined. Change one here
   and it updates everywhere on every page.
   ========================================================================== */

:root {
  --bg:      #FAF9F7;  /* page background (warm off-white) */
  --panel:   #FCFAF6;  /* service cards, thank-you panel — warmed one notch (F6) */
  --ink:     #1a1a1a;  /* headings and body text */
  --muted:   #6E6862;  /* secondary text — warmed from #6b6b6b (F6); re-check
                          contrast pairs before warming further */
  --line:    #e8e6e3;  /* borders and dividers */
  --accent:  #c4a77d;  /* gold accent: numbers, button hover */
  --error:   #c0392b;  /* form validation red */

  --heading: 'Cormorant Garamond', Georgia, serif;
  --body:    'Manrope', -apple-system, BlinkMacSystemFont, sans-serif;
  --mono:    'IBM Plex Mono', monospace;
}

* { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Smooth scrolling is motion: a reduced-motion preference turns it off, so
   in-page anchors jump instead of animating. The fragment lander already
   scrolls instantly for everyone. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  min-height: 100vh;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--body);
  position: relative;
  overflow-x: hidden;
}

img { max-width: 100%; }


/* ===== Navigation ======================================================== */

.site-nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  padding: clamp(16px, 3.5vw, 36px) clamp(18px, 4vw, 48px);
  z-index: 100;
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  /* Opaque by default (A2): inner pages have no hero, and a transparent fixed
     header draws the logo on top of whatever scrolls beneath it. */
  background: var(--bg);
  border-bottom: 1px solid var(--line);
}

/* The home page only: no bar, ever. The logo and phone fade out with scroll
   (below), so nothing but the hamburger remains to overlap content — a bar
   would just draw a white strip over the hero. Inner pages keep the opaque
   header; they have a permanent logo to protect (A2). */
.site-nav--overhero {
  background: transparent;
  border-bottom: none;
}

/* The phone fades with the logo on the home page. site.js adds
   .site-nav--faded once the fade is done, which is what stops an invisible
   tel: link starting a phone call from a blank corner of the screen. */
.site-nav--overhero .site-nav__phone {
  opacity: var(--nav-opacity, 1);
  transition: opacity .2s linear;
}
.site-nav--faded .site-nav__logo,
.site-nav--faded .site-nav__phone { pointer-events: none; }

/* The same guarantee the hero scrim gives the logo, for the one control that
   never fades: once the home header has no bar, the ink hamburger can land
   on anything the page scrolls past — measured 1.07:1 over the dark town in
   the values photo at 390px. A backing pill fades in as the header fades
   out, so at the top it does not exist and scrolled it floors the contrast
   at ~13:1 whatever sits behind it. */
.site-nav--overhero .nav-toggle {
  background: rgba(250, 249, 247, calc((1 - var(--nav-opacity, 1)) * .92));
  border-radius: 4px;
  padding: 0 8px;
  width: 60px;
  margin-right: -8px;
}

/* --nav-opacity is driven by site.js so the logo fades out as you scroll
   past the hero video. Inner pages have no hero, so it stays at 1. */
.site-nav__logo,
.site-nav__links {
  opacity: var(--nav-opacity, 1);
  transition: opacity .2s linear;
}

.site-nav__logo a { display: block; }
.site-nav__logo img { height: auto; width: clamp(160px, 28vw, 370px); display: block; }

.site-nav__links {
  display: flex;
  flex-wrap: wrap;
  justify-content: flex-end;
  gap: clamp(12px, 2.5vw, 32px);
  font-size: clamp(12px, 1.4vw, 14px);
  letter-spacing: .02em;
}

.site-nav__links a {
  color: var(--ink);
  text-decoration: none;
  font-weight: 700;
  opacity: .8;
  transition: opacity .2s;
}
.site-nav__links a:hover { opacity: 1; }


/* ===== Hero ============================================================== */

.hero {
  position: relative;
  width: 100%;
  height: 100vh;
  min-height: clamp(520px, 100vh, 900px);
  overflow: hidden;
  background: var(--bg);
}

.hero video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

/* Fades the bottom of the video into the section below it. */
.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  /* Top band darkened (A3): the white logo and hamburger must survive the
     montage's brightest beach frames, not just the night skyline. The bottom
     fade into the page background is unchanged. */
  background: linear-gradient(
    to bottom,
    rgba(26, 26, 26, .40) 0%,
    rgba(26, 26, 26, 0) 26%,
    rgba(250, 249, 247, 0) 80%,
    rgba(250, 249, 247, .35) 100%
  );
}


/* The headline over the video (B3). Its own contained scrim, because the
   hero's top scrim protects the header and the bottom fade is off-white —
   neither guarantees this corner over every montage frame. */
.hero__content {
  position: absolute;
  left: clamp(20px, 5vw, 64px);
  bottom: clamp(48px, 10vh, 110px);
  z-index: 2;
  max-width: 640px;
  padding: clamp(20px, 3vw, 32px);
  background: linear-gradient(to right, rgba(26, 26, 26, .45), rgba(26, 26, 26, .18) 70%, rgba(26, 26, 26, 0));
}

.hero__content h1 {
  font-family: var(--heading);
  font-size: clamp(28px, 4.6vw, 52px);
  font-weight: 400;
  letter-spacing: -.01em;
  line-height: 1.15;
  color: #FAF9F7;
  margin: 0 0 12px;
}

/* The category line, demoted beneath the outcome headline (VOICE-BRIEF V1). */
.hero__support {
  font-size: clamp(13px, 1.5vw, 15px);
  letter-spacing: .06em;
  color: rgba(250, 249, 247, .85);
  margin: 0 0 22px;
}

.hero__cta {
  display: inline-block;
  color: #FAF9F7;
  text-decoration: none;
  font-size: clamp(13px, 1.5vw, 15px);
  letter-spacing: .08em;
  text-transform: uppercase;
  border: 1px solid rgba(250, 249, 247, .7);
  padding: 12px 22px;
  transition: background .2s, color .2s;
}
.hero__cta:hover { background: #FAF9F7; color: var(--ink); }


/* ===== Generic section shell ============================================= */

.section {
  width: 100%;
  padding: clamp(56px, 8vw, 120px) clamp(20px, 4vw, 48px);
  background: var(--bg);
}

.section__inner { max-width: 1200px; margin: 0 auto; }

/* Inner pages (about.html etc.) need clearance under the fixed nav bar. */
.section--page-top { padding-top: clamp(110px, 15vw, 200px); }

.section-title {
  font-family: var(--heading);
  font-size: clamp(32px, 5vw, 48px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.2;
  color: var(--ink);
  text-align: center;
  margin: 0 0 clamp(40px, 6vw, 80px);
}

/* The small gold "01 / 02 / 03" labels. */
.eyebrow {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .1em;
  color: var(--accent);
  text-transform: uppercase;
  margin-bottom: 12px;
}


/* ===== Services grid ===================================================== */

.services-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 24px;
}

.service-card {
  background: var(--panel);
  border-radius: 4px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.service-card__img {
  width: 100%;
  height: clamp(200px, 24vw, 280px);
  overflow: hidden;
  background-size: cover;
  background-position: center;
  transition: transform .6s ease;
}
.service-card__img:hover { transform: scale(1.04); }

.service-card__body { padding: 32px 24px; }

/* The three promoted cards (B2). Fixed three-up so the hierarchy reads as
   deliberate; stacks at tablet width. */
.services-grid--featured { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .services-grid--featured { grid-template-columns: 1fr; } }

/* A whole card as its link. Text colours are restated because this is an
   <a> now, and default link styling would repaint the card blue. */
.service-card--link { text-decoration: none; color: inherit; }
.service-card__more {
  display: inline-block;
  margin-top: 14px;
  font-size: 13px;
  letter-spacing: .06em;
  color: var(--accent);
}
.service-card--link:hover .service-card__more { color: var(--ink); }

/* The five demoted services (C1): one quiet band, icon above, label below.
   Icons inherit text colour via stroke="currentColor", so the band cannot
   drift off-palette. */
.services-band {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: clamp(24px, 4vw, 56px);
  margin-top: clamp(36px, 5vw, 56px);
  padding-top: clamp(28px, 4vw, 40px);
  border-top: 1px solid var(--line);
}

.services-band__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 10px;
  color: var(--muted);
  min-width: 110px;
}
.services-band__item span { font-size: 13px; letter-spacing: .04em; text-align: center; }

/* One link under the whole group, not a button per item (C5). */
.services-band__cta { text-align: center; margin: 28px 0 0; font-size: 14px; }
.services-band__cta a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line); padding-bottom: 2px; }
.services-band__cta a:hover { color: var(--ink); border-bottom-color: var(--muted); }

.service-card h3 {
  font-family: var(--heading);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--ink);
  margin: 0 0 12px;
}

.service-card p {
  font-size: 15px;
  line-height: 1.6;
  color: var(--muted);
  margin: 0;
}


/* ===== Values (photo background with off-white wash) ===================== */

.values {
  width: 100%;
  padding: clamp(72px, 11vw, 160px) clamp(20px, 4vw, 48px);
  position: relative;
  overflow: hidden;
  /* No wash at all — the photo exactly as shot.
     To bring the wash back, put a gradient above the url() again, e.g.
       linear-gradient(to bottom,
         rgba(250,249,247,1) 0%, rgba(250,249,247,.39) 18%,
         rgba(250,249,247,.39) 82%, rgba(250,249,247,1) 100%),
     and re-check .value-card p — the two move together. */
  background-image: url('../img/values-background.jpg');
  background-size: cover;
  /* Anchored to the BOTTOM, not the centre. The top ~40% of this photo is
     sun haze brighter than the off-white page background, so centring it
     filled the section with something indistinguishable from blank. Anchoring
     low keeps the coastline and town — the part worth showing — and lets the
     haze fall outside the crop. */
  background-position: center bottom;
  background-attachment: scroll;
}

.values__inner { position: relative; z-index: 2; max-width: 1200px; margin: 0 auto; }

/* Same floor as the cards, for the one line of text not on one. */
.values .section-title {
  display: table;
  margin-left: auto;
  margin-right: auto;
  padding: 8px 28px;
  background: rgba(250, 249, 247, .85);
}

.values-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 32px;
}

/* The copy sits on translucent panels rather than on the photograph (A5).
   The photo shows at full strength between and around the cards; behind the
   text it is lifted to a floor the copy can pass 4.5:1 on. Measured against
   the darkest patch of values-background.jpg (rgb(58,59,57)): under .85
   off-white the effective background is rgb(225,225,224) and #333 body copy
   reads 9.7:1. Lighten this alpha and re-check that pair. */
.value-card {
  text-align: center;
  padding: 32px 24px;
  background: rgba(250, 249, 247, .85);
  border: 1px solid rgba(232, 230, 227, .6);
}

.value-card .eyebrow { font-size: 11px; letter-spacing: .15em; margin-bottom: 20px; }

.value-card h3 {
  font-family: var(--heading);
  font-size: 20px;
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--ink);
  margin: 0 0 16px;
}

/* Darker than --muted (#6b6b6b) everywhere else on the site, and deliberately
   so: this is the only body copy in front of a photograph. There is no wash
   on the photo any more — the copy sits on the .value-card panels above,
   rgba(250,249,247,.85), and it is that panel alpha and this colour that
   move together. Measured over the photo's darkest patch (rgb(58,59,57)),
   the panel floors the background at rgb(225,225,224) and #333 reads 9.7:1.
   Lighten the panel alpha or swap in a darker photo, re-check the pair. */
.value-card p { font-size: 15px; line-height: 1.7; color: #333; margin: 0; }


/* ===== Enquiry form ====================================================== */

.enquire__inner { max-width: 600px; margin: 0 auto; text-align: center; }

.enquire h2 {
  font-family: var(--heading);
  font-size: clamp(28px, 4.2vw, 40px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.2;
  color: var(--ink);
  margin: 0 0 16px;
}

.enquire__lede { font-size: 16px; line-height: 1.6; color: var(--muted); margin: 0 0 48px; }

/* Shown only after a successful submit (site.js swaps these). */
.thanks {
  display: none;
  background: var(--panel);
  border-radius: 4px;
  padding: 48px;
  border: 1px solid var(--line);
}
.thanks__title {
  font-family: var(--heading);
  font-size: 24px;
  font-weight: 500;
  color: var(--ink);
  margin-bottom: 12px;
}
.thanks p { font-size: 15px; color: var(--muted); margin: 0; }

.is-submitted .thanks { display: block; }
.is-submitted .form   { display: none; }

.form { display: flex; flex-direction: column; gap: 24px; text-align: left; }

.form__row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
  gap: 24px;
}

.form label {
  display: block;
  font-size: 12px;
  font-weight: 500;
  letter-spacing: .05em;
  color: var(--muted);
  text-transform: uppercase;
  margin-bottom: 8px;
}

.form input,
.form select,
.form textarea {
  width: 100%;
  padding: 14px 0;
  background: transparent;
  border: none;
  border-bottom: 1px solid var(--line);
  border-radius: 0;
  color: var(--ink);
  font-size: 16px;
  font-family: var(--body);
  outline: none;
  transition: border-color .2s;
}

.form input:focus,
.form select:focus,
.form textarea:focus { border-bottom-color: var(--accent); }

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

.form select {
  cursor: pointer;
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2 4l4 4 4-4' fill='none' stroke='%236b6b6b' stroke-width='1.5'/></svg>");
  background-repeat: no-repeat;
  background-position: right center;
}
/* Greys the placeholder option until a real choice is made. */
.form select:invalid { color: var(--muted); }

.field__error {
  display: none;
  margin-top: 8px;
  font-size: 12px;
  color: var(--error);
  letter-spacing: .02em;
}

.field--error label { color: var(--error); }
.field--error input,
.field--error select,
.field--error textarea { border-bottom-color: var(--error); }
.field--error .field__error { display: block; }

.btn {
  padding: 18px 40px;
  background: var(--ink);
  color: var(--bg);
  border: none;
  border-radius: 8px;
  font-family: var(--body);
  font-size: 13px;
  font-weight: 500;
  letter-spacing: .1em;
  text-transform: uppercase;
  cursor: pointer;
  margin-top: 16px;
  align-self: center;
  transition: all .4s cubic-bezier(.4, 0, .2, 1);
  box-shadow: 0 2px 8px rgba(0, 0, 0, .1);
}

.btn:hover {
  background: var(--accent);
  transform: scale(1.02);
  box-shadow: 0 8px 24px rgba(196, 167, 125, .25);
}

/* The button label swaps from "Let's build" to "Your Vision" on hover. */
.btn__label--hover { display: none; }
.btn:hover .btn__label--default { display: none; }
.btn:hover .btn__label--hover   { display: inline; }


/* ===== Footer ============================================================ */

.site-footer {
  padding: clamp(40px, 6vw, 60px) clamp(20px, 4vw, 48px);
  border-top: 1px solid var(--line);
  background: var(--bg);
}

/* The enquiry honeypot. Deliberately NOT .sr-only: that class exists to be
   read aloud, and a visitor using a screen reader who filled this in would
   have their enquiry quietly dropped. This one is hidden from everybody —
   off-screen, untabbable, and its wrapper carries aria-hidden. */
.form__hp {
  position: absolute;
  left: -9999px;
  width: 1px; height: 1px;
  overflow: hidden;
}

/* Visible to Google and screen readers, not on screen. Used for the home
   page heading, where the hero is a video with no text in it. */
.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;
}

/* Phone, email and location — the things a customer looks for first. */
.site-footer__contact {
  max-width: 1200px;
  margin: 0 auto clamp(28px, 4vw, 40px);
  padding-bottom: clamp(24px, 3.5vw, 34px);
  border-bottom: 1px solid var(--line);
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: 20px;
}
/* The icon sits above the label (C3). currentColor keeps it on-palette. */
.site-footer__contact svg {
  display: block;
  color: var(--accent);
  margin-bottom: 10px;
}
.site-footer__contact span {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--muted);
  margin-bottom: 6px;
}
.site-footer__contact a,
.site-footer__contact strong {
  font-size: clamp(15px, 1.7vw, 17px);
  font-weight: 400;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--heading);
  letter-spacing: -.01em;
}
.site-footer__contact a:hover { color: var(--accent); }

.site-footer__top {
  max-width: 1200px;
  margin: 0 auto;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 24px;
}

/* Sized by width so it stays in proportion with the header logo (A6). The
   SVG is 1676×341; height: auto keeps that ratio exact. Only ever set one
   axis — setting both is how a logo actually gets squashed. */
.site-footer__top img { width: clamp(200px, 26vw, 340px); height: auto; display: block; }

.site-footer__links {
  display: flex;
  flex-wrap: wrap;
  gap: 32px;
  font-size: 13px;
  letter-spacing: .02em;
}

.site-footer__links a { color: var(--muted); text-decoration: none; transition: color .2s; }
.site-footer__links a:hover { color: var(--ink); }

.site-footer__legal {
  max-width: 1200px;
  margin: 40px auto 0;
  padding-top: 24px;
  border-top: 1px solid var(--line);
  font-size: 12px;
  color: var(--muted);
  letter-spacing: .02em;
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}

/* Deliberately understated — it's for staff, not customers. */
.staff-link {
  color: var(--muted);
  text-decoration: none;
  border: 1px solid var(--line);
  border-radius: 100px;
  padding: 6px 14px;
  transition: color .2s, border-color .2s;
  white-space: nowrap;
}
.staff-link:hover { color: var(--ink); border-color: var(--muted); }


/* ===== Long-form text, used on About and any future content page ========= */

.prose { max-width: 720px; margin: 0 auto; }

.prose h2 {
  font-family: var(--heading);
  font-size: clamp(26px, 3.6vw, 34px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.2;
  color: var(--ink);
  margin: 48px 0 16px;
}
.prose h2:first-child { margin-top: 0; }

.prose p {
  font-size: 16px;
  line-height: 1.75;
  color: var(--muted);
  margin: 0 0 20px;
}

.prose a { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }


/* ===== Service landing pages =============================================
   Shared building blocks used by the subdivision delivery and feasibility
   review pages. Adding another service page means reusing these classes
   rather than writing new CSS.
   ========================================================================= */

.eyebrow-gold {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  /* Darkened from var(--accent) #c4a77d, which read 2.18:1 on the page
     ground — Lighthouse-flagged. #83704a is the same hue scaled down: the
     closest clean hex that clears 4.5:1 on both grounds (4.55:1 worst).
     --accent itself is untouched; on dark panels it is fine. */
  color: #83704a;
  margin-bottom: 18px;
}

/* Hero: words on the left, picture on the right. */
.svc-hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 5vw, 64px);
  align-items: center;
  padding: clamp(110px, 15vw, 190px) clamp(20px, 4vw, 48px) clamp(48px, 7vw, 90px);
  max-width: 1200px;
  margin: 0 auto;
}
.svc-hero h1 {
  font-family: var(--heading);
  /* Up from clamp(34px, 5.6vw, 60px) — the headline can carry more (E4). */
  font-size: clamp(40px, 6.6vw, 76px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.08;
  margin: 0 0 22px;
}
.svc-hero p { font-size: clamp(15px, 1.6vw, 17px); line-height: 1.7; color: var(--muted); margin: 0 0 30px; }
/* Full-height in its column (D4), so it holds its own against the
   full-bleed home hero instead of floating in dead margin. */
.svc-hero > div:last-child { align-self: stretch; display: flex; }
.svc-hero img { width: 100%; height: 100%; min-height: 440px; object-fit: cover; border-radius: 4px; display: block; }
@media (max-width: 860px) {
  .svc-hero { grid-template-columns: 1fr; }
  .svc-hero img { height: auto; min-height: 0; }
}

.btnrow { display: flex; flex-wrap: wrap; gap: 14px; }

.btn-solid, .btn-outline {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 16px 28px;
  border-radius: 4px;
  font-size: 13px;
  letter-spacing: .06em;
  text-decoration: none;
  transition: background .3s, color .3s, border-color .3s;
}
.btn-solid { background: var(--ink); color: var(--bg); border: 1px solid var(--ink); }
.btn-solid:hover { background: var(--accent); border-color: var(--accent); }
.btn-outline { background: transparent; color: var(--ink); border: 1px solid var(--line); }
.btn-outline:hover { border-color: var(--ink); }

/* The pale strip of value props under the hero. */
.featurebar {
  background: #f3efe8;
  padding: clamp(28px, 4vw, 44px) clamp(20px, 4vw, 48px);
}
.featurebar__inner {
  max-width: 1200px;
  margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(215px, 1fr));
  gap: clamp(20px, 3vw, 40px);
}
/* The strip labels are styled like h3s but are NOT headings: they follow an
   h1 directly and a real h3 there breaks heading order (a11y). */
.featurebar h3, .featurebar .featurebar__label { font-size: 15px; font-weight: 700; margin: 0 0 6px; font-family: var(--body); color: var(--ink); }
/* Icon above, label under (D2) — the same set, size and stroke as the
   services band on the home page, because the two rows get compared. */
.featurebar__inner--icons > div { text-align: center; }
.featurebar__inner--icons svg { color: var(--muted); margin-bottom: 10px; }
.featurebar p { font-size: 13px; line-height: 1.6; color: var(--muted); margin: 0; }

/* Card grids. Use --min to change how many fit per row. */
.tilegrid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(var(--min, 240px), 1fr));
  gap: 18px;
}
.tile {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: 28px 24px;
}
.tile h3 { font-size: 15px; font-weight: 700; font-family: var(--body); margin: 0 0 10px; letter-spacing: 0; }
.tile p { font-size: 14px; line-height: 1.65; color: var(--muted); margin: 0; }
.tile__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 30px; height: 30px;
  border-radius: 100px;
  background: #f0e7d8;
  color: #76633f; /* was #8a7248 - 3.74:1 on its own #f0e7d8 circle, a quiet fail the auditor misses; #76633f is the same family at 4.72:1 */
  font-family: var(--mono);
  font-size: 12px;
  margin-bottom: 14px;
}

/* One photograph, edge to edge (E1). The single big moment on the page —
   it breaks the 1200px container on purpose, so nothing else needs to. */
.bleed { width: 100%; overflow: hidden; }
.bleed img { display: block; width: 100%; height: clamp(320px, 52vh, 560px); object-fit: cover; }

/* The price as a display number (E2). Retired from the offer panel — the
   figure moved to the FAQ — but the rules stay in case a future page wants
   a number at this scale. */
.price__from { font-size: 12px; letter-spacing: .18em; text-transform: uppercase; margin: 0 0 4px; }
.price__figure {
  font-family: var(--heading);
  font-size: clamp(64px, 9vw, 112px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1;
  color: var(--bg);
}
.price__gst { font-size: 13px; margin: 6px 0 0; }

/* The offer panel's display element, now the reader's own question rather
   than the price. Same scale as .section-title (the page's other display
   heading) and the same --bg-on-ink pairing already used by .panel--dark
   h2, so nothing new is introduced — just reused at the size the panel's
   one big element needs to hold. */
.panel__question {
  font-family: var(--heading);
  font-size: clamp(32px, 5vw, 48px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.2;
  color: var(--bg);
  margin: 0 0 22px;
}

/* One quote at display scale (E3): no box, no border, its own section. */
.quote-display {
  max-width: 900px;
  margin: 0 auto;
  padding: clamp(8px, 2vw, 24px) 0;
  font-family: var(--heading);
  font-size: clamp(26px, 3.2vw, 42px);
  font-weight: 400;
  line-height: 1.45;
  letter-spacing: -.01em;
  text-align: center;
  color: var(--ink);
}
.quote-display cite {
  display: block;
  margin-top: 22px;
  font-family: var(--mono);
  font-style: normal;
  font-size: 12px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--muted);
}

/* Deliberate empty space (E5): one transition gets two to three times the
   breathing room of its neighbours, so the busy parts read as intentional. */
.section--breathe { padding-top: clamp(140px, 20vw, 300px); }

/* Scroll reveal (E6). The classes are applied BY JAVASCRIPT ONLY: with no
   JS, no .reveal exists and everything is simply visible. Fires once,
   never on scroll back, and prefers-reduced-motion never adds the class
   in the first place — belt and braces with the media query here. */
.reveal { opacity: 0; transform: translateY(18px); transition: opacity .34s ease-out, transform .34s ease-out; }
.reveal--in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
}

/* --- Enquiry behind a wave (ENQUIRY-WAVE-BRIEF) --------------------------- */

/* The trigger sits where the form used to be. Shared by every form-behind-
   a-dialog on the site, whatever the entrance. */
.dialog-trigger { margin-top: 8px; }

/* The panel. Native <dialog> for focus trapping, Escape and inertness. */
.wavedialog {
  border: none;
  border-radius: 6px;
  padding: clamp(24px, 4vw, 44px);
  width: min(680px, 92vw);
  max-height: 86vh;          /* short screens scroll the panel, not clip it */
  overflow-y: auto;
  background: var(--panel);
  color: var(--ink);
}
.wavedialog::backdrop { background: rgba(26, 26, 26, .55); }
.wavedialog__body h2 { margin-top: 0; }
.wavedialog__close {
  position: sticky;
  top: 0;
  float: right;
  background: none;
  border: none;
  font-size: 26px;
  line-height: 1;
  color: var(--muted);
  cursor: pointer;
  padding: 2px 6px;
}
.wavedialog__close:hover { color: var(--ink); }

/* Nothing behind the panel moves while it is open. */
html.wave-lock, html.wave-lock body { overflow: hidden; }

/* The wash. The white sheet is the guaranteed transition; the video under
   it is the garnish, and there is no video yet (see the FOOTAGE SLOT in
   site.js). Panel placement happens only at full white. */
.wave { position: fixed; inset: 0; z-index: 300; display: none; background: transparent; }
.wave--on { display: block; }
.wave video { width: 100%; height: 100%; object-fit: cover; display: block; }
.wave--recede video { display: none; }
.wave__white {
  position: absolute;
  inset: 0;
  background: #FFFFFF;
  opacity: 0;
  transition: opacity .7s ease-in;
}
.wave--cover .wave__white { opacity: 1; }
.wave--recede .wave__white { opacity: 0; transition: opacity .9s ease-out; }

/* Belt and braces with the JS check: reduced motion never sees the wash. */
@media (prefers-reduced-motion: reduce) {
  .wave { display: none !important; }
}

/* --- Booking behind a survey line (feasibility page) ---------------------
   Deliberately not the wave: this dialog draws its own perimeter and floods
   itself, rather than being revealed from behind a full-screen wash. Same
   <dialog>, same open/close, same backdrop (.wavedialog::backdrop, above) -
   only the entrance differs, and a dedicated modifier class keeps its dark
   colours self-contained rather than fighting .panel's own padding/border
   for a mixed-class element. */

.wavedialog--dark {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--bg);
  text-align: center;
  position: relative; /* the perimeter SVG sizes itself against this box */
  transition: background-color .6s ease, border-color .6s ease;
}
.wavedialog--dark.wavedialog--entering { background: transparent; border-color: transparent; }

.wavedialog--dark h2 {
  font-family: var(--heading);
  font-weight: 400;
  letter-spacing: -.02em;
  font-size: clamp(26px, 3.4vw, 36px);
  margin: 0 0 16px;
}
.wavedialog--dark p { font-size: 14px; line-height: 1.7; color: rgba(250, 249, 247, .75); margin: 0 0 12px; }
.wavedialog--dark .btn-solid { background: var(--accent); border-color: var(--accent); color: var(--ink); }
.wavedialog--dark .btn-solid:hover { background: #d8bd93; border-color: #d8bd93; }

/* The same dark-field-visibility problem the inline booking panel always
   had, restated here because the form now lives in the dialog instead. */
.wavedialog--dark .form input,
.wavedialog--dark .form select,
.wavedialog--dark .form textarea { color: var(--bg); border-bottom-color: rgba(250, 249, 247, .35); }
.wavedialog--dark .form input:focus,
.wavedialog--dark .form select:focus,
.wavedialog--dark .form textarea:focus { border-bottom-color: var(--accent); }
.wavedialog--dark .form label { color: rgba(250, 249, 247, .75); }
.wavedialog--dark .form ::placeholder { color: rgba(250, 249, 247, .45); }
.wavedialog--dark .form select:invalid { color: rgba(250, 249, 247, .55); }
.wavedialog--dark .form select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2 4l4 4 4-4' fill='none' stroke='%23FAF9F7' stroke-width='1.5'/></svg>");
}
.wavedialog--dark .form input:-webkit-autofill,
.wavedialog--dark .form input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--bg);
  -webkit-box-shadow: 0 0 0 1000px var(--ink) inset;
  caret-color: var(--bg);
}
.wavedialog--dark .form .field__error,
.wavedialog--dark .form .field--error label { color: #e88b80; }
.wavedialog--dark .form .field--error input,
.wavedialog--dark .form .field--error select,
.wavedialog--dark .form .field--error textarea { border-bottom-color: #e88b80; }

/* The traced perimeter: one hairline rect. pathLength="100" makes the dash
   values plain percentages regardless of the panel's actual size, so the
   draw is correct whatever height the content gives the dialog. Ink,
   because that is what the panel then floods with - the line and the fill
   are the same colour telling one continuous story, the way a boundary
   drawn on a survey plan precedes the block it describes. */
.surveyline { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.surveyline rect {
  fill: none;
  stroke: var(--ink);
  stroke-width: 1px;
  vector-effect: non-scaling-stroke;
  stroke-dasharray: 100;
  stroke-dashoffset: 100;
}
.wavedialog--dark.wavedialog--entering .surveyline rect { animation: surveyline-draw 1.2s ease forwards; }
@keyframes surveyline-draw { to { stroke-dashoffset: 0; } }

/* Content stays invisible until the perimeter has closed. Removing
   .wavedialog--entering lets the flood (above) and this settle run
   together, offset by a short delay so the ink arrives first and the
   fields follow into it - "the dark panel floods in behind it and the
   fields settle." */
.wavedialog--dark .wavedialog__body { transition: opacity .5s ease .3s, transform .5s ease .3s; }
.wavedialog--dark.wavedialog--entering .wavedialog__body { opacity: 0; transform: translateY(10px); }

/* Belt and braces with the JS check: reduced motion sees the panel appear
   whole, with no line, no flood, no settle. */
@media (prefers-reduced-motion: reduce) {
  .wavedialog--dark.wavedialog--entering { background: var(--ink); border-color: var(--ink); }
  .wavedialog--dark .wavedialog__body { transition: none; opacity: 1; transform: none; }
  .surveyline { display: none !important; }
}

/* Ground alternation (D3): a one-step tonal shift between the page's warm
   off-white and plain white, so consecutive sections read as blocks instead
   of running together. A step, never a stripe. */
.section--tint { background: var(--panel); }

/* Image beside the stacked checks (D1). */
.checksplit {
  display: grid;
  grid-template-columns: 1fr 1.1fr;
  gap: clamp(28px, 5vw, 64px);
  align-items: center;
}
.checksplit__img { margin: 0; align-self: stretch; display: flex; }
.checksplit__img img { width: 100%; height: 100%; min-height: 360px; object-fit: cover; border-radius: 4px; display: block; }
@media (max-width: 860px) {
  .checksplit { grid-template-columns: 1fr; }
  .checksplit__img img { min-height: 0; height: auto; }
}
.section-title--left { text-align: left; }
.checklist { list-style: none; margin: 0; padding: 0; }
.checklist li {
  display: grid;
  grid-template-columns: 30px 1fr;
  gap: 16px;
  padding: 16px 0;
  border-top: 1px solid var(--line);
}
.checklist li:first-child { border-top: none; padding-top: 0; }
.checklist .tile__num { margin-bottom: 0; }
.checklist h3 { font-size: 15px; font-weight: 700; font-family: var(--body); margin: 0 0 6px; }
.checklist p { font-size: 14px; line-height: 1.65; color: var(--muted); margin: 0; }

/* Two-column checklist (D5): self-identification statements scan better as
   a list than as a second row of four equal cards. */
.pairlist {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 clamp(28px, 5vw, 64px);
}
.pairlist > div { padding: 18px 0; border-top: 1px solid var(--line); }
.pairlist > div:nth-child(-n+2) { border-top: none; }
.pairlist h3 { font-size: 15px; font-weight: 700; font-family: var(--body); margin: 0 0 6px; }
.pairlist p { font-size: 14px; line-height: 1.65; color: var(--muted); margin: 0; }
@media (max-width: 700px) {
  .pairlist { grid-template-columns: 1fr; }
  .pairlist > div:nth-child(2) { border-top: 1px solid var(--line); }
}

/* The quote centred over the full-width columns (D6). */
.pullquote--centred { max-width: 640px; margin: 0 auto clamp(32px, 5vw, 56px); text-align: center; }

/* Numbered path with a connecting line behind the circles. */
/* The connecting line (B1): position:relative was already here with nothing
   using it — the line was intended and never drawn. Drawn per step as a
   segment bridging half the grid gap each side, so it is exact for any step
   count; the first and last rows stop at their own dot. The opaque dots sit
   on top. Below 900px the grid would wrap and a horizontal line across
   wrapped rows looks broken, so the steps stack and the line runs vertically
   through the dots instead. */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(0, 1fr));
  gap: 22px;
  position: relative;
}
.step { text-align: center; position: relative; }
.step::before {
  content: "";
  position: absolute;
  top: 22px;
  left: -11px;
  right: -11px;
  height: 1px;
  background: var(--line);
}
.step:first-child::before { left: 50%; }
.step:last-child::before { right: 50%; }

.step__dot {
  width: 44px; height: 44px;
  margin: 0 auto 16px;
  border-radius: 100px;
  background: #f0e7d8;
  color: #76633f; /* was #8a7248 - 3.74:1 on its own #f0e7d8 circle, a quiet fail the auditor misses; #76633f is the same family at 4.72:1 */
  display: flex; align-items: center; justify-content: center;
  font-family: var(--mono); font-size: 14px;
  position: relative;
}

@media (max-width: 900px) {
  .steps { display: block; }
  .step {
    display: grid;
    grid-template-columns: 44px 1fr;
    column-gap: 18px;
    text-align: left;
    padding-bottom: 26px;
  }
  .step::before {
    top: 48px;
    bottom: 4px;
    left: 22px;
    right: auto;
    width: 1px;
    height: auto;
  }
  .step:first-child::before { left: 22px; }
  .step:last-child::before { display: none; }
  .step__dot { margin: 0; grid-row: 1 / span 2; }
  .step h3 { align-self: center; }
  .step p { grid-column: 2; }
}
.step h3 { font-size: 14px; font-weight: 700; font-family: var(--body); margin: 0 0 8px; letter-spacing: 0; }
.step p { font-size: 13px; line-height: 1.6; color: var(--muted); margin: 0; }

/* The development-types band (C2): icon above, label below, no links.
   Everything inherits the palette — the icons are stroke: currentColor. */
.devtypes__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(22px, 3.5vw, 40px) clamp(16px, 2.5vw, 32px);
}
@media (max-width: 900px) { .devtypes__grid { grid-template-columns: repeat(2, 1fr); } }

.devtypes__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  text-align: center;
  color: var(--muted);
  padding: 18px 8px;
}
.devtypes__item svg { color: #76633f; /* was #8a7248 - 3.74:1 on its own #f0e7d8 circle, a quiet fail the auditor misses; #76633f is the same family at 4.72:1 */ }
.devtypes__item span { font-size: 13.5px; letter-spacing: .03em; line-height: 1.4; }

/* ---- The delivery path as three phases (C4) ----------------------------- */
.phases {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(24px, 3.5vw, 48px);
}
@media (max-width: 900px) { .phases { grid-template-columns: 1fr; } }

.phase__head {
  text-align: center;
  margin-bottom: 22px;
}
.phase__no {
  display: block;
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .14em;
  text-transform: uppercase;
  color: #76633f; /* was #8a7248 - 3.74:1 on its own #f0e7d8 circle, a quiet fail the auditor misses; #76633f is the same family at 4.72:1 */
  margin-bottom: 6px;
}
.phase__head h3 {
  font-family: var(--heading);
  font-size: 20px;
  font-weight: 500;
  margin: 0;
  color: var(--ink);
}

/* A pair of steps inside a phase keeps the B1 connector between its two
   dots; the line stops at each phase, which is what makes three read as
   three. On narrow screens the pair stacks vertically like the rest. */
.steps--pair { grid-template-columns: 1fr 1fr; }
@media (max-width: 900px) { .steps--pair { display: block; } }

/* Two panels side by side. */
.split { display: grid; grid-template-columns: 1fr 1fr; gap: 18px; align-items: start; }
@media (max-width: 860px) { .split { grid-template-columns: 1fr; } }

.panel {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: clamp(26px, 3.5vw, 40px);
}
.panel h2 {
  font-family: var(--heading);
  font-size: clamp(21px, 2.6vw, 27px);
  font-weight: 400;
  letter-spacing: -.02em;
  margin: 0 0 16px;
}
.panel p { font-size: 14px; line-height: 1.7; color: var(--muted); margin: 0 0 12px; }
.panel p:last-child { margin-bottom: 0; }

.panel--dark { background: var(--ink); border-color: var(--ink); color: var(--bg); text-align: center; }
.panel--dark h2 { color: var(--bg); font-size: clamp(26px, 3.4vw, 36px); }
.panel--dark p { color: rgba(250, 249, 247, .75); }
.panel--dark .btn-solid { background: var(--accent); border-color: var(--accent); color: var(--ink); }
.panel--dark .btn-solid:hover { background: #d8bd93; border-color: #d8bd93; }

/* The booking form sits on a dark panel, where the default field colours are
   the same near-black as the background — anything typed would be invisible.
   Everything the visitor reads or types is restated for that panel here. */
.panel--dark .form input,
.panel--dark .form select,
.panel--dark .form textarea {
  color: var(--bg);
  border-bottom-color: rgba(250, 249, 247, .35);
}
.panel--dark .form input:focus,
.panel--dark .form select:focus,
.panel--dark .form textarea:focus { border-bottom-color: var(--accent); }

.panel--dark .form label { color: rgba(250, 249, 247, .75); }
.panel--dark .form ::placeholder { color: rgba(250, 249, 247, .45); }

/* The unchosen placeholder option, greyed but still legible. */
.panel--dark .form select:invalid { color: rgba(250, 249, 247, .55); }

/* The dropdown chevron is drawn in ink, which disappears here too. */
.panel--dark .form select {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'><path d='M2 4l4 4 4-4' fill='none' stroke='%23FAF9F7' stroke-width='1.5'/></svg>");
}

/* Browsers paint autofilled fields with their own light background, which
   would undo all of the above. The inset shadow is the only way to override
   it in WebKit. */
.panel--dark .form input:-webkit-autofill,
.panel--dark .form input:-webkit-autofill:focus {
  -webkit-text-fill-color: var(--bg);
  -webkit-box-shadow: 0 0 0 1000px var(--ink) inset;
  caret-color: var(--bg);
}

/* Error text needs to lift off the dark panel too. */
.panel--dark .form .field__error,
.panel--dark .form .field--error label { color: #e88b80; }
.panel--dark .form .field--error input,
.panel--dark .form .field--error select,
.panel--dark .form .field--error textarea { border-bottom-color: #e88b80; }


/* Ticked list used for "What You Receive". */
.ticks { list-style: none; margin: 0; padding: 0; }
.ticks li {
  position: relative;
  padding-left: 30px;
  margin-bottom: 13px;
  font-size: 14.5px;
  line-height: 1.6;
}
.ticks li::before {
  content: "✓";
  position: absolute;
  left: 0; top: -1px;
  width: 20px; height: 20px;
  border-radius: 100px;
  background: #f0e7d8;
  color: #76633f; /* was #8a7248 - 3.74:1 on its own #f0e7d8 circle, a quiet fail the auditor misses; #76633f is the same family at 4.72:1 */
  font-size: 11px;
  display: flex; align-items: center; justify-content: center;
}

.pullquote {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: 4px;
  padding: clamp(26px, 3.5vw, 40px);
}
.pullquote blockquote {
  font-family: var(--heading);
  font-size: clamp(18px, 2.2vw, 23px);
  font-weight: 400;
  line-height: 1.5;
  letter-spacing: -.01em;
  margin: 0 0 20px;
}
.pullquote cite { font-style: normal; font-size: 12px; letter-spacing: .1em; text-transform: uppercase; }
.pullquote span { display: block; font-size: 13px; color: var(--muted); margin-top: 4px; }

/* FAQ built on <details> so it works without JavaScript. */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 16px;
  padding: 17px 0;
  cursor: pointer;
  font-size: 14.5px;
  list-style: none;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 18px; line-height: 1; }
.faq details[open] summary::after { content: "−"; }
.faq p { font-size: 14px; line-height: 1.7; color: var(--muted); margin: 0 0 18px; max-width: 70ch; }

/* Wide call-to-action band. */
.ctaband {
  background: #ece5da;
  border-radius: 4px;
  padding: clamp(28px, 4vw, 46px) clamp(24px, 4vw, 48px);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}
.ctaband h2 {
  font-family: var(--heading);
  font-size: clamp(24px, 3.2vw, 34px);
  font-weight: 400;
  letter-spacing: -.02em;
  line-height: 1.2;
  margin: 0 0 8px;
}
.ctaband p { font-size: 14px; color: var(--muted); margin: 0; }

.section--tight { padding-top: clamp(40px, 5vw, 64px); padding-bottom: clamp(40px, 5vw, 64px); }


/* ===== Hamburger menu ==================================================== */

.nav-toggle {
  width: 44px;
  height: 44px;
  padding: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 6px;
  background: transparent;
  border: none;
  cursor: pointer;
  z-index: 201;
}

.nav-toggle__bar {
  display: block;
  width: 28px;
  height: 2px;
  background: var(--ink);
  transition: transform .3s cubic-bezier(.4, 0, .2, 1), opacity .2s linear;
}

/* Over the hero (A3) the bars are off-white so they survive the night-skyline
   frames, and blend back to ink as the header background fades in. Browsers
   without color-mix keep ink bars — the old behaviour, not a new failure. */
@supports (color: color-mix(in srgb, red 50%, blue)) {
  .site-nav--overhero .nav-toggle__bar {
    background: color-mix(in srgb,
      #FAF9F7 calc(var(--nav-opacity, 1) * 100%), var(--ink));
  }
  .site-nav--overhero .site-nav__phone {
    color: color-mix(in srgb,
      #FAF9F7 calc(var(--nav-opacity, 1) * 100%), var(--ink));
  }
}

/* The phone number in the header (A7): the one action a visitor mid-task
   actually wants from a fixed header. */
.site-nav__phone {
  margin-left: auto;
  color: var(--ink);
  text-decoration: none;
  font-family: var(--mono, monospace);
  font-size: clamp(12px, 1.5vw, 14px);
  letter-spacing: .06em;
  white-space: nowrap;
}
.site-nav__phone:hover { color: var(--accent); }
.nav-toggle__bar:nth-child(2) { width: 20px; }

/* Bars morph into an X while the panel is open. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(1) { transform: translateY(8px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle__bar:nth-child(3) { width: 28px; transform: translateY(-8px) rotate(-45deg); }

.site-menu {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: var(--bg);
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: clamp(18px, 3vw, 28px);
  opacity: 0;
  visibility: hidden;
  transition: opacity .3s ease, visibility .3s;
}
.site-menu[data-open="true"] { opacity: 1; visibility: visible; }

.site-menu a {
  font-family: var(--heading);
  font-size: clamp(28px, 5vw, 44px);
  font-weight: 400;
  letter-spacing: -.02em;
  color: var(--ink);
  text-decoration: none;
  transition: color .2s;
}
.site-menu a:hover { color: var(--accent); }

/* Back arrow, top-left of the open panel. Closes the menu and returns you
   to the page you were on. */
.menu-back {
  position: absolute;
  top: clamp(16px, 3.5vw, 36px);
  left: clamp(18px, 4vw, 48px);
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  padding: 0;
  background: transparent;
  border: none;
  color: var(--ink);
  cursor: pointer;
  opacity: .8;
  transition: opacity .2s, transform .2s;
}
.menu-back:hover { opacity: 1; transform: translateX(-3px); }
.menu-back svg { display: block; }

/* Stops the page scrolling behind the open panel. */
body.menu-open { overflow: hidden; }


/* ===== Gallery: project grid ============================================= */

.project-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 24px;
}

.project-card {
  display: flex;
  flex-direction: column;
  background: var(--panel);
  border-radius: 4px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
  transition: box-shadow .4s ease, transform .4s ease;
}
.project-card:hover {
  transform: translateY(-4px);
  box-shadow: 0 12px 32px rgba(0, 0, 0, .08);
}

.project-card__img {
  width: 100%;
  height: clamp(200px, 24vw, 280px);
  background-size: cover;
  background-position: center;
  background-color: var(--line);
}

.project-card__body { padding: 32px 24px; }

.project-card h2, .project-card h3 {
  font-family: var(--heading);
  font-size: 22px;
  font-weight: 500;
  letter-spacing: -.01em;
  color: var(--ink);
  margin: 0 0 12px;
}

.project-card p { font-size: 15px; line-height: 1.6; color: var(--muted); margin: 0; }

.project-card__count {
  font-family: var(--mono);
  font-size: 11px;
  letter-spacing: .12em;
  color: var(--muted);
  text-transform: uppercase;
  margin-top: 16px;
}


/* ===== Gallery: single project =========================================== */

.project-back {
  display: inline-block;
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .1em;
  text-transform: uppercase;
  color: var(--muted);
  text-decoration: none;
  margin-bottom: 32px;
  transition: color .2s;
}
.project-back:hover { color: var(--ink); }

.project-meta {
  font-family: var(--mono);
  font-size: 12px;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 12px;
}

.project-photos {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
  gap: 16px;
  margin-top: 48px;
}

.project-photos figure { margin: 0; }

.project-photos img {
  width: 100%;
  height: 100%;
  max-height: 460px;
  object-fit: cover;
  border-radius: 4px;
  display: block;
  cursor: zoom-in;
  background: var(--line);
}

.project-photos figcaption {
  font-size: 13px;
  line-height: 1.5;
  color: var(--muted);
  margin-top: 8px;
}

/* Click a photo to view it full size. */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 300;
  background: rgba(26, 26, 26, .92);
  display: none;
  align-items: center;
  justify-content: center;
  padding: 4vh 4vw;
  cursor: zoom-out;
}
.lightbox[data-open="true"] { display: flex; }
.lightbox img { max-width: 100%; max-height: 92vh; object-fit: contain; border-radius: 4px; }

.gallery-empty {
  text-align: center;
  padding: 60px 24px;
  color: var(--muted);
  font-size: 15px;
  line-height: 1.7;
}


/* Shown when an enquiry could not be delivered. A failed send must be as
   visible as a successful one. */
.form__failed {
  background: #fdf3f2;
  border: 1px solid var(--error);
  border-radius: 4px;
  color: var(--error);
  font-size: 14px;
  line-height: 1.6;
  padding: 14px 16px;
  margin-bottom: 24px;
}
