/* Ashworth & Vale — shared stylesheet
   Linked from every page. Design tokens sourced from the Akari vault: Demo Site/Demo Brand.md
   No build step — plain CSS, custom properties for every token so a value only changes in one place. */

/* ---------- Design tokens ---------- */
:root {
  /* Colour — "what if Google/Apple did build and design": bright, cool, one confident accent */
  --color-bg: #FFFFFF;
  --color-bg-alt: #F4F6F9;
  --color-bg-warm: #F5F3EE;
  --color-ink: #14171F;
  --color-ink-muted: #5B6472;
  --color-accent: #2955A3;
  --color-accent-hover: #1F4380;
  --color-border: #E2E6EC;

  /* Verified/trust signal only — not a second brand accent, kept to this one use */
  --color-success: #1D8A5F;
  --color-success-bg: #E9F7F0;
  --color-success-border: #BFE6D3;

  /* Form validation only — same three-tier pattern as --color-success above,
     kept to that one use. Not in the original locked palette; added for the
     Contact page's inline field errors, logged in PROJECT-GUIDE.md. */
  --color-danger: #B3261E;
  --color-danger-bg: #FCEBEA;
  --color-danger-border: #F3C6C2;

  /* Type — single sans-serif throughout, no serif pairing */
  --font-heading: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, sans-serif;

  /* Spacing (8px base unit) */
  --space-1: 8px;
  --space-2: 16px;
  --space-3: 24px;
  --space-4: 32px;
  --space-6: 48px;
  --section-padding: 120px;
  --section-padding-mobile: 64px;

  /* Layout */
  --max-width: 1200px;

  /* Motion — consistent easing/duration everywhere so it reads as one system */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);
  --duration-fast: 0.15s;
  --duration-base: 0.25s;
  --duration-slow: 0.6s;
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

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

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

body, h1, h2, h3, h4, p, figure, blockquote {
  margin: 0;
}

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

a {
  color: inherit;
}

button {
  font: inherit;
  cursor: pointer;
}

/* ---------- Base ---------- */
body {
  background: var(--color-bg);
  color: var(--color-ink);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

/* ---------- Type scale ---------- */
h1, .h1 {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 34px;
  line-height: 1.1;
  letter-spacing: -0.02em;
}

h2, .h2 {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 24px;
  line-height: 1.2;
  letter-spacing: -0.01em;
}

h3, .h3 {
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 20px;
  line-height: 1.3;
}

@media (min-width: 768px) {
  h1, .h1 { font-size: 60px; letter-spacing: -0.025em; }
  h2, .h2 { font-size: 32px; }
  h3, .h3 { font-size: 22px; }
}

.caption, .label {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  letter-spacing: 0.02em;
}

/* ---------- Layout helpers ---------- */
.container {
  max-width: var(--max-width);
  margin-inline: auto;
  padding-inline: var(--space-3);
}

section {
  padding-block: var(--section-padding-mobile);
}

@media (min-width: 768px) {
  section {
    padding-block: var(--section-padding);
  }
}

.section-alt {
  background: var(--color-bg-alt);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-block;
  padding: var(--space-2) var(--space-4);
  border-radius: 4px;
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 16px;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}

.btn:active {
  transform: scale(0.97);
}

.btn-primary {
  background: var(--color-accent);
  color: #FFFFFF;
}

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

.btn-secondary {
  background: transparent;
  color: var(--color-ink);
  border-color: var(--color-border);
}

.btn-secondary:hover {
  border-color: var(--color-ink);
}

/* ---------- Site Header / Nav ---------- */
.site-header {
  border-bottom: 1px solid var(--color-border);
  background: var(--color-bg);
  position: sticky;
  top: 0;
  z-index: 30;
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding-block: var(--space-3);
  position: relative;
}

.site-logo {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 20px;
  letter-spacing: -0.01em;
  text-decoration: none;
  color: var(--color-ink);
}

.site-logo__amp {
  color: var(--color-accent);
}

.site-nav {
  display: none;
}

.site-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  list-style: none;
  margin: 0;
  padding: 0;
}

.site-nav__list a {
  text-decoration: none;
  font-weight: 500;
  font-size: 15px;
  color: var(--color-ink);
  transition: color var(--duration-fast) var(--ease-standard);
}

.site-nav__list a:hover {
  color: var(--color-accent);
}

.site-nav__list a[aria-current="page"] {
  color: var(--color-accent);
}

.site-nav__cta {
  margin-left: var(--space-4);
}

.menu-toggle {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px;
  height: 44px;
  background: transparent;
  border: none;
  padding: 0;
}

.menu-toggle span {
  display: block;
  width: 24px;
  height: 2px;
  background: var(--color-ink);
  margin-inline: auto;
  transition: transform var(--duration-base) var(--ease-standard), opacity var(--duration-base) var(--ease-standard);
}

.menu-toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.menu-toggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.menu-toggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

@media (max-width: 899.98px) {
  /* Nav sheet stays in the layout at all times on mobile — only opacity/transform/visibility
     toggle, so the open/close is an actual animation rather than an instant display swap. */
  .site-nav {
    display: flex;
    flex-direction: column;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    min-height: 100vh;
    background: var(--color-bg);
    padding: var(--space-4) var(--space-3);
    z-index: 20;
    box-shadow: 0 12px 24px -8px rgba(20, 23, 31, 0.15);
    opacity: 0;
    visibility: hidden;
    transform: translateY(-12px);
    pointer-events: none;
    transition: opacity var(--duration-base) var(--ease-standard),
                transform var(--duration-base) var(--ease-standard),
                visibility 0s linear var(--duration-base);
  }

  .site-nav.is-open {
    opacity: 1;
    visibility: visible;
    transform: translateY(0);
    pointer-events: auto;
    transition: opacity var(--duration-base) var(--ease-standard),
                transform var(--duration-base) var(--ease-standard),
                visibility 0s linear 0s;
  }

  .site-nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
  }

  .site-nav__list li {
    border-bottom: 1px solid var(--color-border);
  }

  .site-nav__list a {
    display: block;
    position: relative;
    padding-block: var(--space-3);
    font-family: var(--font-heading);
    font-weight: 600;
    font-size: 22px;
  }

  .site-nav__list a[aria-current="page"] {
    padding-left: var(--space-3);
  }

  .site-nav__list a[aria-current="page"]::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--color-accent);
    transform: translateY(-50%);
  }

  .site-nav__cta {
    margin-left: 0;
    margin-top: var(--space-4);
    display: block;
    width: 100%;
    text-align: center;
  }
}

@media (min-width: 900px) {
  .site-nav {
    display: flex;
    align-items: center;
  }

  .site-nav__list a {
    position: relative;
  }

  .site-nav__list a[aria-current="page"]::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -10px;
    height: 2px;
    border-radius: 2px;
    background: var(--color-accent);
  }

  .menu-toggle {
    display: none;
  }
}

/* ---------- Site Footer ---------- */
.site-footer {
  background: var(--color-bg-alt);
  border-top: 1px solid var(--color-border);
}

.site-footer__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  padding-block: var(--space-6);
}

@media (min-width: 768px) {
  .site-footer__inner {
    grid-template-columns: 1.5fr 1fr 1fr 1fr;
  }
}

.site-footer__tagline {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 15px;
  max-width: 32ch;
}

.site-footer__list {
  list-style: none;
  margin: var(--space-2) 0 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}

.site-footer__list a,
.site-footer__col a {
  text-decoration: none;
  color: var(--color-ink);
  font-size: 15px;
  transition: color var(--duration-fast) var(--ease-standard);
}

.site-footer__list a:hover,
.site-footer__col a:hover {
  color: var(--color-accent);
}

.site-footer__col p {
  margin-top: var(--space-1);
  font-size: 15px;
}

.site-footer__coverage {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 14px;
  line-height: 1.6;
}

.site-footer__bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-block: var(--space-3);
  border-top: 1px solid var(--color-border);
  color: var(--color-ink-muted);
}

/* ---------- CTA Band ---------- */
.cta-band {
  position: relative;
  overflow: hidden;
  background: var(--color-ink);
  color: #FFFFFF;
}

/* Very soft, slow-drifting glow — depth without the "shader gradient" flashiness.
   Purely decorative, so it's excluded from prefers-reduced-motion's global freeze
   only in the sense that a frozen glow still looks fine (it's just a static blur). */
