/* ══════════════════════════════════════════════════════════
   MERAKI MOTORWORKS — Design System
   Light edition. Palette derived from the logo: deep navy +
   champagne gold on a warm paper ground.
   Direction: editorial luxury — gallery walls, not workshops.
   ══════════════════════════════════════════════════════════ */

:root {
  /* ── Surfaces ── */
  --paper:      #FAF9F6;   /* page base — warm white, never pure #fff  */
  --paper-2:    #F1EEE8;   /* alternating band                          */
  --paper-3:    #FFFFFF;   /* raised card / input                       */

  /* ── Ink (from the logo navy) ── */
  --navy:       #13243A;   /* headings + primary text — 14.9:1          */
  --navy-body:  #44566E;   /* body copy — 7.1:1                         */
  --navy-faint: #5A6B82;   /* meta / tertiary — 5.2:1                   */

  /* ── Gold, in three tiers ──────────────────────────────────
     The logo gold is only 2.55:1 on paper, so it can never
     carry text on a light ground. It is kept for fills, rules
     and the mark itself; two darkened variants do the reading.  */
  --gold:       #C89457;   /* BRAND — fills, borders, icons. NOT text.  */
  --gold-deep:  #A87237;   /* display-size accent text ≥24px — 3.9:1    */
  --gold-ink:   #8F5F2B;   /* small accent text, links — 5.2:1          */
  --gold-soft:  rgba(200, 148, 87, 0.16);

  /* ── Lines ── */
  --line:       rgba(19, 36, 58, 0.13);
  --line-strong:rgba(19, 36, 58, 0.24);
  --line-gold:  rgba(200, 148, 87, 0.55);

  /* ── Feedback ── */
  --danger:     #B3261E;   /* 6.4:1 on paper                            */
  --success:    #1E6B45;   /* 6.1:1 on paper                            */

  /* ── Type ──
     One family throughout. Jost is a geometric sans in the Futura line —
     its hard circles and sharp angles echo the chevron geometry of the
     logo mark. Headings run heavy and tight; body stays light. */
  --font-display: 'Jost', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Jost', system-ui, -apple-system, 'Segoe UI', sans-serif;

  /* ── Spacing scale (spacious / 4pt base) ── */
  --s-1: 4px;  --s-2: 8px;   --s-3: 16px; --s-4: 24px;
  --s-5: 40px; --s-6: 64px;  --s-7: 96px; --s-8: 144px;

  /* ── Motion tokens (one global rhythm) ── */
  --ease-out: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-in:  cubic-bezier(0.55, 0, 1, 0.45);
  --dur-fast: 180ms;
  --dur-base: 320ms;
  --dur-slow: 620ms;

  /* ── Layout ── */
  --wrap: 1280px;
  --radius: 2px;          /* near-square reads more premium */

  /* ── Elevation (light theme needs real shadows to separate) ── */
  --shadow-sm: 0 1px 2px rgba(19,36,58,0.05), 0 2px 8px rgba(19,36,58,0.04);
  --shadow-md: 0 2px 6px rgba(19,36,58,0.06), 0 12px 32px rgba(19,36,58,0.07);
  --shadow-lg: 0 4px 12px rgba(19,36,58,0.07), 0 24px 60px rgba(19,36,58,0.10);

  /* ── z-index scale ──
     The nav sits ABOVE the mobile menu overlay on purpose: the overlay
     is full-screen, so if it covered the header the close button would
     be hidden and there'd be no visible way out. */
  --z-base: 0; --z-raised: 10; --z-menu: 150; --z-nav: 200; --z-fab: 300;
}

/* ══════════════ RESET ══════════════ */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px;
  -webkit-text-size-adjust: 100%;
}

