/* ==========================================================================
   Gibbs Auto Detailing — shared stylesheet
   Used by index.html, services.html and contact.html
   ========================================================================== */

/* --- Design tokens -------------------------------------------------------- */
:root {
  --bg:          #08090b;
  --bg-raised:   #0e1014;
  --bg-card:     #121519;
  --line:        #1e232b;
  --line-strong: #2b323c;

  --text:        #f2f4f7;
  --text-muted:  #9aa4b2;
  --text-dim:    #6b7482;

  /* Monochrome chrome/silver — matches the logo and keeps the site mono */
  --accent:      #e7eaee;
  --accent-soft: #ffffff;
  --accent-dim:  rgba(255, 255, 255, 0.07);
  --chrome:      linear-gradient(160deg, #ffffff 0%, #ffffff 26%, #aab1bb 48%, #f4f6f8 62%, #ffffff 100%);

  /* Agency FB is a licensed Microsoft desktop font and can't be served on the
     web. Saira Condensed is the closest free match — same squared, condensed,
     technical feel — with Barlow underneath it for body copy. */
  --font-display: 'Saira Condensed', 'Agency FB', ui-sans-serif, system-ui, sans-serif;
  --font-body:    'Barlow', ui-sans-serif, system-ui, -apple-system, sans-serif;

  --wrap:   1180px;
  --radius: 14px;
  --header-h: 112px;   /* kept in a token so the hero can pull up under it */

  /* ---- Vertical rhythm -------------------------------------------------
     ONE number controls the spacing between every major block on the page.
     Each section gets --rhythm above and below, so the gap between any two
     consecutive sections is always exactly 2 x --rhythm. Nothing sets its
     own section padding any more, which is what made the old page run at
     216 / 240 / 280px in different places.

       desktop (>=1440px) : 96px  ->  192px between sections
       tablet  (~ 900px)  : 81px  ->  162px
       phone   (390px)    : 56px  ->  112px

     To open the page up or tighten it, change --rhythm and nothing else. */
  --rhythm:     clamp(3.5rem, 6.6vw, 6rem);
  --gap-head:   2.5rem;   /* section heading -> its content */
  --gap-block:  2rem;     /* stacked blocks inside a section */

  --shadow:    0 20px 50px -20px rgba(0, 0, 0, 0.85);
  --ease:      cubic-bezier(0.22, 1, 0.36, 1);
}

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

html {
  scroll-behavior: smooth;
  /* offset for the sticky header when jumping to #anchors —
     header is 112px tall (+1px border), plus a little breathing room */
  scroll-padding-top: 126px;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

img { max-width: 100%; display: block; }
a   { color: inherit; text-decoration: none; }

/* Film grain over the whole page — one very faint SVG-noise tile. It stops the
   large near-black planes reading as flat vector fill and gives the photography
   a consistent, slightly analogue finish. Cheap: one fixed layer, no JS. */
body::after {
  content: '';
  position: fixed;
  inset: 0;
  z-index: 2000;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.82' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='180' height='180' filter='url(%23n)'/%3E%3C/svg%3E");
  opacity: 0.045;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 700;
  line-height: 1.08;
  /* Condensed faces don't want the negative tracking a normal-width font
     needs, and they read larger — sizes bumped to keep the same presence. */
  letter-spacing: 0.005em;
  text-transform: uppercase;
  margin: 0 0 0.5em;
}

h1 { font-size: clamp(2.9rem, 7.5vw, 5.4rem); }
h2 { font-size: clamp(2.2rem, 5vw, 3.5rem); }
/* Evens out multi-line headings on narrow screens (no orphaned last word).
   Progressive enhancement — browsers without text-wrap:balance ignore it. */
h1, h2 { text-wrap: balance; }
h3 { font-size: 1.35rem; letter-spacing: 0.02em; }

p { margin: 0 0 1em; color: var(--text-muted); }

::selection { background: var(--accent); color: #08090b; }

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

/* --- Layout helpers ------------------------------------------------------- */
.wrap {
  width: min(100% - 2.5rem, var(--wrap));
  margin-inline: auto;
}
/* wider variant — used for the gallery wall so the photography leads */
.wrap--wide { width: min(100% - 2.5rem, 1400px); }

.section { padding-block: var(--rhythm); }
.section--raised { background: var(--bg-raised); }
.section--tight  { padding-block: var(--rhythm); }   /* now identical - kept only so existing markup keeps working */

.section-head {
  max-width: 640px;
  margin-bottom: var(--gap-head);
}
.section-head--center {
  margin-inline: auto;
  text-align: center;
}
.section-head p { font-size: 1.05rem; margin-bottom: 0; }

/* Practical caveat under a section intro — quieter than body copy, and boxed
   just enough that it reads as a condition of booking rather than more prose. */
.note-inline {
  margin: 1.1rem auto 0;
  padding: 0.7rem 1.1rem;
  max-width: 44rem;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  background: var(--accent-dim);
  font-size: 0.9rem !important;
  color: var(--text-muted);
}

/* Centred call-to-action closing a section. Was an inline margin-top:2.75rem
   sitting in the HTML, which is exactly the kind of one-off that broke the
   rhythm — it now draws from the same scale as everything else. */
.section-cta {
  margin-top: var(--gap-block);
  text-align: center;
}

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 1rem;
}
.eyebrow::before {
  content: '';
  width: 26px;
  height: 1px;
  background: var(--accent);
}
/* Trailing dash, so a centred eyebrow is flanked on both sides rather than
   just led in from the left. The hero was missing it — it isn't a
   .section-head--center, so the rule below never reached it. */
.section-head--center .eyebrow::after,
.band .eyebrow::after,
.hero .eyebrow::after {
  content: '';
  width: 26px;
  height: 1px;
  background: var(--accent);
}

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  padding: 0.95rem 1.7rem;
  border: 1px solid transparent;
  border-radius: 999px;
  /* Must be stated explicitly. An <a class="btn"> has no background by default,
     but a <button class="btn"> keeps the UA's ButtonFace grey (#f0f0f0) — so
     ghost buttons rendered as near-white text on a near-white pill, a contrast
     ratio of 1.03. appearance:none also stops iOS restyling them. */
  appearance: none;
  -webkit-appearance: none;
  background: transparent;
  font-family: var(--font-body);
  font-size: 0.92rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  cursor: pointer;
  transition: transform 0.25s var(--ease), background 0.25s, border-color 0.25s, color 0.25s;
  white-space: nowrap;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

/* Brushed-chrome fill — the same gradient as the hero headline, so the primary
   action reads as part of the logo's metal bar rather than a flat white pill. */
.btn--primary {
  background: var(--chrome);
  color: #0a0a0a;
}
.btn--primary:hover { filter: brightness(1.07); }

.btn--ghost {
  border-color: var(--line-strong);
  color: var(--text);
}
.btn--ghost:hover {
  border-color: var(--accent);
  color: var(--accent);
}

.btn--block { width: 100%; }
.btn--lg { padding: 1.1rem 2.1rem; font-size: 1rem; }

/* --- Header --------------------------------------------------------------- */
/* Frosted bar: mostly opaque, with a blur so content scrolling underneath reads
   as a soft suggestion of movement rather than a sharp image competing with the
   nav. At the top of the page the hero starts below the bar, so there's nothing
   behind it and it reads as flat — the translucency only comes into play once
   you've scrolled, which is exactly when it should.
   84% is deliberate: enough to sense motion, opaque enough that a bright photo
   passing beneath can't fight the nav text. */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(8, 9, 11, 0.84);
  backdrop-filter: blur(18px) saturate(115%);
  -webkit-backdrop-filter: blur(18px) saturate(115%);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s, background 0.3s;
}

/* Fallback: without backdrop-filter the blur never happens, so a see-through
   bar would just look like a smeared overlay. Go solid instead. */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .site-header { background: var(--bg); }
}
/* Once you've scrolled, a hairline defines the bar's lower edge so it separates
   from the content moving beneath it. At rest there's no line — the bar and the
   section below it are the same colour, so it reads as one surface. */