.cta-band::before {
  content: "";
  position: absolute;
  top: -20%;
  right: -10%;
  width: 480px;
  height: 480px;
  background: radial-gradient(circle, rgba(90, 140, 220, 0.35) 0%, rgba(90, 140, 220, 0) 70%);
  filter: blur(40px);
  z-index: 0;
  animation: cta-glow-drift 14s ease-in-out infinite alternate;
  pointer-events: none;
}

@keyframes cta-glow-drift {
  from { transform: translate(0, 0) scale(1); }
  to { transform: translate(-60px, 40px) scale(1.2); }
}

.cta-band h2 {
  color: #FFFFFF;
}

.cta-band__inner {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
}

@media (min-width: 768px) {
  .cta-band__inner {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
  }
}

.cta-band__inner p {
  margin-top: var(--space-1);
  color: rgba(255, 255, 255, 0.75);
  max-width: 48ch;
}

.cta-band__actions {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex-wrap: wrap;
}

/* All buttons go full-width on small phones, not just the hero/CTA-band
   ones — side-by-side buttons get cramped/uneven below ~540px, and a
   button that's full-width in one place but auto-width in another reads
   as inconsistent. Applies to every .btn sitewide (nav's mobile CTA
   already sets its own width:100% and isn't affected by this). */
@media (max-width: 539.98px) {
  .hero__actions,
  .cta-band__actions,
  .section-heading-row {
    flex-direction: column;
    align-items: stretch;
  }

  .btn {
    width: 100%;
    text-align: center;
  }

  .cta-band__actions .cta-band__phone {
    text-align: center;
  }
}

.cta-band__phone {
  color: #FFFFFF;
  text-decoration: none;
  font-weight: 500;
}

.cta-band__phone:hover {
  text-decoration: underline;
}

.cta-band .btn-primary {
  background: #FFFFFF;
  color: var(--color-ink);
}

.cta-band .btn-primary:hover {
  background: var(--color-bg-alt);
}

/* ---------- Hero ----------
   Full-bleed image with overlaid text, edge-to-edge on mobile. A dark gradient
   scrim sits between the image and the text so copy stays readable against any
   photo. The image gets a subtle scroll parallax on desktop only (see main.js) —
   disabled on mobile (perf/iOS quirks) and for prefers-reduced-motion. */
.hero {
  position: relative;
  min-height: 60vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: #FFFFFF;
}

@media (min-width: 900px) {
  .hero {
    min-height: 85vh;
  }
}

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

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.08);
  /* Darkens the whole photo uniformly so text stays legible wherever it
     lands, on top of the gradient scrim below which does the extra work
     right behind the copy. */
  filter: brightness(0.7);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, rgba(8, 10, 15, 0.9) 0%, rgba(8, 10, 15, 0.6) 55%, rgba(8, 10, 15, 0.25) 100%);
}

.hero__content {
  position: relative;
  z-index: 2;
  padding-block: var(--space-6);
  max-width: 720px;
}

.hero h1 {
  color: #FFFFFF;
}

.hero__subhead {
  margin-top: var(--space-3);
  font-size: 18px;
  color: rgba(255, 255, 255, 0.85);
  max-width: 46ch;
}

.hero__actions {
  margin-top: var(--space-4);
  display: flex;
  gap: var(--space-3);
  flex-wrap: wrap;
}

.hero .btn-secondary {
  background: rgba(255, 255, 255, 0.08);
  color: #FFFFFF;
  border-color: rgba(255, 255, 255, 0.5);
  backdrop-filter: blur(4px);
}

.hero .btn-secondary:hover {
  background: rgba(255, 255, 255, 0.16);
  border-color: #FFFFFF;
}

/* ---------- Trust Bar ----------
   One consolidated trust/stats band, not two — a separate compact Trust Bar
   plus a bigger Big Stats section further down said the same things twice.
   Only numbers go in the stat grid — mixing in a text badge ("FMB ·
   Checkatrade") at the same giant scale as the numbers wrapped to two lines
   and threw off row heights on mobile, reading as messy. The accreditation
   now sits as its own smaller badge line below the three number cards,
   which also matches how real stat bands are usually built (numbers only). */
.trust-bar {
  padding-block: var(--space-6);
}

@media (min-width: 900px) {
  .trust-bar {
    padding-block: 80px;
  }
}

.trust-bar__inner {
  display: flex;
  flex-direction: column;
}

@media (min-width: 640px) {
  .trust-bar__inner {
    flex-direction: row;
  }
}

.trust-bar__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);
  text-align: center;
  flex: 1;
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.trust-bar__item:last-child {
  border-bottom: none;
}

@media (min-width: 640px) {
  .trust-bar__item {
    padding-block: 0;
    padding-inline: var(--space-3);
    border-bottom: none;
    border-left: 1px solid var(--color-border);
  }

  .trust-bar__item:first-child {
    border-left: none;
  }
}

.trust-bar__item .icon-circle {
  margin-bottom: var(--space-1);
}

.trust-bar__badge {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  margin: var(--space-4) auto 0;
  padding: var(--space-2) var(--space-4);
  width: fit-content;
  max-width: 100%;
  border: 1px solid var(--color-success-border);
  border-radius: 999px;
  background: var(--color-success-bg);
  color: var(--color-success);
  font-size: 14px;
  font-weight: 600;
  text-align: center;
}

.trust-bar__badge svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
  color: var(--color-success);
}

/* ---------- Icon Circle (shared — Trust Bar, Process, Services) ---------- */
.icon-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--color-accent);
  color: #FFFFFF;
}

.icon-circle svg {
  width: 20px;
  height: 20px;
}

.icon-circle--sm {
  width: 32px;
  height: 32px;
}

.icon-circle--sm svg {
  width: 16px;
  height: 16px;
}

/* ---------- Section heading row (heading + action on one line) ---------- */
.section-heading-row {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  align-items: flex-start;
  justify-content: space-between;
  margin-bottom: var(--space-4);
}

@media (min-width: 768px) {
  .section-heading-row {
    flex-direction: row;
    align-items: flex-end;
  }
}

.section-heading-row p {
  margin-top: var(--space-1);
  color: var(--color-ink-muted);
  max-width: 52ch;
}

/* ---------- Services Grid ---------- */
.services-grid h2 {
  margin-bottom: var(--space-4);
}

.services-grid__list {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 640px) {
  .services-grid__list {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1000px) {
  .services-grid__list {
    grid-template-columns: repeat(4, 1fr);
  }
}

.service-card {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  overflow: hidden;
  box-shadow: 0 1px 2px rgba(20, 23, 31, 0.04);
  transition: border-color var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard);
}

.service-card:hover {
  border-color: var(--color-accent);
  transform: translateY(-3px);
  box-shadow: 0 12px 20px -12px rgba(20, 23, 31, 0.18);
}

/* Photo header — the "What We Do" cards were plain text, flat next to the
   rest of the now photography-led page. A representative shot per service
   ties this section into the same visual language as the bento project
   grid, using images already sourced rather than needing anything new. */
.service-card__image {
  height: 140px;
  overflow: hidden;
}

.service-card__image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--duration-slow) var(--ease-standard);
}

.service-card:hover .service-card__image img {
  transform: scale(1.05);
}

.service-card__body {
  padding: var(--space-3);
}

.service-card__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.service-card__header h3 {
  margin: 0;
}

.service-card p {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 15px;
}

.service-card__link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--space-2);
  color: var(--color-accent);
  text-decoration: none;
  font-weight: 500;
  font-size: 15px;
}

.service-card__link .arrow {
  display: inline-block;
  transition: transform var(--duration-fast) var(--ease-standard);
}

.service-card__link:hover .arrow {
  transform: translateX(3px);
}