body {
  background: var(--paper);
  color: var(--navy);
  font-family: var(--font-body);
  font-size: 17px;
  font-weight: 400;
  line-height: 1.7;      /* Jost has a small x-height — needs more air */
  letter-spacing: 0.012em;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
img { height: auto; object-fit: cover; }
button, input, select, textarea { font: inherit; color: inherit; }
button { background: none; border: 0; cursor: pointer; }
a { color: inherit; text-decoration: none; }
ul, ol { list-style: none; padding: 0; }

/* ══════════════ FOCUS & A11Y ══════════════ */
:focus-visible {
  outline: 2px solid var(--gold-ink);
  outline-offset: 3px;
  border-radius: var(--radius);
}
:focus:not(:focus-visible) { outline: none; }

.skip-link {
  position: absolute;
  left: var(--s-3);
  top: -100px;
  z-index: 999;
  padding: var(--s-3) var(--s-4);
  background: var(--navy);
  color: var(--paper);
  font-weight: 500;
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-link:focus { top: var(--s-3); }

/* ══════════════ TYPOGRAPHY ══════════════ */
.h2 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(2.3rem, 5.2vw, 4.2rem);
  line-height: 1.05;
  /* Geometric sans at display size needs negative tracking, or the wide
     round letterforms drift apart and read as a default system font. */
  letter-spacing: -0.03em;
  text-wrap: balance;
  color: var(--navy);
}
/* A condensed .h2 for sections that no longer carry the main brand
   headline (that moved to the hero) but still want more weight than .h3. */
.h2--sm { font-size: clamp(1.8rem, 3.2vw, 2.6rem); }

.h3 {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.55rem, 2.6vw, 2.1rem);
  line-height: 1.15;
  letter-spacing: -0.02em;
  color: var(--navy);
}
/* Display-size only — --gold-deep clears 3:1 for large text, not small. */
.h2 em, .h3 em, .hero__title em {
  font-style: normal;
  color: var(--gold-deep);
}

.eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: var(--s-4);
}
.eyebrow::before {
  content: '';
  display: inline-block;
  width: 28px;
  height: 1px;
  background: var(--gold);
  vertical-align: middle;
  margin-right: var(--s-3);
  margin-bottom: 3px;
}

p { color: var(--navy-body); max-width: 62ch; }

/* Stars run at 11–14px, so they need the small-text gold, not the
   display one — they carry the 5.0 rating and must stay readable. */
.stars { color: var(--gold-ink); letter-spacing: 0.14em; font-size: 0.85em; }

/* ══════════════ LAYOUT ══════════════ */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--s-4);
  position: relative;
  z-index: var(--z-raised);
}
.section { padding-block: clamp(52px, 6vw, 88px); position: relative; }

.section__head { margin-bottom: clamp(28px, 3.5vw, 52px); }
.section__head--center { text-align: center; }
.section__head--center .eyebrow::before { display: none; }
.section__head--row {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--s-5);
  flex-wrap: wrap;
}

/* ══════════════ BUTTONS ══════════════ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  min-height: 52px;
  padding: 0 var(--s-5);
  border-radius: var(--radius);
  font-size: 0.82rem;
  font-weight: 500;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  touch-action: manipulation;
  transition: color var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn--sm { min-height: 44px; padding: 0 var(--s-4); font-size: 0.72rem; }
.btn--block { width: 100%; }
.btn:active { transform: scale(0.985); }

/* Primary: gold fill, navy text (5.8:1), wiping to navy with paper text
   (15.7:1) on hover.

   The wipe is a moving background gradient rather than a ::before overlay.
   An overlay sits ON TOP of the button's text nodes, and only element
   children can be lifted back above it — these buttons contain bare text,
   so the label vanished on hover. Animating the background can't cover
   anything, so it works whatever the markup. */
.btn--gold {
  color: var(--navy);
  box-shadow: var(--shadow-sm);
  background-image: linear-gradient(
    to right,
    var(--navy) 0%, var(--navy) 50%,
    var(--gold) 50%, var(--gold) 100%
  );
  background-size: 200% 100%;
  background-position: 100% 0;   /* start showing the gold half */
  transition: background-position var(--dur-base) var(--ease-out),
              color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out),
              transform var(--dur-fast) var(--ease-out);
}
.btn--gold:hover,
.btn--gold:focus-visible {
  background-position: 0 0;      /* slide the navy half across */
  color: var(--paper);
  box-shadow: var(--shadow-md);
}

.btn--ghost {
  border: 1px solid var(--line-strong);
  color: var(--navy);
}
.btn--ghost:hover { border-color: var(--navy); background: var(--navy); color: var(--paper); }

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  min-height: 44px;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.link-arrow svg { transition: transform var(--dur-base) var(--ease-out); }
.link-arrow:hover svg { transform: translateX(5px); }
.link-arrow--sm { min-height: 32px; font-size: 0.7rem; }