.site-header.is-stuck {
  border-bottom-color: var(--line);
}
/* Menu open: the panel needs the bar behind it to be solid, whatever the
   scroll position. Driven by a class from script.js rather than :has(), so it
   doesn't depend on selector support. */
.site-header.is-menu-open {
  border-bottom-color: var(--line);
  background: rgba(8, 9, 11, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
}

/* Three columns so the logo sits dead-centre regardless of how wide the links
   and phone number are — space-between would only centre it by luck. */
.nav {
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 2rem;
  height: var(--header-h);
}
.nav .logo      { grid-column: 2; justify-self: center; }
.nav-links      { grid-column: 1; grid-row: 1; justify-self: start; }
.nav-cta        { grid-column: 3; grid-row: 1; justify-self: end; }

.logo {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 1.02rem;
  letter-spacing: -0.01em;
  line-height: 1.15;
}
/* Header: the horizontal wordmark lockup. A wide mark needs more width than a
   badge to stay legible, so it's sized on width with height left to follow.
   No shadow — it sits on a solid bar now, so a halo would only add grime. */
.logo-lockup {
  width: 208px;
  height: auto;
  flex: none;
}

/* Footer: the round black badge, masked to a transparent circle from the
   1080px original. No added ring — the artwork carries its own white outline. */
.footer-badge {
  width: 92px;
  height: 92px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
  margin-bottom: 0.25rem;
}

/* Admin panel still uses the badge in its header and login card. */
.logo-mark {
  width: 42px;
  height: 42px;
  flex: none;
  border-radius: 50%;
  object-fit: cover;
}
.logo-mark--lg { width: 76px; height: 76px; }
.logo span { display: block; }
.logo small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 2.1rem;
  list-style: none;
  margin: 0;
  padding: 0;
}
.nav-links a {
  position: relative;
  font-size: 0.92rem;
  font-weight: 500;
  color: var(--text-muted);
  transition: color 0.2s;
}
.nav-links a:hover { color: var(--text); }
.nav-links a.is-active { color: var(--text); }
.nav-links a.is-active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -6px;
  height: 2px;
  border-radius: 2px;
  background: var(--accent);
}

.nav-cta { display: flex; align-items: center; gap: 1rem; }

/* Social links in the bar. Bordered squares rather than bare glyphs so they
   read as buttons and give a 38px target without needing extra padding. */
.nav-social {
  display: flex;
  align-items: center;
  gap: 0.45rem;
}
.nav-social a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  color: var(--text-muted);
  transition: color 0.2s, border-color 0.2s, transform 0.2s var(--ease);
}
.nav-social a:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-2px);
}
.nav-social svg { width: 17px; height: 17px; }

/* Duplicate set that lives inside the mobile menu. Hidden on desktop, where the
   bar version is used instead — three icons plus a hamburger plus the logo will
   not fit across a 390px bar without something being squashed. */
.nav-menu-social { display: none; }

.nav-toggle {
  display: none;
  width: 42px;
  height: 42px;
  padding: 0;
  background: none;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  cursor: pointer;
}
.nav-toggle span {
  display: block;
  width: 18px;
  height: 2px;
  margin: 4px auto;
  background: var(--text);
  border-radius: 2px;
  transition: transform 0.3s var(--ease), opacity 0.2s;
}
.nav-toggle[aria-expanded='true'] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded='true'] span:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded='true'] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }

/* --- Hero ----------------------------------------------------------------- */
/* Sits below the header rather than under it — the bar is its own strip now,
   so the hero starts where the bar ends and nothing is overlapped. */
.hero {
  position: relative;
  /* Top gap pulled in by 4rem — exactly one square of the 64px background grid,
     so the eyebrow lands a row closer to the bar. Floored with max() so it
     can't collapse on a phone, where --rhythm is already small. */
  padding-block: max(2.25rem, calc(var(--rhythm) + 2.5rem - 4rem)) var(--rhythm);
  overflow: hidden;
}
.hero::before {
  /* soft light bloom behind the headline */
  content: '';
  position: absolute;
  top: -18%;
  left: 50%;
  width: 900px;
  height: 620px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.10), transparent 68%);
  pointer-events: none;
}
.hero::after {
  /* faint grid to stop the black looking flat */
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(rgba(255, 255, 255, 0.022) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, 0.022) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(ellipse at 50% 30%, #000 20%, transparent 72%);
  -webkit-mask-image: radial-gradient(ellipse at 50% 30%, #000 20%, transparent 72%);
  pointer-events: none;
}
/* Hero background photo.
   TODO: drop the shot in as assets/hero.jpg and uncomment background-image.
   Kept dark and low-contrast on purpose — white headline over a car photo goes
   unreadable fast, so the image sits behind a scrim rather than at full bite. */
.hero-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  /* Ferrari 488 Pista, front three-quarter.
     Two art-directed crops rather than one file. The originals are 4032x3024,
     but the hero was being fed a 1536px copy — and `cover` scales by WIDTH, so
     a 1920px desktop upscaled it 1.25x and a 2560px monitor 1.67x. That's the
     softness on desktop. A phone at 390px only ever needed ~1170px, which is
     why mobile looked fine.
     Desktop now gets a 2560x1160 landscape band (no upscaling up to a 2560
     monitor); mobile gets a 1200x1500 upright crop below, so a portrait hero
     shows the car rather than a narrow slice of it. */
  background-image: url('assets/hero.jpg');
  background-size: cover;
  background-position: center 50%;
  /* Miami Blue is a bright colour — this frame measures ~96 luminance across
     the headline strip against 82 for the Ferrari and 49 for the cabin shot.
     So the desaturation is pushed harder (0.55) to bring the blue down to a
     mid grey rather than dimming the whole photo, which keeps the car's shape
     and highlights while giving the white type something to sit on. */
  opacity: 0.75;
  filter: grayscale(0.55) contrast(1.12);
}
.hero-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  /* Lighter overall so the car reads, but the radial still pools behind the
     headline specifically — the type sits in the one softened area while the
     car stays clear at the edges. Fades to solid at the base so the hero joins
     the next section without a seam. */
  background:
    linear-gradient(180deg, rgba(8,9,11,0.34) 0%, rgba(8,9,11,0.54) 60%, var(--bg) 100%),
    radial-gradient(ellipse 60% 44% at 50% 44%, rgba(8,9,11,0.70), rgba(8,9,11,0.08) 100%);
}

.hero .wrap { position: relative; z-index: 1; }

.hero-inner {
  max-width: 820px;
  margin-inline: auto;
  text-align: center;
}
/* Scaled back ~18% and slightly see-through so the photograph leads and the
   type sits with it rather than over it. Scoped to the hero — interior page
   titles keep their full weight. Held at 0.88: any lower and it starts to look
   like a mistake rather than a deliberate softening. */
.hero h1 {
  margin-bottom: 1.1rem;
  font-size: clamp(2.4rem, 6.2vw, 4.45rem);
  opacity: 0.88;
}
/* brushed-chrome text, echoing the metal bar in the logo */
.hero h1 em {
  font-style: normal;
  background: var(--chrome);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.hero-sub {
  font-size: clamp(1.02rem, 1.9vw, 1.2rem);
  max-width: 620px;
  margin-inline: auto;
  margin-bottom: 2.2rem;
}

.hero-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  justify-content: center;
}

.hero-note {
  margin-top: 1.7rem;
  font-size: 0.85rem;
  color: var(--text-dim);
}

/* page hero — smaller variant used on services/contact */
.page-hero {
  padding-block: calc(var(--rhythm) * 0.8) var(--rhythm);
  text-align: center;
  position: relative;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
}
.page-hero::before {
  content: '';
  position: absolute;
  top: -55%;
  left: 50%;
  width: 760px;
  height: 520px;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at center, rgba(255, 255, 255, 0.08), transparent 70%);
  pointer-events: none;
}
/* Faint echo of the home hero photo (already cached by then) so interior pages
   open on depth rather than a flat black strip. Kept well under legibility
   thresholds and faded out before the first section starts. */
.page-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: url('assets/hero.jpg') center 40% / cover no-repeat;
  filter: grayscale(0.7) contrast(1.05);
  opacity: 0.14;
  mask-image: linear-gradient(180deg, #000 30%, transparent 96%);
  -webkit-mask-image: linear-gradient(180deg, #000 30%, transparent 96%);
}
.page-hero .wrap { position: relative; z-index: 1; }
.page-hero p {
  max-width: 580px;
  margin-inline: auto;
  margin-bottom: 0;
  font-size: 1.05rem;
}

.crumbs {
  font-size: 0.8rem;
  color: var(--text-dim);
  margin-bottom: 1.2rem;
}
.crumbs a:hover { color: var(--accent); }

/* --- Stat strip ----------------------------------------------------------- */
.stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  margin-top: clamp(3rem, 6vw, 4.5rem);
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
/* Content sized to fill the tile rather than float in the middle of it —
   padding pulled in, icon and type scaled up. */
.stat {
  background: var(--bg);
  padding: 1.5rem 1rem;
  text-align: center;
}
.stat-icon {
  display: grid;
  place-items: center;
  width: 60px;
  height: 60px;
  margin: 0 auto 0.9rem;
  border-radius: 15px;
  background: var(--accent-dim);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--accent);
}
.stat-icon svg { width: 30px; height: 30px; }
.stat b {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3.1vw, 2.3rem);
  font-weight: 700;
  line-height: 1.1;
  text-transform: uppercase;
  color: var(--text);
  letter-spacing: 0.01em;
}
.stat span {
  display: block;
  margin-top: 0.3rem;
  font-size: 0.85rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
}