/* ---------- Project Grid / Project Card ---------- */
.project-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 640px) {
  .project-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (min-width: 1000px) {
  .project-grid {
    grid-template-columns: repeat(4, 1fr);
  }
}

.project-card {
  display: block;
  text-decoration: none;
  color: var(--color-ink);
  border-radius: 8px;
  overflow: hidden;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  box-shadow: 0 1px 2px rgba(20, 23, 31, 0.04);
  transition: box-shadow var(--duration-base) var(--ease-standard),
              transform var(--duration-base) var(--ease-standard);
}

/* The [hidden] attribute (used by the Projects page filter) would
   otherwise lose to the `display: block` above — an author rule always
   beats the browser's default [hidden] behaviour regardless of
   specificity, since UA styles sit below any author style in the
   cascade. This restores it. */
.project-card[hidden] {
  display: none;
}

.project-card:hover {
  box-shadow: 0 12px 20px -12px rgba(20, 23, 31, 0.18);
  transform: translateY(-3px);
}

.project-card img {
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  /* Only the top corners round — the card's own radius + overflow:hidden
     handles the outer shape, so the image should sit flush into the text
     block below rather than reading as a separate rounded tile inside it. */
  border-radius: 0;
  transition: transform var(--duration-slow) var(--ease-standard);
}

.project-card:hover img {
  transform: scale(1.04);
}

.project-card__body h3 {
  transition: color var(--duration-fast) var(--ease-standard);
}

.project-card:hover .project-card__body h3 {
  color: var(--color-accent);
}

.project-card__body {
  padding: var(--space-2) var(--space-2) var(--space-3);
}

.project-card__body .label {
  color: var(--color-accent);
}

.project-card__body h3 {
  margin-top: 4px;
  font-size: 18px;
}

.project-card__body .caption {
  color: var(--color-ink-muted);
  font-weight: 400;
}

/* Non-linked cards (Projects page listing) — only one demo project has a
   full detail page; the other 5 are proof-of-range cards with nowhere to
   go yet. Rendered as plain <div>s rather than <a>s, so this strips the
   hover lift/zoom/cursor that would otherwise (misleadingly) suggest
   they're clickable. */
.project-card--static {
  cursor: default;
}

.project-card--static:hover {
  box-shadow: 0 1px 2px rgba(20, 23, 31, 0.04);
  transform: none;
}

.project-card--static:hover img {
  transform: none;
}

.project-card--static:hover .project-card__body h3 {
  color: var(--color-ink);
}

/* ---------- Project Filters (Projects page) ----------
   Same pill language as the Services page's quick nav, for a consistent
   "this is how Ashworth & Vale does filter/nav chips" feel across pages —
   not sticky here though, this is a one-off filter row, not a scrollspy. */
.project-filters {
  padding-block: var(--space-6) var(--space-4);
}

.project-filters__header {
  display: grid;
  gap: var(--space-1);
  margin-bottom: var(--space-3);
}

.project-filters__header h2 {
  font-size: 24px;
}

.project-filters__status {
  color: var(--color-ink-muted);
  font-size: 14px;
}

.project-filters__list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
}

.project-filters__btn {
  padding: 8px 16px;
  border-radius: 999px;
  border: 1px solid var(--color-border);
  background: var(--color-bg);
  color: var(--color-ink-muted);
  font: inherit;
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard),
              border-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}

.project-filters__btn:hover {
  border-color: var(--color-ink);
  color: var(--color-ink);
}

.project-filters__btn.is-active {
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: #FFFFFF;
}

/* ---------- Project Listing (Projects page) ---------- */
.project-listing {
  padding-top: 0;
}

.project-listing__empty {
  padding-block: var(--space-4);
  color: var(--color-ink-muted);
  text-align: center;
}

.process-condensed__link {
  display: inline-flex;
  margin-top: var(--space-2);
}

/* ---------- Project Grid — Bento variant (Homepage Featured Projects) ----------
   Kept as a separate modifier rather than changing .project-grid/.project-card
   directly — the plain equal-column version above stays available for the
   Projects page listing (Stage 4), which doesn't need one hero tile. */
.project-grid--bento {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 900px) {
  .project-grid--bento {
    grid-template-columns: repeat(4, 1fr);
    /* Asymmetric rows, not a plain 50/50 split — row 1 (hero tile top +
       the two small tiles) taller so the small tiles feel substantial
       rather than squeezed; row 2 (hero tile bottom + the wide tile)
       shorter, so the wide tile reads as a lower-key supporting piece
       instead of visually competing with the hero tile above it. */
    grid-template-rows: 340px 220px;
    gap: var(--space-4);
  }

  .project-grid--bento .project-card--bento:nth-child(1) {
    grid-column: 1 / 3;
    grid-row: 1 / 3;
  }

  .project-grid--bento .project-card--bento:nth-child(2) {
    grid-column: 3 / 4;
    grid-row: 1 / 2;
  }

  .project-grid--bento .project-card--bento:nth-child(3) {
    grid-column: 4 / 5;
    grid-row: 1 / 2;
  }

  .project-grid--bento .project-card--bento:nth-child(4) {
    grid-column: 3 / 5;
    grid-row: 2 / 3;
  }
}

.project-card--bento {
  position: relative;
  display: block;
  min-height: 280px;
  border-radius: 12px;
  overflow: hidden;
  text-decoration: none;
  color: inherit;
}

.project-card--bento img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 0;
  transition: transform var(--duration-slow) var(--ease-standard);
}

.project-card--bento:hover img {
  transform: scale(1.05);
}

.project-card--bento::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(8, 10, 15, 0.85) 0%, rgba(8, 10, 15, 0.15) 55%, rgba(8, 10, 15, 0) 75%);
}

.project-card--bento__body {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 1;
  padding: var(--space-3);
  color: #FFFFFF;
}

.project-card--bento__body .label {
  color: rgba(255, 255, 255, 0.75);
}

.project-card--bento__body h3 {
  margin-top: 4px;
  font-size: 19px;
  color: #FFFFFF;
}

.project-card--bento__body .caption {
  color: rgba(255, 255, 255, 0.75);
}

/* The extra detail line is hidden until hover/focus — the "active grid" touch:
   tiles reveal a bit more on interaction instead of just zooming the photo. */
.project-card--bento__detail {
  display: block;
  margin-top: var(--space-1);
  font-size: 13px;
  font-weight: 500;
  color: #FFFFFF;
  max-height: 0;
  opacity: 0;
  overflow: hidden;
  transition: max-height var(--duration-base) var(--ease-standard),
              opacity var(--duration-base) var(--ease-standard);
}

.project-card--bento:hover .project-card--bento__detail,
.project-card--bento:focus-visible .project-card--bento__detail {
  max-height: 24px;
  opacity: 1;
}

/* ---------- Process Steps (condensed) ---------- */
.process-condensed p {
  margin-top: var(--space-1);
  color: var(--color-ink-muted);
  max-width: 52ch;
}

.process-steps {
  list-style: none;
  margin: var(--space-4) 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
}

@media (min-width: 768px) {
  .process-steps {
    grid-template-columns: repeat(4, 1fr);
  }
}

/* Card treatment + a large ghost numeral per step — the numeral does the
   "this is a sequence" job on its own, more distinctive than a thin
   connecting line, and gives each step some actual visual weight instead
   of an icon floating in whitespace. */
.process-steps li {
  position: relative;
  overflow: hidden;
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: var(--space-4) var(--space-3) var(--space-3);
  transition: transform var(--duration-base) var(--ease-standard),
              box-shadow var(--duration-base) var(--ease-standard),
              border-color var(--duration-base) var(--ease-standard);
}

.process-steps li:hover {
  transform: translateY(-3px);
  box-shadow: 0 12px 20px -12px rgba(20, 23, 31, 0.18);
  border-color: var(--color-accent);
}

.process-steps__number {
  position: absolute;
  top: -14px;
  right: 4px;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 72px;
  line-height: 1;
  color: var(--color-bg);
  -webkit-text-stroke: 1.5px var(--color-border);
  z-index: 0;
  user-select: none;
}

.process-steps .icon-circle,
.process-steps h3,
.process-steps p {
  position: relative;
  z-index: 1;
}

.process-steps .icon-circle {
  margin-bottom: var(--space-2);
}

.process-steps h3 {
  font-size: 17px;
}

.process-steps p {
  margin-top: 4px;
  font-size: 14px;
  color: var(--color-ink-muted);
}

/* ---------- Big Stat number/label ----------
   Reusable typographic treatment for a large stat, used inside the Trust
   Bar items above. Numbers count up the first time they scroll into view
   (see main.js), skipped for prefers-reduced-motion (final value shown
   immediately instead). Kept as its own block rather than folded into
   .trust-bar so it stays reusable anywhere else a big number is needed. */
.big-stat__number {
  display: block;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 44px;
  letter-spacing: -0.02em;
  color: var(--color-accent);
}

@media (min-width: 768px) {
  .big-stat__number {
    font-size: 56px;
  }
}

.big-stat__label {
  display: block;
  margin-top: var(--space-1);
  color: var(--color-ink-muted);
  font-size: 15px;
}

/* ---------- Testimonials ---------- */
.testimonials__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-3);
  margin-top: var(--space-4);
}

@media (min-width: 768px) {
  .testimonials__grid {
    grid-template-columns: 1fr 1fr;
  }
}

.testimonial-card {
  position: relative;
  overflow: hidden;
  margin: 0;
  padding: var(--space-4);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  background: var(--color-bg);
}