/* ══════════════ NAV ══════════════ */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-nav);
  transition: background var(--dur-base) var(--ease-out),
              backdrop-filter var(--dur-base) var(--ease-out),
              border-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
  border-bottom: 1px solid transparent;
}
.nav.is-stuck {
  background: rgba(250, 249, 246, 0.86);
  backdrop-filter: blur(18px) saturate(140%);
  border-bottom-color: var(--line);
  box-shadow: var(--shadow-sm);
}
.nav__inner {
  max-width: var(--wrap);
  margin-inline: auto;
  padding: var(--s-3) var(--s-4);
  display: flex;
  align-items: center;
  gap: var(--s-5);
}

.wordmark { display: flex; align-items: center; gap: var(--s-3); flex-shrink: 0; }
.wordmark__mark {
  width: 42px; height: 42px;
  flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-out);
}
.wordmark:hover .wordmark__mark { transform: scale(1.06); }
/* Fallback letter, shown only if assets/logo.svg is missing. */
.wordmark__m {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  background: var(--navy);
  color: var(--gold);
  font-family: var(--font-display);
  font-size: 1.35rem;
  font-weight: 700;
  line-height: 1;
  padding-top: 2px;
}
.wordmark__text {
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  line-height: 1.3;
  color: var(--navy);
}
.wordmark__text em {
  display: block;
  font-style: normal;
  font-weight: 400;
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  color: var(--gold-ink);
}

.nav__links { display: flex; gap: var(--s-5); margin-left: auto; }
.nav__links a {
  position: relative;
  padding-block: var(--s-2);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  color: var(--navy-body);
  transition: color var(--dur-base) var(--ease-out);
}
.nav__links a::after {
  content: '';
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1.5px;
  background: var(--gold);
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-base) var(--ease-out);
}
.nav__links a:hover, .nav__links a.is-active { color: var(--navy); }
.nav__links a:hover::after, .nav__links a.is-active::after {
  transform: scaleX(1);
  transform-origin: left;
}

.nav__actions { display: flex; align-items: center; gap: var(--s-4); }
.nav__tel {
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  /* --gold-ink, not raw --gold: small text needs the 5.2:1-contrast token,
     not the 2.55:1 brand gold used for fills/borders (see BRAND.md). */
  color: var(--gold-ink);
  font-variant-numeric: tabular-nums;
  transition: color var(--dur-base) var(--ease-out);
}
.nav__tel:hover { color: var(--navy); }

.nav__toggle {
  display: none;
  width: 44px; height: 44px;
  margin-left: auto;
  flex-direction: column;
  justify-content: center;
  align-items: flex-end;
  gap: 6px;
}
.nav__toggle span {
  display: block;
  height: 1.5px;
  background: var(--navy);
  transition: transform var(--dur-base) var(--ease-out),
              width var(--dur-base) var(--ease-out);
}
.nav__toggle span:nth-child(1) { width: 26px; }
.nav__toggle span:nth-child(2) { width: 18px; }
.nav__toggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(3.75px) rotate(45deg); }
.nav__toggle[aria-expanded="true"] span:nth-child(2) { width: 26px; transform: translateY(-3.75px) rotate(-45deg); }

/* ── Mobile menu ── */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: var(--z-menu);
  background: var(--paper);
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: var(--s-6);
  padding: var(--s-6) var(--s-4) calc(var(--s-6) + env(safe-area-inset-bottom));
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.mobile-menu[hidden] { display: none; }
.mobile-menu.is-open { opacity: 1; }
.mobile-menu nav { display: flex; flex-direction: column; }
.mobile-menu nav a {
  padding: var(--s-3) 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--font-display);
  font-size: 2rem;
  font-weight: 600;
  letter-spacing: -0.03em;
  line-height: 1.4;
  color: var(--navy);
}
.mobile-menu__foot { display: grid; gap: var(--s-3); }

/* ══════════════ HERO ══════════════
   Editorial split: photograph anchored right, paper gradient
   carrying the type on the left so the page reads light. */
/* Mobile-first: photo gets its own band at the top, type sits below it on
   clean paper. Overlaying the two meant either the headline fought the car
   or the scrim hid it entirely. */
.hero {
  position: relative;
  display: grid;
  grid-template-areas: "media" "content" "bar";
  grid-template-rows: auto auto auto;
  /* Same guides as every other section — max-width and side padding — so the
     hero sits in the page rather than bleeding past it. Height comes from the
     content, not the viewport. */
  max-width: var(--wrap);
  margin-inline: auto;
  padding: 100px var(--s-4) 0;
  background: var(--paper);
}
/* Back inside the normal content flow (left column on desktop) — sits
   after the lede, same as the buttons' original position. */