/* --- Generic card grid ---------------------------------------------------- */
.grid {
  display: grid;
  gap: 1.25rem;
}
.grid--2 { grid-template-columns: repeat(2, 1fr); }
/* Fits however many services he has without leaving an orphan on its own row. */
.grid--auto { grid-template-columns: repeat(auto-fit, minmax(255px, 1fr)); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--4 { grid-template-columns: repeat(4, 1fr); }

.card {
  position: relative;
  padding: 2rem 1.75rem;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  transition: border-color 0.3s, transform 0.3s var(--ease), background 0.3s;
}
.card:hover {
  border-color: var(--line-strong);
  transform: translateY(-4px);
}
.card p:last-child { margin-bottom: 0; }

.card-icon {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: 1.3rem;
  border-radius: 12px;
  background: var(--accent-dim);
  border: 1px solid rgba(255, 255, 255, 0.14);
  color: var(--accent);
}
.card-icon svg { width: 22px; height: 22px; }

/* --- Service cards (home) ------------------------------------------------- */
.service-card { display: flex; flex-direction: column; }

/* Photo-led variant: the image runs edge to edge, so the card kills its own
   padding and the body puts it back. */
.card--media { padding: 0; overflow: hidden; }
.service-photo {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  border-radius: 0;
  border: 0;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
  filter: grayscale(0.35) contrast(1.04);
  transition: filter 0.6s, transform 1.1s var(--ease);
}
@media (hover: hover) {
  .card--media:hover .service-photo {
    filter: grayscale(0) contrast(1.02);
    transform: scale(1.04);
  }
}
.service-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 1.6rem 1.75rem 1.9rem;
}
.service-card .price {
  margin-top: auto;
  padding-top: 1.4rem;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  color: var(--text);
}
.service-card .price small {
  display: block;
  font-family: var(--font-body);
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-dim);
}

.tick-list {
  list-style: none;
  margin: 0 0 1.4rem;
  padding: 0;
  display: grid;
  gap: 0.6rem;
}
.tick-list li {
  position: relative;
  padding-left: 1.65rem;
  font-size: 0.92rem;
  color: var(--text-muted);
}
.tick-list li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.52em;
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--accent);
}

/* --- Split (about) -------------------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.split--reverse .split-media { order: 2; }

/* --- Image placeholders ---------------------------------------------------
   TODO: replace each .ph block with a real <img> once photos are supplied.
   ------------------------------------------------------------------------- */
.ph {
  position: relative;
  display: grid;
  place-items: center;
  border-radius: var(--radius);
  border: 1px dashed var(--line-strong);
  background:
    linear-gradient(135deg, #14181d 0%, #0d1013 50%, #16191f 100%);
  color: var(--text-dim);
  font-size: 0.74rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  overflow: hidden;
}
.ph::after {
  /* subtle diagonal sheen so the placeholder reads as "car photo goes here" */
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(115deg, transparent 42%, rgba(255, 255, 255, 0.05) 50%, transparent 58%);
}
.ph--4x3   { aspect-ratio: 4 / 3; }
.ph--3x2   { aspect-ratio: 3 / 2; }
.ph--1x1   { aspect-ratio: 1 / 1; }
.ph--tall  { aspect-ratio: 3 / 4; }
/* Map slot (contact page). NOTE: never pair a min-height with the wide ratio —
   min-height transfers through aspect-ratio into a min-WIDTH (240px × 16/6 =
   640px) and forces horizontal scroll on phones. The ratio switches instead. */
.ph--map { aspect-ratio: 16 / 6; }
@media (max-width: 620px) {
  .ph--map { aspect-ratio: 4 / 3; }
}

/* Coverage map. No forced aspect-ratio — each crop is already framed around the
   radius circle, so letting the image set its own height is what keeps the
   circle whole. The photo treatment elsewhere desaturates on rest and restores
   colour on hover; a map has no colour to restore, so it opts out. */
.figure-frame--map {
  max-width: 900px;
  margin-inline: auto;
}
/* The two crops have different shapes (1100x700 vs 760x700), and the <img>
   carries only the desktop dimensions — so a phone would reserve the wide ratio
   and then jump when the square-ish file arrived. State the ratio per
   breakpoint instead, and let height follow from it. */
.figure-frame--map img {
  width: 100%;
  height: auto;
  aspect-ratio: 1100 / 700;
  object-fit: cover;
  filter: none;
}
@media (max-width: 620px) {
  .figure-frame--map img { aspect-ratio: 760 / 700; }
}
@media (hover: hover) {
  .figure-frame--map:hover img { filter: none; transform: none; }
}

/* --- Photography treatment --------------------------------------------------
   All photos sit slightly desaturated at rest so the colourful cars don't
   fight the monochrome palette; pointer hover releases the full colour.
   Touch devices (no hover) get the gentler rest state permanently. */
.figure-frame {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-card);
  border: 1px solid var(--line-strong);
}
.figure-frame img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
  filter: grayscale(0.35) contrast(1.04);
  transition: filter 0.6s, transform 1.1s var(--ease);
}
.figure-frame::after {
  /* inner hairline + soft bottom shade — reads as print finishing */
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow:
    inset 0 0 0 1px rgba(255, 255, 255, 0.05),
    inset 0 -90px 90px -70px rgba(0, 0, 0, 0.6);
}
@media (hover: hover) {
  .figure-frame:hover img,
  a:hover > .figure-frame img {
    filter: grayscale(0) contrast(1.02);
    transform: scale(1.03);
  }
}