.testimonial-card__quote-mark {
  position: absolute;
  top: -28px;
  left: var(--space-2);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 120px;
  line-height: 1;
  color: var(--color-bg-alt);
  z-index: 0;
  user-select: none;
}

.testimonial-card__stars {
  position: relative;
  z-index: 1;
  display: flex;
  gap: 2px;
  color: var(--color-accent);
  margin-bottom: var(--space-2);
}

.testimonial-card__stars svg {
  width: 16px;
  height: 16px;
}

.testimonial-card p {
  position: relative;
  z-index: 1;
  font-size: 18px;
  line-height: 1.5;
}

.testimonial-card__author {
  position: relative;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: var(--space-2);
  margin-top: var(--space-3);
}

.avatar-circle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  flex-shrink: 0;
  border-radius: 50%;
  background: var(--color-accent);
  color: #FFFFFF;
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 14px;
}

.testimonial-card cite {
  display: block;
  font-style: normal;
  font-weight: 500;
  font-size: 14px;
}

.testimonial-card cite .caption {
  display: block;
  margin-top: 1px;
  font-weight: 400;
  color: var(--color-ink-muted);
}

/* ---------- Page Intro (Services page, and other inner pages) ----------
   Borrows the Homepage Hero's image + scrim + overlay-text language so
   inner pages read as part of the same site, but scaled down (32/40vh vs
   the Hero's 60/85vh) so it doesn't compete with the real Hero for drama.
   Kept shorter than the Hero specifically so the title has less vertical
   "runway" to get lost in — a tall band this size needs bigger text to
   still register, not a Hero-height crop. */
.page-intro {
  position: relative;
  min-height: 32vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: #FFFFFF;
}

@media (min-width: 900px) {
  .page-intro {
    min-height: 40vh;
  }
}

.page-intro__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.page-intro__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.7);
}

.page-intro__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, rgba(8, 10, 15, 0.85) 0%, rgba(8, 10, 15, 0.55) 55%, rgba(8, 10, 15, 0.2) 100%);
}

.page-intro__content {
  position: relative;
  z-index: 2;
  padding-block: var(--space-4);
}

@media (min-width: 768px) {
  .page-intro__content {
    padding-block: var(--space-6);
  }
}

.page-intro__title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 40px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #FFFFFF;
}

@media (min-width: 768px) {
  .page-intro__title {
    font-size: 56px;
  }
}

.page-intro__lead {
  margin-top: var(--space-2);
  color: rgba(255, 255, 255, 0.9);
  font-size: 19px;
  max-width: 56ch;
}

/* ---------- Service Quick Nav (Services page) ----------
   Sticks just below the site header once you scroll past the intro, and
   highlights whichever service block is currently in view (scrollspy via
   IntersectionObserver in main.js). Solves two things at once: the "jump
   straight to the service you care about" UX note, and gives the page a
   sense of progress as you scroll instead of feeling like one flat list. */
/* Frosted-glass treatment — translucent tint + blur rather than a flat
   opaque fill, so whatever's scrolling underneath (page content, service
   images) reads as soft blurred colour through the bar instead of a hard
   cut. rgba version of --color-bg-alt (#F4F6F9) since custom properties
   can't have alpha spliced in directly. */
.service-quicknav {
  position: sticky;
  top: 113px;
  z-index: 25;
  background: rgba(244, 246, 249, 0.72);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  border-bottom: 1px solid var(--color-border);
}

.service-quicknav__inner {
  display: flex;
  gap: var(--space-2);
  padding-block: var(--space-2);
  overflow-x: auto;
  scrollbar-width: none;
}

.service-quicknav__inner::-webkit-scrollbar {
  display: none;
}

.service-quicknav__link {
  flex-shrink: 0;
  padding: 8px 16px;
  border-radius: 999px;
  color: var(--color-ink-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}

.service-quicknav__link:hover {
  color: var(--color-ink);
}

.service-quicknav__link.is-active {
  background: var(--color-bg);
  color: var(--color-accent);
  font-weight: 600;
}

/* ---------- Service Detail blocks (Services page) ----------
   Richer than the Homepage's teaser service-card grid — one full block per
   service with image, description, typical scope, budget, and its own CTA.
   Alternates image side per block (.service-detail--reverse) for rhythm
   across 4 in a row. scroll-margin-top accounts for both sticky bars now
   stacked at the top (site header + quick nav) so neither covers the
   block when jumped to directly via an anchor link. */
.service-detail {
  padding-block: var(--space-6);
  scroll-margin-top: 188px;
}

@media (min-width: 768px) {
  .service-detail {
    padding-block: 64px;
  }
}

.service-detail__inner {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  align-items: center;
}

@media (min-width: 900px) {
  .service-detail__inner {
    flex-direction: row;
    gap: var(--space-6);
  }

  .service-detail--reverse .service-detail__inner {
    flex-direction: row-reverse;
  }

  /* flex-grow only applies once we're in a row: on mobile (column), giving
     both children flex:1 1 0 forces a circular height calculation — each
     tries to share the column's content-driven height before that height
     is known, and the image collapses to 0. Full-width block layout on
     mobile; a photography-led 56/44 split (image favoured) once there's
     a row to split, rather than an even 50/50. */
  .service-detail__media {
    flex: 0 0 56%;
  }

  .service-detail__body {
    flex: 1 1 0;
  }
}

.service-detail__media {
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
}

/* Edge-to-edge on mobile — breaks out of .container's side padding to run
   full viewport width, no rounded corners (touching the screen edge, a
   radius would look off). Only below the row-layout breakpoint; once the
   image sits alongside text in a two-column row it needs to stay contained
   like the rest of the block. */
@media (max-width: 899.98px) {
  .service-detail__media {
    width: 100vw;
    margin-inline: calc(50% - 50vw);
    border-radius: 0;
  }
}

.service-detail__media img {
  width: 100%;
  /* Taller than the Homepage's 4:3 project cards — this is the main visual
     moment per service block, not a supporting thumbnail, so it earns more
     presence. */
  aspect-ratio: 5 / 4;
  object-fit: cover;
  display: block;
}

/* Scoped to [data-reveal] blocks only (Renovations, Kitchen & Bathroom, Loft
   — never the first/Extensions block, which is above the fold and stays at
   rest per the sitewide no-animate-on-load rule). Image starts slightly
   zoomed and settles to 1 as the block scrolls into view (.is-visible added
   by the shared reveal observer) — a restrained Ken-Burns-style "arrival"
   rather than a static image just appearing. */
.service-detail__media[data-reveal] img {
  transform: scale(1.08);
  transition: transform var(--duration-slow) var(--ease-standard);
}

.service-detail__media[data-reveal].is-visible img {
  transform: scale(1);
}

.service-detail__body {
  width: 100%;
}

.service-detail__header {
  display: flex;
  align-items: center;
  gap: var(--space-2);
}

.service-detail__header h2 {
  margin: 0;
}

.service-detail__body > p {
  margin-top: var(--space-3);
  color: var(--color-ink-muted);
}

.service-detail__meta {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-top: var(--space-3);
  padding-top: var(--space-3);
  border-top: 1px solid var(--color-border);
}

.service-detail__meta-item .label {
  display: block;
  margin-bottom: 2px;
}

.service-detail__meta-item p {
  margin-top: 0;
  color: var(--color-ink);
}

.service-detail__budget-value {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 20px;
  color: var(--color-accent);
}

.service-detail__link {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-top: var(--space-4);
  color: var(--color-accent);
  text-decoration: none;
  font-weight: 500;
}

.service-detail__link .arrow {
  display: inline-block;
  transition: transform var(--duration-fast) var(--ease-standard);
}

.service-detail__link:hover .arrow {
  transform: translateX(3px);
}

/* ---------- FAQ (condensed — Services page) ----------
   A lightweight accordion — collapsed by default, one open at a time
   (toggle logic in main.js). Same interaction pattern the dedicated
   Stage 7 FAQ page will use at full scale, built here first for these two
   cost/timeline questions. Divider between items rather than boxed cards,
   consistent with the Trust Bar's divider treatment. Collapse itself uses
   the grid-template-rows: 0fr → 1fr trick rather than JS height
   measurement or max-height guessing — animates smoothly to exactly the
   content's real height with pure CSS. */
.faq-condensed__list {
  margin-top: var(--space-4);
  max-width: 72ch;
}

.faq-condensed__item {
  border-bottom: 1px solid var(--color-border);
}

.faq-condensed__item:last-child {
  border-bottom: none;
}

.faq-condensed__item h3 {
  font-size: 18px;
  margin: 0;
}

.faq-condensed__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding-block: var(--space-3);
  background: none;
  border: none;
  font: inherit;
  font-weight: 600;
  color: var(--color-ink);
  text-align: left;
  cursor: pointer;
}