.hero__cta { display: flex; gap: var(--s-3); flex-wrap: wrap; margin-top: var(--s-2); }
/* Sized so the headline, services, lede AND the CTA all clear the fold on
   a 375x812 phone. Any taller and "Request a quote" drops out of view. */
.hero__media {
  grid-area: media;
  position: relative;
  height: 34svh;
  min-height: 220px;
  /* Clips the scroll parallax. The image is translated by a few percent
     of its own height as you scroll — without this it slides past its
     box and hangs over the section below. */
  overflow: hidden;
}
.hero__media img,
.hero__media .img-missing {
  width: 100%; height: 100%;
  object-fit: cover;
  aspect-ratio: auto !important;
}
.hero__scrim {
  position: absolute;
  inset: 0;
  /* Mobile: just soften where the photo meets the type below it. */
  background: linear-gradient(
    to top,
    var(--paper) 0%,
    rgba(250,249,246,0.55) 14%,
    rgba(250,249,246,0) 34%
  );
}
/* ── Desktop: editorial split ──
   The photography is all 4:5 portrait. Stretching that across a wide
   banner would crop the cars to a letterbox strip, so above 900px the
   hero becomes two columns: type left on paper, portrait photo right. */
@media (min-width: 900px) {
  .hero {
    display: grid;
    grid-template-columns: 1fr minmax(0, 44%);
    grid-template-rows: auto auto;
    grid-template-areas: "content media" "bar bar";
    /* Top-aligned rather than centred — that's what raises the photo to
       sit level with the headline instead of floating centred against it. */
    align-items: start;
    column-gap: clamp(32px, 5vw, 72px);
    /* Only needs to clear the 77px fixed nav — the tall stacked-layout
       padding pushed the review rating below the fold. */
    padding: var(--s-7) var(--s-4) 0;
  }
  .hero__media {
    position: relative;
    inset: auto;
    grid-area: media;
    /* Height comes from the photo's own ratio, not a stretched full-height
       box — that's what let the headline sit against the top of the photo
       instead of its middle, and forced the section to viewport height. */
    width: 100%;
    height: auto;
    aspect-ratio: 4 / 5;
    min-height: 0;          /* clear the mobile band height */
  }
  .hero__cta { margin-top: var(--s-5); }
  /* .hero itself now carries the page's standard side padding (it's a
     boxed container like .wrap, not full-bleed), so content/bar no longer
     need to calculate their own inset back to the page centre — that was
     for when the photo ran edge-to-edge and only the text was indented. */
  .hero__content { grid-area: content; padding: 0; align-self: start; }
  .hero__bar { grid-area: bar; }
  /* Feather the photo's left edge into the page. The studio shots are
     shot on white, so this reads as one continuous surface. */
  .hero__scrim {
    background: linear-gradient(to right,
      var(--paper) 0%,
      rgba(250, 249, 246, 0.55) 12%,
      rgba(250, 249, 246, 0) 34%);
  }
}

.hero__content {
  /* Horizontal inset comes from .hero's own padding now — this only
     needs the vertical rhythm. No align-self here: on mobile each row is
     auto-sized to its own content so it has no effect, and setting it here
     unconditionally was overriding the desktop media query's align-self
     (this rule comes later in the file, so it always won the cascade). */
  grid-area: content;
  position: relative;
  z-index: var(--z-raised);
  width: 100%;
  padding: var(--s-5) 0 var(--s-4);
}
/* Sized for the brand-story line ("Meraki — to do something with soul,
   creativity and love."), not the old two-word punchline — that ran at
   up to 7.4rem, which would wrap this much longer phrase into 4+ lines
   and blow well past the mobile fold. */
.hero__title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: clamp(2rem, 4.6vw, 3.8rem);
  line-height: 1.08;
  letter-spacing: -0.025em;
  color: var(--navy);
  margin-bottom: var(--s-4);
}
/* The literal "what we do" list — sits right after the brand headline so
   a visitor knows the business in one glance, before any prose. One box
   that cycles through the four services, rather than four static boxes —
   same transparent/gold-outline treatment as before, just one at a time. */