/* Aspect helpers for framed photos (portrait sources crop badly into wide
   bands, so layouts that can take a portrait use it). */
.figure-frame--45  { aspect-ratio: 4 / 5; }
.figure-frame--11  { aspect-ratio: 1 / 1; }
.figure-frame--43  { aspect-ratio: 4 / 3; }

/* --- About page: overlapping photo pair ------------------------------------ */
.media-stack {
  position: relative;
  margin-bottom: 3rem;   /* room for the overhanging detail shot */
}
.media-stack .figure-frame:first-child {
  width: 86%;
  aspect-ratio: 4 / 5;
}
.media-stack .figure-frame:last-child {
  position: absolute;
  right: 0;
  bottom: -3rem;
  width: 52%;
  aspect-ratio: 1 / 1;
  outline: 8px solid var(--bg);
  box-shadow: var(--shadow);
}

/* --- Full-bleed statement band ---------------------------------------------
   The one place the photography runs edge to edge. The image is pinned on
   desktop for a gentle depth-on-scroll feel; phones and reduced-motion get a
   plain (still full-bleed) image. */
.band {
  position: relative;
  padding-block: var(--rhythm);
  overflow: hidden;
  border-block: 1px solid var(--line);
}
.band-bg {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background-size: cover;
  background-position: center 38%;
  filter: grayscale(0.9) contrast(1.1) brightness(0.85);
  opacity: 0.34;
}
.band::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background:
    linear-gradient(180deg, var(--bg) 0%, transparent 26%, transparent 74%, var(--bg) 100%),
    radial-gradient(ellipse at 50% 50%, transparent 30%, rgba(8, 9, 11, 0.5) 100%);
}
.band .wrap {
  position: relative;
  z-index: 1;
  text-align: center;
}
.band h2 {
  font-size: clamp(2.8rem, 7vw, 5rem);
  max-width: 800px;
  margin-inline: auto;
}
.band h2 em {
  font-style: normal;
  background: var(--chrome);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.band p {
  max-width: 520px;
  margin: 0 auto;
  font-size: 1.02rem;
  color: var(--text-muted);
}
@media (min-width: 961px) and (prefers-reduced-motion: no-preference) {
  .band-bg { background-attachment: fixed; }
}

/* --- Process steps -------------------------------------------------------- */
.steps {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1.25rem;
  counter-reset: step;
}
.step {
  position: relative;
  padding: 2rem 1.5rem;
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--bg-card);
}
.step { transition: border-color 0.3s; }
.step:hover { border-color: var(--line-strong); }
.step::before {
  counter-increment: step;
  content: '0' counter(step);
  display: block;
  margin-bottom: 1rem;
  font-family: var(--font-display);
  font-size: 1.9rem;
  font-weight: 700;
  color: var(--accent);
  opacity: 0.55;
  letter-spacing: -0.03em;
}
.step h3 { font-size: 1.05rem; margin-bottom: 0.45rem; }
.step p { font-size: 0.9rem; margin-bottom: 0; }

/* --- Gallery -------------------------------------------------------------- */
/* Four equal tiles in a single strip. Was a six-tile mosaic — the client felt
   the home page carried too many pictures, and the full set lives on the
   gallery anyway. */
.gallery {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 240px;
  gap: 1rem;
}
.gallery .ph { aspect-ratio: auto; height: 100%; }
.gallery img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: var(--radius);
  background: var(--bg-card);
  box-shadow: 0 0 0 1px var(--line);
  filter: grayscale(0.35) contrast(1.04);
  transition: filter 0.6s, transform 0.7s var(--ease), box-shadow 0.3s;
}
@media (hover: hover) {
  .gallery img:hover {
    filter: grayscale(0) contrast(1.02);
    transform: translateY(-4px);
    box-shadow: 0 0 0 1px var(--line-strong), var(--shadow);
  }
}

/* --- Photo wall (gallery page) -------------------------------------------- */
/* Masonry-ish columns: the source photos are all portrait phone shots, and a
   fixed-ratio grid would crop the subject out of most of them. */
.photo-wall {
  columns: 3;
  column-gap: 1.1rem;
}
.photo-tile {
  position: relative;
  break-inside: avoid;
  margin: 0 0 1.1rem;
  border-radius: var(--radius);
  overflow: hidden;
  background: var(--bg-card);
  border: 1px solid var(--line);
  transition: border-color 0.3s;
}
.photo-tile a { display: block; cursor: zoom-in; }
.photo-tile img {
  width: 100%;
  height: auto;
  display: block;
  filter: grayscale(0.35) contrast(1.04);
  transition: filter 0.6s, transform 1.1s var(--ease);
}
/* caption sits over the photo behind a scrim, not on a grey bar below it */
.photo-tile figcaption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 2.6rem 1.1rem 0.95rem;
  font-size: 0.84rem;
  color: var(--text);
  background: linear-gradient(180deg, transparent, rgba(5, 6, 8, 0.88));
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.4s;
}
@media (hover: hover) {
  .photo-tile:hover { border-color: var(--line-strong); }
  .photo-tile:hover img {
    filter: grayscale(0) contrast(1.02);
    transform: scale(1.035);
  }
  .photo-tile:hover figcaption,
  .photo-tile:focus-within figcaption { opacity: 1; }
}
@media (hover: none) {
  .photo-tile figcaption { opacity: 1; }
}
.photo-wall .data-note { column-span: all; }

@media (max-width: 960px) { .photo-wall { columns: 2; } }
@media (max-width: 620px) { .photo-wall { columns: 1; } }