.faq-condensed__icon {
  position: relative;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
}

.faq-condensed__icon::before,
.faq-condensed__icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--color-accent);
  transform: translate(-50%, -50%);
  transition: transform var(--duration-base) var(--ease-standard);
}

.faq-condensed__icon::before {
  width: 100%;
  height: 2px;
}

.faq-condensed__icon::after {
  width: 2px;
  height: 100%;
}

/* Plus becomes minus on open — vertical bar rotates flat onto the
   horizontal one, rather than disappearing, so the icon still reads as a
   clear "collapse" affordance rather than just vanishing. */
.faq-condensed__question[aria-expanded="true"] .faq-condensed__icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.faq-condensed__answer-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-standard);
}

.faq-condensed__item.is-open .faq-condensed__answer-wrap {
  grid-template-rows: 1fr;
}

.faq-condensed__answer {
  overflow: hidden;
}

.faq-condensed__answer p {
  padding-bottom: var(--space-3);
  color: var(--color-ink-muted);
}

/* ---------- Project Header (Project Detail page) ----------
   Same image + scrim + overlay-text language as the Services page's
   Page Intro, shorter still (35/42vh) since this header only needs to
   carry a breadcrumb, type, title and location — no lead paragraph. */
.project-header {
  position: relative;
  min-height: 35vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: #FFFFFF;
}

@media (min-width: 900px) {
  .project-header {
    min-height: 42vh;
  }
}

.project-header__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}

.project-header__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  filter: brightness(0.7);
}

.project-header__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(0deg, rgba(8, 10, 15, 0.85) 0%, rgba(8, 10, 15, 0.55) 55%, rgba(8, 10, 15, 0.2) 100%);
}

.project-header__content {
  position: relative;
  z-index: 2;
  padding-block: var(--space-4);
}

@media (min-width: 768px) {
  .project-header__content {
    padding-block: var(--space-6);
  }
}

.project-header__breadcrumb {
  margin-bottom: var(--space-3);
}

/* A frosted pill rather than plain text — the same visual language as the
   Before/After labels — so it reads as a clear, tappable control against
   the photo instead of blending into the scrim. */
.project-header__breadcrumb-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 8px 16px 8px 12px;
  border-radius: 999px;
  background: rgba(8, 10, 15, 0.45);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #FFFFFF;
  text-decoration: none;
  font-size: 15px;
  font-weight: 600;
  transition: background-color var(--duration-fast) var(--ease-standard);
}

.project-header__breadcrumb-link svg {
  width: 16px;
  height: 16px;
  flex-shrink: 0;
}

.project-header__breadcrumb-link:hover {
  background: rgba(8, 10, 15, 0.65);
}

.project-header__type {
  color: rgba(255, 255, 255, 0.75);
}

/* Same banner-title scale as .page-intro__title (Services/Projects intro)
   — kept in sync deliberately, not the Homepage Hero's larger H1 scale,
   which tested as too big for a shorter, non-hero band. */
.project-header__title {
  margin-top: var(--space-1);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 40px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: #FFFFFF;
}

@media (min-width: 768px) {
  .project-header__title {
    font-size: 56px;
  }
}

.project-header__location {
  margin-top: var(--space-1);
  color: rgba(255, 255, 255, 0.85);
}

/* ---------- Project Stats (Project Detail page) ----------
   Same divider-over-box treatment as the Trust Bar and Service Detail
   meta rows — small repeated label+value pairs, not boxed cards. */
.project-stats {
  padding-block: var(--space-4);
  border-bottom: 1px solid var(--color-border);
}

.project-stats__list {
  display: flex;
  flex-direction: column;
}

@media (min-width: 640px) {
  .project-stats__list {
    flex-direction: row;
  }
}

.project-stats__item {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 1;
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-border);
}

.project-stats__item:last-child {
  border-bottom: none;
}

@media (min-width: 640px) {
  .project-stats__item {
    padding-block: 0;
    padding-inline: var(--space-3);
    border-bottom: none;
    border-left: 1px solid var(--color-border);
  }

  .project-stats__item:first-child {
    border-left: none;
    padding-left: 0;
  }
}

.project-stats__item .label {
  display: block;
  margin-bottom: 2px;
}

.project-stats__item p {
  margin: 0;
  font-weight: 600;
}

/* ---------- Project Gallery Carousel (Project Detail page) ----------
   Horizontal scroll-snap track — native swipe/drag on touch and trackpad
   for free, no JS needed for the actual sliding. Prev/next buttons and
   dots are a progressive-enhancement layer on top (main.js), and hide
   themselves entirely when there's only one photo, since there's nothing
   to navigate to. One slide = 100% of the track width, so it works
   whether there's 1 photo or 10 without layout changes either way. */
.project-gallery h2 {
  margin-bottom: var(--space-3);
}

.gallery-carousel {
  position: relative;
}

.gallery-carousel__track {
  display: flex;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: none;
  border-radius: 12px;
}

.gallery-carousel__track::-webkit-scrollbar {
  display: none;
}

.gallery-carousel__slide {
  flex: 0 0 100%;
  scroll-snap-align: center;
  margin: 0;
}

.gallery-carousel__slide img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
  border-radius: 12px;
}

.gallery-carousel__slide figcaption {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 14px;
  text-align: center;
}

.gallery-carousel__nav {
  position: absolute;
  top: calc(50% - 20px - 14px);
  z-index: 2;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: #FFFFFF;
  color: var(--color-accent);
  box-shadow: 0 4px 12px rgba(8, 10, 15, 0.2);
  cursor: pointer;
  transition: transform var(--duration-fast) var(--ease-standard),
              opacity var(--duration-fast) var(--ease-standard);
}

.gallery-carousel__nav:hover {
  transform: scale(1.06);
}

.gallery-carousel__nav:disabled,
.gallery-carousel__nav[hidden] {
  display: none;
}

.gallery-carousel__nav svg {
  width: 20px;
  height: 20px;
}

.gallery-carousel__nav--prev {
  left: var(--space-2);
}

.gallery-carousel__nav--next {
  right: var(--space-2);
}

.gallery-carousel__dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  margin-top: var(--space-3);
}

.gallery-carousel__dots[hidden] {
  display: none;
}

.gallery-carousel__dot {
  width: 8px;
  height: 8px;
  padding: 0;
  border-radius: 50%;
  border: none;
  background: var(--color-border);
  cursor: pointer;
  transition: background-color var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}

.gallery-carousel__dot.is-active {
  background: var(--color-accent);
  transform: scale(1.2);
}

/* ---------- Before / After Slider (Project Detail page) ----------
   "One of the strongest conversion tools for this niche" per the
   Component Library — drag to reveal, works with mouse, touch, and
   keyboard. Both images sit stacked at full frame size; the "before"
   image is clipped with clip-path rather than resizing a wrapper, which
   keeps both images the same scale as the handle moves (see main.js).
   No transition on the clip/handle position during an active drag — it
   needs to track the pointer 1:1, a lag would feel unresponsive — but a
   brief transition is added for the keyboard-nudge and intro-hint cases,
   where a bit of ease reads as polish rather than latency. */
.before-after {
  margin-top: var(--space-4);
}

.before-after__frame {
  position: relative;
  overflow: hidden;
  border-radius: 12px;
  aspect-ratio: 4 / 3;
  cursor: ew-resize;
  touch-action: none;
}

@media (min-width: 768px) {
  .before-after__frame {
    aspect-ratio: 16 / 9;
  }
}

.before-after__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  user-select: none;
  -webkit-user-drag: none;
}

.before-after__img--before {
  clip-path: inset(0 50% 0 0);
}