.hero__services { margin-bottom: var(--s-4); }
.hero__services-box {
  /* inline-grid + every word stacked in the same cell: the box sizes
     itself to the WIDEST word (all of them contribute to that cell's
     intrinsic size) even though only one is visible, so swapping words
     never changes the box's width or causes a layout jump. justify-items
     centers each word within that shared cell — without it, shorter
     words (e.g. "Vehicle Wrapping") sat flush left, leaving visible
     empty space on the right since the box is sized for the longest. */
  display: inline-grid;
  justify-items: center;
  padding: 10px 22px;
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  background: transparent;
}
.hero__services-word {
  grid-area: 1 / 1;
  font-size: 0.98rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  color: var(--navy);
  white-space: nowrap;
  text-align: center;
  opacity: 0;
  transition: opacity 320ms ease;
}
.hero__services-word.is-active { opacity: 1; }
.hero__lede {
  font-size: clamp(1rem, 1.6vw, 1.18rem);
  color: var(--navy-body);
  max-width: 44ch;
  margin-bottom: 0;
}

/* Visually hidden but readable by screen readers — used to give the
   complete, static service list to assistive tech, since the visible
   rotator's text keeps changing and is marked aria-hidden. */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.hero__bar {
  grid-area: bar;
  position: relative;
  z-index: var(--z-raised);
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--s-5);
  flex-wrap: wrap;
  padding: var(--s-3) 0;
  border-top: 1px solid var(--line);
  font-size: 0.78rem;
  color: var(--navy-body);
}
.hero__bar-item { display: inline-flex; align-items: center; gap: var(--s-2); }
.hero__bar-item strong { color: var(--navy); font-weight: 600; }
.hero__bar-item--link {
  margin-left: auto;
  min-height: 44px;
  font-weight: 600;
  color: var(--gold-ink);
}
.hero__bar-item--link:hover { color: var(--navy); }

/* Was a "scroll to continue" hint for the old full-viewport hero. The hero
   is now sized to its content rather than the screen, so the affordance
   no longer applies — kept in markup (harmless) but hidden here. */
.scroll-cue { display: none; }
.scroll-cue span {
  position: absolute;
  inset: 0;
  background: var(--gold);
  animation: cue 2.6s var(--ease-out) infinite;
}
@keyframes cue {
  0%   { transform: translateY(-100%); }
  60%  { transform: translateY(100%); }
  100% { transform: translateY(100%); }
}

/* ══════════════ CRAFT ══════════════ */
.craft__grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(40px, 6vw, var(--s-7));
  align-items: center;
}
.craft__copy p { margin-bottom: var(--s-4); }
.craft__copy .h2 { margin-bottom: var(--s-5); }

.craft__list { margin-top: var(--s-5); display: grid; gap: 0; }
.craft__list li {
  display: grid;
  grid-template-columns: 48px 1fr;
  gap: var(--s-3);
  align-items: baseline;
  padding-block: var(--s-3);
  border-top: 1px solid var(--line);
  color: var(--navy);
  font-size: 0.95rem;
}
.craft__list li:last-child { border-bottom: 1px solid var(--line); }
.craft__list span {
  color: var(--gold-ink);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  font-variant-numeric: tabular-nums;
}

.craft__figure { position: relative; }
.craft__figure img {
  width: 100%;
  aspect-ratio: 4 / 5;
  max-height: 480px;
  object-position: center;
  box-shadow: var(--shadow-lg);
}
.craft__figure figcaption {
  margin-top: var(--s-3);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--navy-faint);
}

/* ══════════════ SERVICES ══════════════ */
/* Three across rather than three stacked full-width rows. The portrait
   photography made each row 730px tall, which put a third of the page
   into this one section. */
.services__list {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
}

.service { display: flex; flex-direction: column; }
.service--flip .service__media { order: 0; }

.service__media {
  overflow: hidden;
  box-shadow: var(--shadow-md);
  margin-bottom: var(--s-4);
}
.service__media img {
  width: 100%;
  /* 4:5 source, shown 1:1 here. A modest centre crop on a 400px card
     keeps the section compact without losing the subject. */
  aspect-ratio: 1 / 1;
  transition: transform 900ms var(--ease-out);
}
.service:hover .service__media img { transform: scale(1.04); }

.service__num {
  font-size: 0.9rem;      /* body font — too small for Bodoni's hairlines */
  font-weight: 600;
  letter-spacing: 0.22em;
  color: var(--gold-ink);
  margin-bottom: var(--s-3);
}
.service__body .h3 { margin-bottom: var(--s-3); }
.service__body > p { margin-bottom: var(--s-4); }