/* --- Lightbox (gallery page) ----------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 400;
  display: grid;
  place-items: center;
  padding: clamp(1rem, 4vw, 3rem);
  background: rgba(5, 6, 8, 0.93);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  opacity: 0;
  transition: opacity 0.3s;
}
.lightbox.is-open { opacity: 1; }
.lightbox figure { margin: 0; max-width: min(100%, 1100px); }
.lightbox img {
  max-width: 100%;
  max-height: 84vh;
  width: auto;
  margin-inline: auto;
  border-radius: var(--radius);
  box-shadow: 0 40px 90px -30px rgba(0, 0, 0, 0.9), 0 0 0 1px var(--line-strong);
}
.lightbox figcaption {
  margin-top: 0.9rem;
  text-align: center;
  font-size: 0.88rem;
  color: var(--text-muted);
}
.lightbox-close {
  position: absolute;
  top: 1.1rem;
  right: 1.1rem;
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--text);
  font-size: 1.5rem;
  line-height: 1;
  cursor: pointer;
  transition: border-color 0.2s, color 0.2s;
}
.lightbox-close:hover { border-color: var(--accent); color: var(--accent); }

/* --- Testimonials --------------------------------------------------------- */
.quote {
  padding: 2rem 1.75rem;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.stars {
  display: flex;
  gap: 3px;
  margin-bottom: 1rem;
  color: var(--accent);
}
.stars svg { width: 15px; height: 15px; }
.quote blockquote {
  margin: 0 0 1.4rem;
  font-size: 0.98rem;
  color: var(--text);
  line-height: 1.7;
}
.quote figcaption {
  font-size: 0.85rem;
  color: var(--text-dim);
}
.quote figcaption b {
  display: block;
  color: var(--text);
  font-weight: 600;
}

/* --- FAQ / accordion ------------------------------------------------------ */
.faq { max-width: 780px; margin-inline: auto; }
.faq-item {
  border-bottom: 1px solid var(--line);
}
.faq-q {
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.4rem 0;
  background: none;
  border: 0;
  color: var(--text);
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 600;
  text-align: left;
  cursor: pointer;
  transition: color 0.2s;
}
.faq-q:hover { color: var(--accent); }
.faq-q::after {
  content: '';
  flex: none;
  width: 11px;
  height: 11px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg) translate(-2px, -2px);
  transition: transform 0.3s var(--ease);
}
.faq-q[aria-expanded='true']::after {
  transform: rotate(-135deg) translate(-3px, -3px);
}
.faq-a {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.35s var(--ease);
}
.faq-a p {
  padding-bottom: 1.4rem;
  margin: 0;
  font-size: 0.95rem;
}

/* --- Pricing tiers (services page) ---------------------------------------- */
.tiers {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
  align-items: start;
}
.tier {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 2.25rem 1.9rem;
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}
.tier--featured {
  border-color: rgba(255, 255, 255, 0.30);
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.045), var(--bg-card) 55%);
  box-shadow: var(--shadow);
}
.tier-flag {
  position: absolute;
  top: -11px;
  left: 50%;
  transform: translateX(-50%);
  padding: 0.28rem 0.85rem;
  border-radius: 999px;
  background: var(--accent);
  color: #0a0a0a;
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
}
.tier h3 { font-size: 1.3rem; margin-bottom: 0.35rem; }
.tier .tier-blurb {
  font-size: 0.9rem;
  min-height: 2.6em;
}
.tier-price {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  padding: 1.1rem 0 1.4rem;
  margin-bottom: 1.4rem;
  border-bottom: 1px solid var(--line);
}
.tier-price b {
  font-family: var(--font-display);
  font-size: 2.4rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  color: var(--text);
}
.tier-price span { font-size: 0.85rem; color: var(--text-dim); }
.tier .btn { margin-top: auto; }
.tier .tick-list { margin-bottom: 1.75rem; }

/* Long "price varies with…" notes sit under the price, not inside it. */
.tier-note {
  margin: -0.9rem 0 1.4rem;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--text-dim);
}

/* --- Detailed service rows (services page) -------------------------------- */
.svc-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
  padding: clamp(2.5rem, 5vw, 4rem) 0;
  border-bottom: 1px solid var(--line);
}
.svc-row:last-of-type { border-bottom: 0; }
.svc-row:nth-child(even) .svc-media { order: 2; }
/* The source photos are portrait phone shots — shown portrait, not squashed
   into a wide 3:2 crop that would lose the car. */
.svc-media .figure-frame {
  aspect-ratio: 4 / 5;
  max-width: 500px;
  margin-inline: auto;
}
.svc-row h2 { font-size: clamp(1.6rem, 3vw, 2.15rem); }
.svc-meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.6rem;
  margin-bottom: 1.4rem;
}
.pill {
  padding: 0.32rem 0.85rem;
  border: 1px solid var(--line-strong);
  border-radius: 999px;
  font-size: 0.76rem;
  font-weight: 500;
  color: var(--text-muted);
}
.pill--accent {
  border-color: rgba(255, 255, 255, 0.26);
  background: var(--accent-dim);
  color: var(--accent);
}