.before-after__label {
  position: absolute;
  top: var(--space-2);
  z-index: 2;
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(8, 10, 15, 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: #FFFFFF;
  font-size: 13px;
  font-weight: 500;
}

.before-after__label--before {
  left: var(--space-2);
}

.before-after__label--after {
  right: var(--space-2);
}

.before-after__handle {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  z-index: 3;
  width: 44px;
  margin-left: -22px;
  display: flex;
  align-items: center;
  justify-content: center;
  touch-action: none;
}

.before-after__handle::before {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 2px;
  margin-left: -1px;
  background: #FFFFFF;
  box-shadow: 0 0 0 1px rgba(8, 10, 15, 0.15);
}

.before-after__grip {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #FFFFFF;
  color: var(--color-accent);
  box-shadow: 0 4px 12px rgba(8, 10, 15, 0.25);
}

.before-after__grip svg {
  width: 18px;
  height: 18px;
}

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

/* Only added while the intro hint or a keyboard nudge is animating —
   see main.js. Not present during an active pointer drag. */
.before-after--animating .before-after__handle,
.before-after--animating .before-after__img--before {
  transition: left var(--duration-slow) var(--ease-standard),
              clip-path var(--duration-slow) var(--ease-standard);
}

.before-after-section__lead {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  max-width: 56ch;
}

.before-after-section__caption {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 14px;
  text-align: center;
}

/* ---------- Project Narrative (Project Detail page) ---------- */
.project-narrative__inner {
  max-width: 72ch;
}

.project-narrative__inner p {
  color: var(--color-ink-muted);
}

.project-narrative__inner p + p {
  margin-top: var(--space-3);
}

/* ---------- Project Testimonial (Project Detail page) ----------
   Reuses the Homepage's .testimonial-card component as-is rather than a
   one-off pattern — a single instance, centred, rather than a grid item. */
.project-testimonial__card {
  max-width: 640px;
  margin-inline: auto;
}

/* ---------- Scroll Reveal ----------
   Apply data-reveal to below-the-fold elements only (never the hero/first
   viewport — content already visible on load shouldn't fade in). main.js
   adds .is-visible via IntersectionObserver the first time each element
   scrolls into view. Falls back to visible immediately if JS/IO unavailable,
   and prefers-reduced-motion disables the animation globally (see tokens). */
[data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity var(--duration-slow) var(--ease-standard),
              transform var(--duration-slow) var(--ease-standard);
}

[data-reveal].is-visible {
  opacity: 1;
  transform: translateY(0);
}

.reveal-delay-1 { transition-delay: 0.08s; }
.reveal-delay-2 { transition-delay: 0.16s; }
.reveal-delay-3 { transition-delay: 0.24s; }
.reveal-delay-4 { transition-delay: 0.32s; }

/* ---------- Simple page intro (no photography) ----------
   Same 40px/56px banner-title scale as .page-intro (Services/Projects),
   for pages the Image Plan deliberately leaves without dedicated
   photography — visual interest here comes from the content itself. */
.simple-intro {
  padding-bottom: var(--space-4);
}

.process-intro {
  position: relative;
  overflow: hidden;
  padding-block: 72px 88px;
  background: var(--color-bg-warm);
}

.process-intro::after {
  content: "";
  position: absolute;
  width: 420px;
  height: 420px;
  right: -210px;
  top: -250px;
  border: 1px solid rgba(41, 85, 163, 0.1);
  border-radius: 50%;
  box-shadow: 0 0 0 64px rgba(41, 85, 163, 0.025),
              0 0 0 128px rgba(41, 85, 163, 0.018);
  pointer-events: none;
}

.process-intro::before {
  content: "";
  position: absolute;
  z-index: 1;
  left: max(45px, calc((100vw - var(--max-width)) / 2 + 45px));
  bottom: 0;
  width: min(42vw, 460px);
  height: 2px;
  background: linear-gradient(90deg, var(--color-accent) 0 44px, rgba(41, 85, 163, 0.2) 44px 100%);
}

.process-intro__grid {
  position: relative;
  z-index: 1;
  display: grid;
  gap: var(--space-6);
  align-items: center;
}

.process-intro__eyebrow {
  margin-bottom: var(--space-2);
  color: var(--color-accent);
}

.simple-intro__title {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 40px;
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--color-ink);
}

@media (min-width: 768px) {
  .simple-intro__title {
    font-size: 56px;
  }
}

.simple-intro__lead {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 19px;
  max-width: 56ch;
}

.process-promises {
  margin: 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--color-border);
}

.process-promises li {
  display: grid;
  grid-template-columns: 36px 1fr;
  gap: var(--space-2);
  align-items: center;
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-weight: 500;
}

.process-promises__mark {
  color: var(--color-accent);
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

@media (min-width: 900px) {
  .process-intro {
    padding-block: 104px 128px;
  }

  .process-intro__grid {
    grid-template-columns: minmax(0, 1.25fr) minmax(320px, 0.75fr);
    gap: 96px;
  }
}

/* ---------- Process Journey ----------
   The dedicated page uses a connected editorial journey rather than the
   Homepage card grid. A sticky architectural drawing develops as the user
   moves through the five stages; the linear timeline remains the complete
   mobile experience when the drawing is hidden. */
.process-full {
  position: relative;
  overflow: visible;
  background: var(--color-bg);
}

/* Carries the hero rule down to the first timeline node, turning the
   section boundary into the beginning of the customer journey. */
.process-full::before {
  content: "";
  position: absolute;
  left: max(45px, calc((100vw - var(--max-width)) / 2 + 45px));
  top: 0;
  width: 2px;
  height: calc(var(--section-padding-mobile) + 22px);
  background: linear-gradient(180deg, var(--color-accent), var(--color-border));
  pointer-events: none;
}

@media (min-width: 768px) {
  .process-full::before {
    height: calc(var(--section-padding) + 22px);
  }
}

.process-journey {
  display: grid;
  gap: var(--space-6);
  align-items: start;
}

.process-steps--full {
  display: block;
  max-width: 680px;
  margin: 0;
  position: relative;
  padding-left: 68px;
  --progress: 0;
  --line-top: 22px;
  --line-span: calc(100% - 44px);
}

.process-steps--full::before,
.process-steps--full::after {
  content: '';
  position: absolute;
  left: 21px;
  top: var(--line-top);
  width: 2px;
}

.process-steps--full::before {
  height: var(--line-span);
  background: var(--color-border);
}

.process-steps--full::after {
  height: calc(var(--line-span) * var(--progress));
  background: var(--color-accent);
  transition: height 80ms linear;
}

.process-steps--full li {
  background: none;
  border: none;
  box-shadow: none;
  border-radius: 0;
  padding: 0 0 72px;
  overflow: visible;
  transition: transform var(--duration-base) var(--ease-standard);
}

.process-steps--full li:last-child {
  padding-bottom: 0;
}

.process-steps--full li:hover {
  transform: none;
  box-shadow: none;
  border-color: transparent;
}

.process-steps--full .icon-circle {
  position: absolute;
  left: -68px;
  top: 0;
  margin: 0;
  box-shadow: 0 0 0 6px var(--color-bg);
  background: var(--color-bg);
  color: var(--color-accent);
  border: 2px solid var(--color-accent);
  transition: background-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard),
              transform var(--duration-fast) var(--ease-standard);
}

.process-steps--full li.is-active {
  transform: translateX(6px);
}

.process-steps--full li.is-complete .icon-circle,
.process-steps--full li.is-active .icon-circle {
  background: var(--color-accent);
  color: #FFFFFF;
}

.process-steps--full li.is-active .icon-circle {
  box-shadow: 0 0 0 6px var(--color-bg),
              0 0 0 9px rgba(41, 85, 163, 0.14);
  transform: scale(1.06);
}

.process-steps--full .process-steps__number {
  position: static;
  display: block;
  font-size: 56px;
  line-height: 0.8;
  color: rgba(41, 85, 163, 0.1);
  -webkit-text-stroke: 0;
  margin: 0 0 4px;
}

.process-step__content {
  max-width: 54ch;
}

@media (min-width: 768px) {
  .process-steps--full .process-steps__number {
    font-size: 72px;
  }
}

.process-steps__time {
  margin-top: 4px !important;
  font-size: 13px !important;
  font-weight: 500;
  color: var(--color-accent) !important;
}

.process-steps__time + p {
  margin-top: 4px;
}

.process-step__outcome {
  margin-top: var(--space-2) !important;
  padding-top: var(--space-2);
  border-top: 1px solid var(--color-border);
  color: var(--color-ink) !important;
  font-size: 14px !important;
}