.tags { display: flex; flex-wrap: wrap; gap: var(--s-2); margin-bottom: var(--s-3); }
.tags li {
  padding: 6px var(--s-3);
  border: 1px solid var(--line-strong);
  border-radius: 100px;
  font-size: 0.72rem;
  letter-spacing: 0.06em;
  color: var(--navy-body);
}

/* ══════════════ PROCESS ══════════════ */
.process { background: var(--paper-2); border-block: 1px solid var(--line); }
.process__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 0;
}
.step {
  padding: var(--s-5) var(--s-4) var(--s-5) 0;
  border-top: 1px solid var(--line-strong);
  position: relative;
}
.step + .step { padding-left: var(--s-4); }
.step::before {
  content: '';
  position: absolute;
  top: -1px; left: 0;
  width: 0; height: 2px;
  background: var(--gold);
  transition: width var(--dur-slow) var(--ease-out);
}
.step:hover::before { width: 100%; }
.step__num {
  font-family: var(--font-display);
  font-size: 2.6rem;
  font-weight: 700;
  letter-spacing: -0.03em;
  line-height: 1;
  /* Fading these with opacity dropped them to 2.3:1. The hover
     affordance is the gold rule above instead. */
  color: var(--gold-deep);
  margin-bottom: var(--s-3);
  transition: color var(--dur-base) var(--ease-out);
}
.step:hover .step__num { color: var(--navy); }
.step__title {
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--navy);
  margin-bottom: var(--s-2);
}
/* :not() is load-bearing — a bare `.step p` outranks `.step__num`
   on specificity and silently shrinks the numeral to body size. */
.step p:not(.step__num) { font-size: 0.92rem; }

/* ══════════════ GALLERY ══════════════ */
.gallery {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-3);
}
.gallery__item { overflow: hidden; position: relative; box-shadow: var(--shadow-sm); }
.gallery__item img {
  width: 100%;
  height: 100%;
  aspect-ratio: 1 / 1;
  transition: transform 900ms var(--ease-out);
}
/* Uniform square tiles — compact, and the grid reads as one block
   rather than two tall rows. */
.gallery__item--tall img { aspect-ratio: 1 / 1; }
.gallery__item:hover img { transform: scale(1.05); }

/* ══════════════ REVIEWS ══════════════ */
.reviews { background: var(--paper-2); border-block: 1px solid var(--line); }
.reviews__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s-4);
}
.review {
  padding: var(--s-5);
  background: var(--paper-3);
  border-top: 2px solid var(--gold);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  transition: box-shadow var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.review:hover { box-shadow: var(--shadow-md); transform: translateY(-3px); }
.review p {
  font-family: var(--font-display);
  font-size: clamp(1.3rem, 1.8vw, 1.5rem);
  font-weight: 500;
  line-height: 1.4;
  letter-spacing: -0.015em;
  color: var(--navy);
  flex: 1;
}
.review cite {
  font-style: normal;
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--navy-faint);
}

/* ══════════════ CONTACT ══════════════ */
.contact__grid {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(40px, 6vw, var(--s-7));
  align-items: start;
}
.contact__aside .h2 { margin-bottom: var(--s-4); }

.contact__details { margin-top: var(--s-6); display: grid; gap: 0; }
.contact__details > div {
  display: grid;
  grid-template-columns: 110px 1fr;
  gap: var(--s-3);
  padding-block: var(--s-4);
  border-top: 1px solid var(--line);
}
.contact__details > div:last-child { border-bottom: 1px solid var(--line); }
.contact__details dt {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--navy-faint);
  padding-top: 3px;
}
.contact__details dd { margin: 0; font-size: 0.95rem; color: var(--navy-body); }
.contact__details dd a {
  color: var(--navy);
  font-weight: 500;
  border-bottom: 1px solid var(--line-gold);
  padding-bottom: 1px;
  transition: color var(--dur-base) var(--ease-out);
}
.contact__details dd a:hover { color: var(--gold-ink); }
.contact__details .link-arrow { border: 0; }

/* ── Form ── */
.form {
  padding: clamp(28px, 4vw, var(--s-6));
  background: var(--paper-3);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-lg);
  display: grid;
  gap: var(--s-4);
}
.form__row { display: grid; grid-template-columns: 1fr 1fr; gap: var(--s-4); }