/* --- Add-ons table -------------------------------------------------------- */
.addons {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.addon {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.05rem 1.5rem;
  border-bottom: 1px solid var(--line);
  background: var(--bg-card);
}
.addon:last-child { border-bottom: 0; }
.addon { transition: background 0.25s; }
.addon:hover { background: #161a1f; }
.addon strong { font-weight: 600; font-size: 0.95rem; }
.addon p { margin: 0.1rem 0 0; font-size: 0.85rem; }
.addon-price {
  flex: none;
  font-family: var(--font-display);
  font-weight: 600;
  color: var(--accent);
}

/* --- Contact page --------------------------------------------------------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1.15fr 0.85fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
}
/* Grid items default to min-width:auto, so one long unbreakable string (the
   email address) can force the column past the viewport on ~360px phones. */
.contact-grid > * { min-width: 0; }
.contact-list strong { overflow-wrap: anywhere; }

.form-card {
  padding: clamp(1.75rem, 3vw, 2.5rem);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
}

.field { margin-bottom: 1.15rem; }
.field label {
  display: block;
  margin-bottom: 0.45rem;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--text);
}
.field label .req { color: var(--accent); }

.field input,
.field select,
.field textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--bg);
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  color: var(--text);
  font-family: var(--font-body);
  font-size: 0.95rem;
  transition: border-color 0.2s, background 0.2s;
}
.field textarea { min-height: 130px; resize: vertical; }
.field input::placeholder,
.field textarea::placeholder { color: var(--text-dim); }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: #0b0d10;
}
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%239aa4b2' d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 1rem center;
  background-size: 11px;
  padding-right: 2.5rem;
}

.field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1.15rem;
}

.consent {
  display: flex;
  align-items: flex-start;
  gap: 0.65rem;
  margin-bottom: 1.4rem;
  font-size: 0.85rem;
  color: var(--text-muted);
}
.consent input {
  width: auto;
  margin-top: 0.25rem;
  flex: none;
  accent-color: var(--accent);
}

.form-note {
  margin: 1rem 0 0;
  font-size: 0.8rem;
  color: var(--text-dim);
  text-align: center;
}

.form-status {
  display: none;
  margin-top: 1rem;
  padding: 0.85rem 1.1rem;
  border-radius: 10px;
  font-size: 0.9rem;
}
.form-status.is-visible { display: block; }
.form-status--ok {
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: var(--accent-soft);
}
/* A failed enquiry has to look failed. Overrides --ok, which is on the element
   in the markup so the pre-JS state still has a sane style. */
.form-status--error {
  background: rgba(220, 76, 70, 0.12);
  border: 1px solid rgba(220, 76, 70, 0.55);
  color: #ffb4ae;
}
.form-status--error a { color: inherit; }

/* Honeypot: off-screen rather than display:none, since some bots skip hidden
   fields but not positioned ones. Never focusable, never announced. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

/* contact detail list */
.contact-list {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  display: grid;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.contact-list li {
  display: flex;
  align-items: flex-start;
  gap: 1rem;
  padding: 1.25rem 1.4rem;
  background: var(--bg-card);
}
.contact-list .card-icon {
  width: 40px;
  height: 40px;
  margin: 0;
  flex: none;
}
.contact-list span {
  display: block;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 0.15rem;
}
.contact-list strong {
  font-size: 1rem;
  font-weight: 600;
  color: var(--text);
}
.contact-list a strong:hover { color: var(--accent); }

.hours {
  list-style: none;
  margin: 0;
  padding: 0;
}
.hours li {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.65rem 0;
  border-bottom: 1px solid var(--line);
  font-size: 0.92rem;
  color: var(--text-muted);
}
.hours li:last-child { border-bottom: 0; }
.hours b { color: var(--text); font-weight: 600; }

.area-tags {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 1.25rem;
}

/* --- CTA band ------------------------------------------------------------- */
.cta-band {
  position: relative;
  padding: clamp(3rem, 7vw, 5rem) clamp(1.5rem, 5vw, 4rem);
  border: 1px solid var(--line);
  border-radius: 20px;
  background:
    radial-gradient(ellipse at 20% 0%, rgba(255, 255, 255, 0.10), transparent 60%),
    var(--bg-card);
  text-align: center;
  overflow: hidden;
}
/* whisper of the foam texture behind the CTA — depth, not decoration */
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background: url('assets/band-foam.jpg') center 30% / cover no-repeat;
  filter: grayscale(1) contrast(1.1);
  opacity: 0.07;
  pointer-events: none;
}
.cta-band > * { position: relative; }
.cta-band h2 { max-width: 640px; margin-inline: auto; }
.cta-band p {
  max-width: 520px;
  margin-inline: auto;
  margin-bottom: 2rem;
}
.cta-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.9rem;
  justify-content: center;
}

/* --- Footer --------------------------------------------------------------- */
.site-footer {
  border-top: 1px solid var(--line);
  padding: clamp(3rem, 6vw, 4.5rem) 0 2rem;
  background: var(--bg-raised);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.5fr 1fr 1fr 1.2fr;
  gap: 2.5rem;
  padding-bottom: 2.75rem;
  border-bottom: 1px solid var(--line);
}
.footer-grid h4 {
  font-family: var(--font-body);
  font-size: 0.76rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-dim);
  margin-bottom: 1.1rem;
}
.footer-grid ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.65rem;
}
.footer-grid a {
  font-size: 0.92rem;
  color: var(--text-muted);
  transition: color 0.2s;
}
.footer-grid a:hover { color: var(--accent); }
.footer-brand p {
  font-size: 0.9rem;
  margin: 1.1rem 0 1.3rem;
  max-width: 300px;
}
.socials { display: flex; gap: 0.6rem; }
.socials a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border: 1px solid var(--line-strong);
  border-radius: 10px;
  color: var(--text-muted);
  transition: color 0.2s, border-color 0.2s, transform 0.2s var(--ease);
}
.socials a:hover {
  color: var(--accent);
  border-color: var(--accent);
  transform: translateY(-2px);
}
.socials svg { width: 17px; height: 17px; }

.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  justify-content: space-between;
  padding-top: 1.75rem;
  font-size: 0.82rem;
  color: var(--text-dim);
}

/* --- Data-driven placeholder -----------------------------------------------
   Shown while services load, and if they can't be loaded at all. */