.process-step__outcome span {
  display: block;
  margin-bottom: 2px;
  color: var(--color-ink-muted);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.process-step__focus {
  margin-bottom: var(--space-1);
  color: rgba(255, 255, 255, 0.62);
}

.process-step--build .process-step__content {
  margin-left: -12px;
  padding: var(--space-4);
  border-radius: 12px;
  background: var(--color-ink);
  color: #FFFFFF;
  box-shadow: 0 20px 44px -26px rgba(20, 23, 31, 0.45);
}

.process-step--build .process-steps__number {
  /* The numeral sits outside the dark content panel, so it must retain the
     same pale-navy treatment as the other four stages for continuity. */
  color: rgba(41, 85, 163, 0.1);
}

.process-step--build .process-steps__time {
  color: rgba(255, 255, 255, 0.72) !important;
}

.process-step--build .process-step__content > p:not(.process-step__focus):not(.process-steps__time):not(.process-step__outcome) {
  color: rgba(255, 255, 255, 0.78);
}

.process-step--build .process-step__outcome {
  border-color: rgba(255, 255, 255, 0.14);
  color: #FFFFFF !important;
}

.process-step--build .process-step__outcome span {
  color: rgba(255, 255, 255, 0.55);
}

.process-step--handover .process-step__content {
  padding-bottom: var(--space-3);
  border-bottom: 3px solid var(--color-accent);
}

/* Sticky architectural drawing — desktop only. */
.process-blueprint {
  display: none;
}

@media (min-width: 900px) {
  .process-journey {
    grid-template-columns: minmax(0, 1.05fr) minmax(380px, 0.95fr);
    gap: 88px;
  }

  .process-blueprint {
    display: block;
    position: sticky;
    top: 148px;
  }

  .process-blueprint__panel {
    position: relative;
    overflow: hidden;
    min-height: 570px;
    padding: var(--space-4);
    border: 1px solid rgba(41, 85, 163, 0.16);
    border-radius: 16px;
    background: linear-gradient(145deg, #F8FAFD 0%, #EEF3FA 100%);
    box-shadow: 0 24px 70px -48px rgba(20, 23, 31, 0.45);
  }

  .process-blueprint__header {
    position: relative;
    z-index: 2;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: var(--space-3);
  }

  .process-blueprint__header .label {
    color: var(--color-accent);
  }

  .process-blueprint__stage-name {
    margin-top: 4px;
    color: var(--color-ink);
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.02em;
  }

  .process-blueprint__stage-note {
    margin-top: 3px;
    max-width: 32ch;
    color: var(--color-ink-muted);
    font-size: 13px;
    line-height: 1.45;
  }

  .process-blueprint__counter {
    display: flex;
    align-items: baseline;
    gap: 5px;
    color: var(--color-ink-muted);
    font-size: 14px;
    font-weight: 600;
  }

  .process-blueprint__counter [data-process-current] {
    color: var(--color-ink);
    font-size: 28px;
    line-height: 1;
  }

  .process-blueprint__drawing {
    display: block;
    width: 100%;
    height: auto;
    margin-top: var(--space-2);
    color: rgba(41, 85, 163, 0.15);
  }

  .process-blueprint__grid {
    opacity: 0.65;
  }

  .blueprint-stage {
    fill: none;
    stroke: var(--color-accent);
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
    opacity: 0;
    transition: opacity var(--duration-base) var(--ease-standard),
                stroke-width var(--duration-base) var(--ease-standard);
  }

  .blueprint-stage path,
  .blueprint-stage circle {
    stroke-dasharray: 900;
    stroke-dashoffset: 900;
    transition: stroke-dashoffset 0.8s var(--ease-standard);
  }

  .blueprint-stage text {
    fill: var(--color-accent);
    stroke: none;
    font-family: var(--font-body);
    font-size: 14px;
    font-weight: 600;
  }

  .blueprint-stage.is-drawn {
    opacity: 0.28;
  }

  .blueprint-stage.is-current {
    opacity: 1;
    stroke-width: 2.6;
  }

  .blueprint-stage.is-drawn path,
  .blueprint-stage.is-drawn circle {
    stroke-dashoffset: 0;
  }

  .process-blueprint__legend {
    display: grid;
    grid-template-columns: repeat(5, auto);
    justify-content: space-between;
    gap: var(--space-1);
    padding-top: var(--space-2);
    border-top: 1px solid rgba(41, 85, 163, 0.12);
    color: var(--color-ink-muted);
    font-size: 11px;
  }

  .process-blueprint__legend span {
    display: flex;
    align-items: center;
    gap: 5px;
  }

  .process-blueprint__legend i {
    width: 5px;
    height: 5px;
    border-radius: 50%;
    background: var(--color-border);
    transition: background-color var(--duration-fast) var(--ease-standard);
  }

  .process-blueprint[data-stage="1"] .process-blueprint__legend span:nth-child(-n+1) i,
  .process-blueprint[data-stage="2"] .process-blueprint__legend span:nth-child(-n+2) i,
  .process-blueprint[data-stage="3"] .process-blueprint__legend span:nth-child(-n+3) i,
  .process-blueprint[data-stage="4"] .process-blueprint__legend span:nth-child(-n+4) i,
  .process-blueprint[data-stage="5"] .process-blueprint__legend span:nth-child(-n+5) i {
    background: var(--color-accent);
  }
}

/* ---------- Simple FAQ (condensed, non-interactive) ---------- */
.process-faq {
  padding-block: 80px;
}

.process-faq__layout {
  display: grid;
  gap: var(--space-4);
}

.process-faq__intro > p:not(.label):not(.process-faq__more) {
  margin-top: var(--space-2);
  max-width: 38ch;
  color: var(--color-ink-muted);
}

.process-faq__intro .label {
  margin-bottom: var(--space-1);
  color: var(--color-accent);
}

.simple-faq {
  margin: 0;
  max-width: none;
}

.simple-faq__item {
  padding-block: var(--space-3);
  border-bottom: 1px solid var(--color-border);
}

.simple-faq__item:first-child {
  border-top: 1px solid var(--color-border);
}

.simple-faq__item dt {
  font-weight: 600;
  font-size: 17px;
}

.simple-faq__item dd {
  margin: var(--space-1) 0 0;
  color: var(--color-ink-muted);
  max-width: 60ch;
}

.process-faq__more {
  margin-top: var(--space-3);
}

@media (min-width: 768px) {
  .process-faq {
    padding-block: 96px;
  }

  .process-faq__layout {
    grid-template-columns: minmax(260px, 0.75fr) minmax(0, 1.25fr);
    gap: 96px;
    align-items: start;
  }
}

/* ---------- FAQ Topic Nav (FAQ page) ----------
   Same sticky, horizontally-scrolling pill-bar recipe as the Services
   page's .service-quicknav (rgba(244,246,249,0.72) is that same
   --color-bg-alt tint, blurred). Kept as its own named component rather
   than sharing the class, so a change to one page's sticky bar can never
   bleed into the other's already-approved page. top:113px and the
   .faq-topic scroll-margin-top below both reuse the exact header-height
   figure .service-quicknav already established. Scrollspy + active-pill
   logic lives in main.js. */
.faq-topicnav {
  position: sticky;
  top: 113px;
  z-index: 25;
  background: rgba(244, 246, 249, 0.72);
  backdrop-filter: blur(12px) saturate(160%);
  -webkit-backdrop-filter: blur(12px) saturate(160%);
  border-bottom: 1px solid var(--color-border);
}

.faq-topicnav__inner {
  display: flex;
  gap: var(--space-2);
  padding-block: var(--space-2);
  overflow-x: auto;
  scrollbar-width: none;
}

.faq-topicnav__inner::-webkit-scrollbar {
  display: none;
}

.faq-topicnav__link {
  flex-shrink: 0;
  padding: 8px 16px;
  border-radius: 999px;
  color: var(--color-ink-muted);
  text-decoration: none;
  font-size: 14px;
  font-weight: 500;
  white-space: nowrap;
  transition: background-color var(--duration-fast) var(--ease-standard),
              color var(--duration-fast) var(--ease-standard);
}

.faq-topicnav__link:hover {
  color: var(--color-ink);
}

.faq-topicnav__link.is-active {
  background: var(--color-bg);
  color: var(--color-accent);
  font-weight: 600;
}

/* ---------- FAQ Topic Sections (FAQ page) ----------
   One section per topic, alternating background — a felt beat change to
   go with the scrollspy, not just a technically-updated nav state.
   scroll-margin-top matches .service-detail: same sticky site-header plus
   a same-height sticky bar stacked above it. */
.faq-topic {
  scroll-margin-top: 188px;
}

.faq-topic__inner {
  max-width: 72ch;
}

.faq-topic__related {
  margin-top: var(--space-4);
}

/* ---------- FAQ Accordion (FAQ page) ----------
   Same interaction recipe as the Services page's .faq-condensed
   (grid-rows 0fr/1fr collapse, plus/minus icon rotate, single-open — here
   scoped per topic list rather than page-wide, so opening a question in
   one topic doesn't collapse one left open in another). Kept as its own
   named component rather than sharing the class, so this page's one
   addition — the open question's text also changes colour, not just its
   icon, so "the expanded state is obvious" per the FAQ brief — can never
   cascade onto the already-approved Services page's mini-FAQ. Falls back
   to fully expanded, unstyled-icon via a <noscript> stylesheet in
   faq.html when JS is unavailable. */
.faq-accordion__list {
  margin-top: var(--space-4);
}

.faq-accordion__item {
  border-bottom: 1px solid var(--color-border);
}

.faq-accordion__item:last-child {
  border-bottom: none;
}

.faq-accordion__item h3 {
  font-size: 18px;
  margin: 0;
}

.faq-accordion__question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  width: 100%;
  padding-block: var(--space-3);
  background: none;
  border: none;
  font: inherit;
  font-weight: 600;
  color: var(--color-ink);
  text-align: left;
  cursor: pointer;
  transition: color var(--duration-fast) var(--ease-standard);
}

.faq-accordion__question[aria-expanded="true"] {
  color: var(--color-accent);
}

.faq-accordion__icon {
  position: relative;
  flex-shrink: 0;
  width: 18px;
  height: 18px;
}

.faq-accordion__icon::before,
.faq-accordion__icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  background: var(--color-accent);
  transform: translate(-50%, -50%);
  transition: transform var(--duration-base) var(--ease-standard);
}