/* align-content defaults to "normal", which computes to "stretch" for a
   grid container — so when .form__row forces two side-by-side .field
   divs to equal height (e.g. Vehicle's extra hint line makes it taller
   than Service), the shorter field's OWN rows stretched to fill that
   extra space, pushing its label and input down out of line with its
   sibling. Pinning content to the top keeps every field's input sitting
   at the same height as its neighbour regardless of which one is taller. */
.field { display: grid; align-content: start; gap: var(--s-2); }
.field label {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--navy);
}
.field label span { color: var(--gold-ink); }

.field input, .field select, .field textarea {
  width: 100%;
  min-height: 52px;
  padding: var(--s-3);
  background: var(--paper);
  border: 1px solid var(--line-strong);
  border-radius: var(--radius);
  color: var(--navy);
  font-size: 16px;           /* 16px prevents iOS zoom-on-focus */
  font-weight: 400;
  transition: border-color var(--dur-base) var(--ease-out),
              background var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.field textarea { min-height: 120px; resize: vertical; line-height: 1.6; }
.field select {
  appearance: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' fill='none' stroke='%2344566E' stroke-width='1.6'%3E%3Cpath d='m1 1 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right var(--s-3) center;
  padding-right: var(--s-5);
  cursor: pointer;
}
.field input::placeholder, .field textarea::placeholder { color: var(--navy-faint); }
.field input:hover, .field select:hover, .field textarea:hover { border-color: var(--navy-faint); }
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--gold);
  background: var(--paper-3);
  box-shadow: 0 0 0 3px var(--gold-soft);
  outline: none;
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--gold-ink);
  outline-offset: 2px;
}

.field__hint { font-size: 0.78rem; color: var(--navy-faint); }
.field__error {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--danger);
}
.field__error::before { content: '!'; font-weight: 700; }
/* display:flex above beats the [hidden] UA rule on specificity — restore it,
   or every field shows a stray "!" before the user has done anything. */
.field__error[hidden] { display: none; }
.field.has-error input,
.field.has-error select { border-color: var(--danger); }