.data-note {
  margin: 0;
  padding: 2.5rem 1.5rem;
  text-align: center;
  font-size: 0.95rem;
  color: var(--text-muted);
  border: 1px dashed var(--line-strong);
  border-radius: var(--radius);
}

/* --- Scroll reveal -------------------------------------------------------- */
.reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.7s var(--ease), transform 0.7s var(--ease);
}
.reveal.is-in {
  opacity: 1;
  transform: none;
}

/* --- Responsive ----------------------------------------------------------- */
@media (max-width: 960px) {
  .grid--4 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
  .steps   { grid-template-columns: repeat(2, 1fr); }
  .tiers   { grid-template-columns: 1fr; max-width: 520px; margin-inline: auto; }
  .tier--featured { order: -1; }

  .split,
  .svc-row,
  .contact-grid { grid-template-columns: 1fr; }
  .split--reverse .split-media,
  .svc-row:nth-child(even) .svc-media { order: 0; }

  .gallery { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 190px; }

  .footer-grid { grid-template-columns: 1fr 1fr; gap: 2rem; }
  .footer-brand { grid-column: 1 / -1; }

  /* Touch targets: the footer link lists render ~18px tall as bare text.
     Pad each link out to ~40px on touch-first widths; the list gap shrinks
     so the visual rhythm stays roughly the same. */
  .footer-grid ul { gap: 0.1rem; }
  .footer-grid ul a { display: inline-block; padding-block: 0.7rem; }
  .socials a { width: 44px; height: 44px; }

  /* mobile nav */
  .nav-toggle { display: block; }
  .nav-links {
    position: fixed;
    inset: var(--header-h) 0 auto;
    /* The desktop rule sets justify-self:start for the grid layout. On an
       abspos grid child that alignment wins over left:0/right:0 and shrinks
       the panel to its content width (~100px) instead of spanning the screen. */
    justify-self: stretch;
    width: auto;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 1rem 1.25rem 1.75rem;
    background: var(--bg-raised);
    border-bottom: 1px solid var(--line);
    /* Hidden state must clear the top of the viewport completely. A percentage
       transform is relative to the panel's own height, so -120% left 26px of it
       still showing below the top edge (it starts at top:var(--header-h), not 0)
       — which is the pale bar that was appearing above the logo. Subtracting the
       header height as well guarantees the bottom edge lands exactly at 0. */
    visibility: hidden;
    transform: translateY(calc(-100% - var(--header-h)));
    transition: transform 0.35s var(--ease), visibility 0s linear 0.35s;
  }
  .nav-links.is-open {
    visibility: visible;
    transform: translateY(0);
    transition: transform 0.35s var(--ease), visibility 0s;
  }
  .nav-links li { border-bottom: 1px solid var(--line); }
  .nav-links li:last-child { border-bottom: 0; }
  .nav-links a {
    display: block;
    padding: 0.95rem 0;
    font-size: 1rem;
  }
  .nav-links a.is-active::after { display: none; }

  /* Bar is too narrow for icons at phone widths — swap to the in-menu set. */
  .nav-social { display: none; }
  .nav-menu-social {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    padding-top: 1.1rem;
    border-bottom: 0;
  }
  .nav-menu-social a {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 1px solid var(--line-strong);
    border-radius: 11px;
    color: var(--text-muted);
  }
  .nav-menu-social a:hover { color: var(--accent); border-color: var(--accent); }
  .nav-menu-social svg { width: 19px; height: 19px; }
}

@media (max-width: 620px) {
  html { scroll-padding-top: 106px; }  /* header shrinks to 92px (+border) */
  /* Upright hero crop on phones. A landscape band in a portrait hero box would
     be scaled to fill the height and lose most of the car off the sides; this
     version is framed for the taller shape and is a smaller download too. */
  .hero-bg { background-image: url('assets/hero-mobile.jpg'); }

  /* Stay three across on phones, matching desktop. Stacked they ran down a
     whole screen and read as three separate claims instead of one row of
     reassurance. Everything scales down to fit ~100px columns. */
  .stats { grid-template-columns: repeat(3, 1fr); }
  /* Same intent on phones — bigger content, tighter padding — but capped by a
     ~100px column, so it scales rather than simply inheriting desktop sizes. */
  .stat { padding: 1rem 0.25rem; }
  .stat-icon { width: 42px; height: 42px; margin-bottom: 0.5rem; border-radius: 11px; }
  .stat-icon svg { width: 21px; height: 21px; }
  /* "Proper Products" wraps to two lines at this width while the other two
     don't. Reserving two lines on all three keeps the sub-labels on a shared
     baseline instead of one sitting lower than its neighbours. */
  .stat b { font-size: 1.08rem; line-height: 1.12; min-height: 2.24em; }
  .stat span { font-size: 0.6rem; letter-spacing: 0.04em; margin-top: 0.2rem; }
  .logo-lockup { width: 168px; }
  :root { --header-h: 92px; }


  .grid--3, .grid--4, .steps { grid-template-columns: 1fr; }
  .field-row { grid-template-columns: 1fr; }
  /* 2x2 of square tiles on phones. Single-column ran the four photos down most
     of a screen; square crops give a tidy block you take in at a glance.
     grid-auto-rows goes to auto so the tiles' own aspect-ratio sets the height
     rather than a fixed row size fighting it. */
  .gallery {
    grid-template-columns: repeat(2, 1fr);
    grid-auto-rows: auto;
    gap: 0.7rem;
  }
  .gallery img,
  .gallery .ph {
    aspect-ratio: 1 / 1;
    height: auto;
  }

  .hero-actions .btn,
  .cta-actions .btn { width: 100%; }
  .footer-grid { grid-template-columns: 1fr; }
  .addon { flex-direction: column; align-items: flex-start; gap: 0.35rem; }
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
  .reveal { opacity: 1; transform: none; }
}