.faq-accordion__icon::before {
  width: 100%;
  height: 2px;
}

.faq-accordion__icon::after {
  width: 2px;
  height: 100%;
}

.faq-accordion__question[aria-expanded="true"] .faq-accordion__icon::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

.faq-accordion__answer-wrap {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--duration-base) var(--ease-standard);
}

.faq-accordion__item.is-open .faq-accordion__answer-wrap {
  grid-template-rows: 1fr;
}

.faq-accordion__answer {
  overflow: hidden;
}

.faq-accordion__answer p {
  padding-bottom: var(--space-3);
  color: var(--color-ink-muted);
}

/* ---------- Contact: What Happens Next (Contact page) ----------
   Same "stack + horizontal divider on mobile, row + vertical divider from
   tablet up" recipe as the Homepage's .trust-bar, reused here rather than
   invented fresh — satisfies the brief's "explain the next step before the
   form" note without a new layout idea. */
.contact-next {
  padding-top: 0;
}

.contact-next__list {
  display: flex;
  flex-direction: column;
  list-style: none;
  margin: 0;
  padding: 0;
}

.contact-next__list li {
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-weight: 500;
}

.contact-next__list li:last-child {
  border-bottom: none;
}

@media (min-width: 640px) {
  .contact-next__list {
    flex-direction: row;
  }

  .contact-next__list li {
    flex: 1;
    padding-block: 0;
    padding-inline: var(--space-3);
    border-bottom: none;
    border-left: 1px solid var(--color-border);
  }

  .contact-next__list li:first-child {
    padding-left: 0;
    border-left: none;
  }
}

.contact-next__mark {
  flex-shrink: 0;
  color: var(--color-accent);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.02em;
}

/* ---------- Contact: Form + Reassurance Panel (Contact page) ----------
   Split composition per the brief: form is the primary column, a sticky
   panel beside it folds in Contact Details + Location Coverage rather than
   listing them as separate flat sections below — the richer realisation of
   the brief's flat Section Order, same evolution Process/FAQ already went
   through. DOM order is form-then-panel throughout, so mobile naturally
   stacks with the phone/reassurance panel straight after the form (per the
   brief's mobile note) with no reordering needed; the grid below is what
   turns that same order into a side-by-side split from 900px up. */
.contact-main__grid {
  display: grid;
  gap: var(--space-6);
}

@media (min-width: 900px) {
  .contact-main__grid {
    grid-template-columns: minmax(0, 1.4fr) minmax(280px, 1fr);
    align-items: start;
  }
}

.contact-form {
  max-width: 640px;
}

.contact-form__group {
  border: none;
  margin: 0 0 var(--space-6);
  padding: 0;
}

.contact-form__group legend {
  width: 100%;
  margin-bottom: var(--space-3);
  padding-bottom: var(--space-2);
  border-bottom: 1px solid var(--color-border);
  font-family: var(--font-heading);
  font-weight: 600;
  font-size: 17px;
}

.form-field {
  margin-top: var(--space-3);
}

.form-field:first-child {
  margin-top: 0;
}

.form-field label {
  display: block;
  margin-bottom: 6px;
  font-size: 15px;
  font-weight: 600;
}

.form-field__optional {
  font-weight: 400;
  color: var(--color-ink-muted);
}

.form-field input,
.form-field select,
.form-field textarea {
  width: 100%;
  padding: 12px 14px;
  border: 1px solid var(--color-border);
  border-radius: 4px;
  background: var(--color-bg);
  color: var(--color-ink);
  font: inherit;
  font-size: 16px;
  transition: border-color var(--duration-fast) var(--ease-standard),
              box-shadow var(--duration-fast) var(--ease-standard);
}

.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px rgba(41, 85, 163, 0.15);
}

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

.form-field__error {
  margin: 6px 0 0;
  color: var(--color-danger);
  font-size: 13px;
  font-weight: 500;
}

.form-field__error:empty {
  display: none;
}

.form-field.has-error input,
.form-field.has-error select,
.form-field.has-error textarea {
  border-color: var(--color-danger);
  background: var(--color-danger-bg);
}

.form-field.has-error input:focus,
.form-field.has-error textarea:focus {
  box-shadow: 0 0 0 3px rgba(179, 38, 30, 0.15);
}

.contact-form__submit {
  width: 100%;
}

@media (min-width: 540px) {
  .contact-form__submit {
    width: auto;
  }
}

.contact-form__reassurance {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
  font-size: 14px;
}

.contact-success h2 {
  margin-bottom: var(--space-2);
}

.contact-success p {
  color: var(--color-ink-muted);
  max-width: 52ch;
}

.contact-panel {
  background: var(--color-bg-alt);
  border-radius: 12px;
  padding: var(--space-4);
}

@media (min-width: 900px) {
  /* 113px header + var(--space-3) breathing room — same header-height figure
     already established for .service-quicknav/.faq-topicnav, just without
     a second sticky bar stacked on top of it here. */
  .contact-panel {
    position: sticky;
    top: 137px;
  }
}

.contact-panel__phone {
  display: block;
  margin-top: 4px;
  color: var(--color-accent);
  text-decoration: none;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 24px;
}

.contact-panel__note {
  margin-top: var(--space-1);
  color: var(--color-ink-muted);
  font-size: 14px;
}

.contact-panel__section {
  margin-top: var(--space-4);
  padding-top: var(--space-4);
  border-top: 1px solid var(--color-border);
}

.contact-panel__label--spaced {
  margin-top: var(--space-2);
}

/* ---------- Contact: Location Coverage (Contact page) ----------
   A schematic node diagram (Guildford hub + spokes out to each town) —
   deliberately abstract/not-to-scale rather than a real map embed, so it
   never implies false geographic precision for a placeholder address and
   adds no third-party script/dependency. Fixed pixel width rather than
   scaling with the viewport: SVG text scales with the whole graphic, and
   shrinking it to fit a 375px screen would make the labels illegible: the
   wrap scrolls horizontally on narrow screens instead, same pattern as the
   Services/FAQ pill nav. The plain-text list above it stays the primary
   accessible summary either way. */
.coverage__grid {
  display: grid;
  gap: var(--space-4);
  align-items: center;
}

@media (min-width: 900px) {
  .coverage__grid {
    grid-template-columns: minmax(280px, 0.8fr) minmax(0, 1.2fr);
    gap: var(--space-6);
  }
}

.coverage__copy h2 {
  margin-top: var(--space-1);
}

.coverage__copy > p {
  margin-top: var(--space-2);
  color: var(--color-ink-muted);
}

.coverage__list {
  font-weight: 500;
  color: var(--color-ink) !important;
}

.coverage__map-wrap {
  overflow-x: auto;
}

.coverage__map {
  display: block;
  width: 560px;
  height: auto;
}

.coverage__lines line {
  stroke: var(--color-border);
  stroke-width: 1.5;
}

.coverage__node circle {
  fill: var(--color-accent);
}

.coverage__node--hub circle {
  stroke: var(--color-bg);
  stroke-width: 4;
}

.coverage__node text {
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 600;
  fill: var(--color-ink);
  text-anchor: middle;
}

.coverage__node--hub text {
  font-weight: 700;
  fill: var(--color-accent);
}