.btn__spinner {
  width: 15px; height: 15px;
  border: 2px solid rgba(19,36,58,0.25);
  border-top-color: var(--navy);
  border-radius: 50%;
  display: none;
  animation: spin 0.7s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.btn.is-loading { pointer-events: none; opacity: 0.75; }
.btn.is-loading .btn__spinner { display: block; }

.form__status { font-size: 0.9rem; font-weight: 500; min-height: 1.4em; }
.form__status.is-success { color: var(--success); }
.form__status.is-error { color: var(--danger); }

.form__alt { font-size: 0.85rem; color: var(--navy-faint); }
.form__alt a { color: var(--gold-ink); font-weight: 600; }

/* ══════════════ FOOTER ══════════════ */
.footer { border-top: 1px solid var(--line); padding-top: var(--s-6); background: var(--paper-2); }
.footer__inner {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: var(--s-5);
  padding-bottom: var(--s-6);
}
.footer__brand p { font-size: 0.88rem; margin-top: var(--s-3); }
.footer__nav, .footer__contact { display: flex; flex-direction: column; gap: var(--s-2); }
.footer__nav a, .footer__contact a {
  font-size: 0.88rem;
  color: var(--navy-body);
  min-height: 30px;
  display: inline-flex;
  align-items: center;
  transition: color var(--dur-base) var(--ease-out);
}
.footer__nav a:hover, .footer__contact a:hover { color: var(--gold-ink); }
.footer__contact address {
  font-style: normal;
  font-size: 0.85rem;
  color: var(--navy-faint);
  margin-top: var(--s-2);
  line-height: 1.6;
}

.footer__base {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: var(--s-3);
  flex-wrap: wrap;
  padding-block: var(--s-4) calc(var(--s-4) + env(safe-area-inset-bottom));
  border-top: 1px solid var(--line);
  font-size: 0.78rem;
  color: var(--navy-faint);
}
.footer__rating { display: inline-flex; align-items: center; gap: var(--s-2); }

/* ══════════════ FLOATING CALL (mobile) ══════════════ */
.fab {
  display: none;
  position: fixed;
  right: var(--s-4);
  bottom: calc(var(--s-4) + env(safe-area-inset-bottom));
  z-index: var(--z-fab);
  width: 56px; height: 56px;
  place-items: center;
  background: var(--navy);
  color: var(--gold);
  border-radius: 50%;
  box-shadow: var(--shadow-lg);
  transition: transform var(--dur-fast) var(--ease-out);
}
.fab:active { transform: scale(0.94); }
/* The open menu already offers a Call button — two would compete. */
body.nav-open .fab { display: none; }

/* ══════════════ IMAGE PLACEHOLDER FALLBACK ══════════════
   Until real photography is dropped into /assets, any missing
   image renders as an intentional slot marker rather than a
   broken-image icon. Delete this block once assets are in. */
.img-missing {
  position: relative;
  display: grid;
  place-items: center;
  min-height: 220px;
  background:
    repeating-linear-gradient(45deg,
      #EDE9E2 0px, #EDE9E2 12px,
      #E7E2DA 12px, #E7E2DA 24px);
  border: 1px solid var(--line);
}
.img-missing::after {
  content: attr(data-slot);
  position: absolute;
  padding: var(--s-2) var(--s-3);
  background: var(--paper);
  border: 1px solid var(--line);
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--navy-faint);
  text-align: center;
}

/* ══════════════ REVEAL (JS adds inline styles) ══════════════ */
[data-reveal], [data-reveal-stagger] > * {
  opacity: 0;
  transform: translateY(26px);
}
.no-js [data-reveal], .no-js [data-reveal-stagger] > * {
  opacity: 1;
  transform: none;
}

/* ══════════════ RESPONSIVE ══════════════ */
@media (max-width: 1024px) {
  .nav__links, .nav__actions { display: none; }
  .nav__toggle { display: flex; }
  .craft__grid, .contact__grid { grid-template-columns: 1fr; }
  .craft__figure { max-width: 480px; }
  .process__grid { grid-template-columns: repeat(2, 1fr); }
  .step, .step + .step { padding-left: 0; padding-right: var(--s-4); }
  .footer__inner { grid-template-columns: 1fr 1fr; }
  .fab { display: grid; }
}

@media (max-width: 768px) {
  html { scroll-padding-top: 76px; }
  body { font-size: 16px; }

  /* Everything stacks on a phone, so the page gets long fast — tighten
     the vertical rhythm rather than cutting content. */
  .section { padding-block: 44px; }
  .section__head { margin-bottom: 28px; }
  .craft__list li { padding-block: 10px; }
  .contact__details > div { padding-block: 14px; }
  .service__media { margin-bottom: var(--s-3); }
  .service__media img { aspect-ratio: 16 / 11; }
  .craft__grid { gap: 32px; }
  .footer { padding-top: 44px; }
  .footer__inner { padding-bottom: 32px; }
  .services__list { grid-template-columns: 1fr; gap: var(--s-5); }
  .reviews__grid { grid-template-columns: 1fr; }
  .gallery { grid-template-columns: repeat(2, 1fr); }
  .gallery__item--tall { grid-row: span 1; }
  .gallery__item--tall img { aspect-ratio: 4 / 3; }
  .form__row { grid-template-columns: 1fr; }
  .hero__bar-item--hide-sm { display: none; }
  .hero__bar-item--link { margin-left: 0; }
  .scroll-cue { display: none; }
  /* The brand-story headline runs to 4 lines at mobile width. Reclaim the
     room from a smaller size and tighter margins so "Request a quote"
     still clears the fold, rather than shrinking the photo further. */
  .hero__title { font-size: 1.7rem; margin-bottom: var(--s-3); }
  .hero__services { margin-bottom: var(--s-3); }
  .hero__lede { margin-bottom: var(--s-4); }
  .hero__media { height: 30svh; }
  .footer__inner { grid-template-columns: 1fr; gap: var(--s-5); }
  .footer__base { justify-content: flex-start; }
}

@media (max-width: 480px) {
  .process__grid { grid-template-columns: 1fr; }
  .contact__details > div { grid-template-columns: 1fr; gap: var(--s-1); }
  .btn { width: 100%; }
  .hero__cta { flex-direction: column; align-items: stretch; }
  .mobile-menu nav a { font-size: 1.6rem; }
}

/* ══════════════ REDUCED MOTION ══════════════ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  [data-reveal], [data-reveal-stagger] > * { opacity: 1; transform: none; }
  .scroll-cue { display: none; }
}

/* ══════════════ PRINT ══════════════ */
@media print {
  .nav, .fab, .mobile-menu, .scroll-cue, .hero__media { display: none; }
  body { background: #fff; color: #000; }
  [data-reveal], [data-reveal-stagger] > * { opacity: 1; transform: none; }
}
