/* ============================================================
   DUCKIT — section skeletons.
   One skeleton per section, never reused across a page.
   ============================================================ */

/* ============================================================ 1 · HOME hero
   full-bleed plate, type anchored low */

.hero {
  position: relative;
  min-height: calc(100svh - var(--header-h));
  display: grid;
  align-items: end;
  isolation: isolate;
}

.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; object-position: 50% 45%; }

/* scrim: dark at the type end, transparent over the car */
.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  background:
    linear-gradient(180deg, rgba(10,10,11,0.18) 0%, transparent 30%, rgba(10,10,11,0.78) 84%, var(--ink) 100%),
    linear-gradient(96deg, rgba(10,10,11,0.42) 0%, rgba(10,10,11,0.12) 46%, transparent 70%);
}

.hero__in {
  align-self: end;
  /* tuned so the headline and lede clear 100vh at 1366x768 */
  padding-block: clamp(24px, 4.4vw, 50px) clamp(40px, 6vw, 76px);
  max-width: var(--maxw);
}

.hero__h {
  margin-top: 16px;
  font-size: var(--t-hero);
  letter-spacing: -0.04em;
}
.hero__h span { color: var(--torch); }

.hero__p {
  margin-top: 20px;
  max-width: 34ch;
  font-size: var(--t-md);
  color: rgba(255, 255, 255, 0.86);
}

@media (max-width: 700px) {
  /* keep the copy out from under the floating WhatsApp button, which sits
     bottom-right over exactly this block at scroll 0 */
  .hero__in { padding-bottom: calc(clamp(40px, 6vw, 76px) + 24px); }
  .hero__p { font-size: var(--t-body); }
}

/* ============================================================ 2 · capability grid
   compact 3x2 photo tiles, name + icon overlaid — all six in one screen */

.caps { padding-block: clamp(48px, 5.5vw, 84px); }

.caps__head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: 10px 24px;
  margin-bottom: clamp(20px, 2.6vw, 34px);
}
.caps__h { font-size: var(--t-lg); margin-top: 12px; }
.caps__all {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--display); font-weight: 700; font-size: var(--t-sm);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--torch);
  white-space: nowrap;
}
.caps__all svg { width: 17px; height: 17px; transition: transform 0.25s var(--ease); }
.caps__all:hover svg { transform: translateX(5px); }

/* Four across so seven cards land 4 + 3 rather than 3 + 3 + 1, which leaves a
   single card alone on its own row. */
.caps__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 12px;
}

/* The card carries the ratio rather than a fixed row height. At the old
   ~424x174 the tiles were a letterbox slot onto 4:3 and portrait photos, so
   the cars were cropped to a band; 4:3 shows the shot close to as framed. */
.cap {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  /* Accent rather than a white hairline. Against --ink a 10%-white border sits
     at 1.25:1 and 22% only reaches 1.91:1, both under the 3:1 a boundary needs
     to register; torch clears it at 5.89:1. Hover moves to --torch-hot so the
     state still steps, alongside the photo scale, the scrim and the arrow. */
  border: 1px solid var(--torch);
  transition: border-color 0.25s var(--ease);
}
.cap:hover { border-color: var(--torch-hot); }

.cap__media { position: absolute; inset: 0; }
.cap__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease); }
.cap:hover .cap__media img { transform: scale(1.05); }

/* Scrim keeps the overlaid title AA-legible over any photo. It stays clear far
   further down than it used to: measured against these tiles the title sits at
   ~19:1 where AA asks 4.5:1, so the old scrim was darkening most of the card to
   buy contrast that was never in question. It now holds off until the lower
   third and firms up only in the band the text actually occupies. */
.cap::after {
  content: '';
  position: absolute; inset: 0;
  background: linear-gradient(180deg, transparent 62%, rgba(10,10,11,0.26) 82%, rgba(10,10,11,0.82));
  transition: background 0.25s var(--ease);
}
.cap:hover::after { background: linear-gradient(180deg, transparent 58%, rgba(10,10,11,0.32) 80%, rgba(10,10,11,0.86)); }

.cap__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 13px 14px;
}
.cap__ico { color: var(--torch); flex: none; display: grid; }
.cap__ico svg { width: 20px; height: 20px; }
.cap__h {
  font-size: clamp(0.95rem, 0.88rem + 0.35vw, 1.18rem);
  color: #fff;
  line-height: 1.06;
  letter-spacing: -0.01em;
}
.cap__go { margin-left: auto; flex: none; color: var(--white); opacity: 0; transform: translateX(-4px);
  transition: opacity 0.25s var(--ease), transform 0.25s var(--ease); }
.cap:hover .cap__go { opacity: 1; transform: none; }
.cap__go svg { width: 17px; height: 17px; }

@media (max-width: 1100px) {
  .caps__grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 860px) {
  .caps__grid { grid-template-columns: repeat(2, 1fr); }
}
/* on a phone two columns squeeze "Aero & Bodykit Conversion" onto three lines
   inside a 128px tile — one wide tile per row reads far better */
@media (max-width: 560px) {
  .caps__grid { grid-template-columns: 1fr; gap: 10px; }
  .cap__h { font-size: 1.05rem; }
}

/* ============================================================ 4 · reel (standalone video band) */

.reel { position: relative; }
.reel__media {
  position: relative;
  height: clamp(300px, 46vw, 560px);
  background: var(--ink-3);
  overflow: hidden;
}
.reel__poster, .reel__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 50%;
  display: block;
}
/* the video fades in over the still once it starts playing (desktop only) */
.reel__video { z-index: 1; opacity: 0; transition: opacity 0.6s var(--ease); }
.reel__video.on { opacity: 1; }
/* scrim so the caption stays legible over any frame */
.reel__media::after {
  content: '';
  position: absolute; inset: 0; z-index: 2;
  background: linear-gradient(180deg, transparent 62%, rgba(10, 10, 11, 0.62));
  pointer-events: none;
}
.reel__cap {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 3;
  padding-bottom: clamp(18px, 3vw, 34px);
}
.reel__line {
  margin-top: 8px;
  font-family: var(--display); font-weight: 600;
  font-size: var(--t-md); color: var(--white); letter-spacing: -0.01em;
}

/* sound toggle, top-right of the clip. Hidden until the video is playing. */
.reel__mute {
  position: absolute;
  top: clamp(14px, 2vw, 24px);
  right: clamp(14px, 2vw, 24px);
  z-index: 4;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  background: rgba(10, 10, 11, 0.55);
  border: 1px solid var(--line-strong);
  color: var(--white);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.reel__mute[hidden] { display: none; }
.reel__mute:hover { background: var(--torch); border-color: var(--torch); color: var(--ink); }
.reel__mute svg { width: 20px; height: 20px; }
/* aria-pressed doubles as the state: true = muted */
.reel__mute .reel__mute-off { display: none; }
.reel__mute[aria-pressed='false'] .reel__mute-on { display: none; }
.reel__mute[aria-pressed='false'] .reel__mute-off { display: grid; }
.reel__mute[aria-pressed='false'] { border-color: var(--torch); color: var(--torch); }
.reel__mute[aria-pressed='false']:hover { color: var(--ink); }

/* ============================================================ 5 · signature work (split content) */

.sig__in {
  display: grid;
  grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
  gap: clamp(28px, 5vw, 80px);
  align-items: center;
}
.sig__h { font-size: var(--t-xl); margin: 12px 0 16px; }
.sig__p { color: var(--mute); font-size: var(--t-md); max-width: 46ch; }
.sig__go {
  margin-top: 24px;
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--display); font-weight: 700; font-size: var(--t-sm);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--torch);
}
.sig__go svg { width: 18px; height: 18px; transition: transform 0.25s var(--ease); }
.sig__go:hover svg { transform: translateX(5px); }

/* checklist as a bordered spec panel with the fin notch */
.sig__list {
  display: grid;
  background: var(--ink-3);
  border: 1px solid var(--line-strong);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
}
.sig__list li {
  display: flex; align-items: center; gap: 14px;
  padding: clamp(15px, 2vw, 21px) clamp(20px, 2.5vw, 28px);
  font-size: var(--t-md);
  border-bottom: 1px solid var(--line);
}
.sig__list li:last-child { border-bottom: 0; }
.sig__list svg { width: 19px; height: 19px; color: var(--torch); flex: none; }

@media (max-width: 800px) { .sig__in { grid-template-columns: 1fr; gap: 28px; } }

/* ============================================================ 5 · hard split */

.split { display: grid; grid-template-columns: 1fr 1fr; align-items: stretch; }
.split__text { background: var(--ink-2); display: grid; place-items: center; }
.split__inner {
  position: relative;
  max-width: 480px;
  padding: clamp(48px, 6vw, 92px) var(--pad-x);
}
/* the one burnt-titanium moment — decorative only, no text on top */
.split__heat { display: block; width: 84px; height: 4px; background: var(--ti); margin-bottom: 22px; }
.split__h { font-size: var(--t-xl); margin: 14px 0 16px; }
.split__p { color: var(--mute); margin-bottom: 26px; }
.split__specs { display: grid; gap: 0; margin-bottom: 30px; }
.split__specs > div {
  display: flex; justify-content: space-between; gap: 16px;
  padding: 13px 0; border-bottom: 1px solid var(--line);
}
.split__specs dt { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.1em; text-transform: uppercase; color: var(--mute-dim); }
.split__specs dd { margin: 0; font-size: var(--t-sm); text-align: right; }
.split__media { min-height: 320px; }
.split__media img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 900px) {
  .split { grid-template-columns: 1fr; }
  .split__media { min-height: 260px; order: -1; }
  .split__inner { max-width: none; }
}

/* ============================================================ 6 · horizontal scroller */

.gal { padding-block: var(--sec-y); }
.gal__head {
  display: flex; flex-wrap: wrap; align-items: flex-end; justify-content: space-between;
  gap: 16px; margin-bottom: clamp(24px, 3vw, 40px);
}
.gal__h { font-size: var(--t-xl); margin-top: 12px; }
.gal__hint { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.1em; color: var(--mute-dim); }
/* The belt pauses on hover with a mouse and while a finger is held down on a
   touch screen, so the hint says whichever one the visitor has. */
.gal__hint-touch { display: none; }
@media (hover: none) {
  .gal__hint-hover { display: none; }
  .gal__hint-touch { display: inline; }
}

/* Continuous belt, full-bleed. Two identical sets let it loop seamlessly: the
   belt runs to the end of the first set and jumps back by exactly that width,
   which lands on the same picture.

   It is driven by scrollLeft, not by a transform animation. A transform belt is
   one long composited layer, and on iOS Safari the layer is re-rasterised in
   tiles while it moves - which showed as two marks from different points in the
   loop drawn over each other. Scrolling is the browser's own machinery, tiled
   correctly by definition, and it costs nothing to let a thumb push the strip
   as well. Pauses on hover / focus / touch, in JS. */
.gal__strip {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.gal__strip::-webkit-scrollbar { display: none; }
.gal__track { display: flex; width: max-content; }
.gal__set { display: flex; flex: none; }
.shot {
  position: relative;
  flex: 0 0 clamp(258px, 33vw, 430px);
  margin-right: 16px;
  overflow: hidden;
  padding: 0;
  border: 1px solid var(--line);
}

@media (prefers-reduced-motion: reduce) {
  /* No auto-motion: the strip is still a scroller, but nothing pushes it and
     the scrollbar comes back so it is obvious that it moves. */
  .gal__track { width: auto; padding-left: 0; }
  .gal__strip {
    padding-inline: var(--pad-x);
    scrollbar-width: thin;
    scrollbar-color: var(--line-strong) transparent;
  }
  .gal__strip::-webkit-scrollbar { display: initial; }
  .gal__set:last-child { display: none; }   /* drop the duplicate set */
}
.shot img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform 0.5s var(--ease); }
.shot:hover img { transform: scale(1.05); }
.shot__tag {
  position: absolute; left: 0; bottom: 0;
  padding: 9px 15px;
  background: var(--ink);
  font-family: var(--mono); font-size: var(--t-xs);
  letter-spacing: 0.1em; text-transform: uppercase;
  clip-path: polygon(0 0, 100% 0, calc(100% - 12px) 100%, 0 100%);
}
.shot::after {
  content: '';
  position: absolute; inset: 0;
  box-shadow: inset 0 0 0 2px transparent;
  transition: box-shadow 0.25s var(--ease);
  pointer-events: none;
}
.shot:hover::after { box-shadow: inset 0 0 0 2px var(--torch); }

/* ============================================================ 7 · light partner band */

/* dark band: the supplied partner marks are white-for-dark versions, so they
   only show their true colours (AE Design / EXN red, BMWCoding's M stripe,
   the rest white) on a dark
   surface — a light band would swallow them. Kept distinct from its all-dark
   neighbours by the --ink-2 shade + top/bottom hairline rules. */
.partners { background: var(--ink-2); color: var(--white); border-block: 1px solid var(--line); padding-block: clamp(52px, 6vw, 84px); }
.partners__in {
  display: grid;
  grid-template-columns: minmax(0, 0.82fr) minmax(0, 2.5fr);
  gap: clamp(28px, 4vw, 60px);
  align-items: center;
}
.partners__h { font-size: var(--t-lg); margin-top: 12px; }

/* Hairline-ruled ribbon that never ends: two identical sets inside the track
   let translateX(-50%) loop seamlessly. Deliberately unlike the "Recent work"
   marquee further up — that one is full-bleed, drifts left and is built from
   detached bordered cards. This one stays inside its own column, drifts the
   other way, and reads as a single continuous ruled ribbon whose ends dissolve
   rather than being cut off, which is what says "there is more of this". */
.partners__rail {
  position: relative;
  overflow: hidden;
  background: var(--ink-3);
  border-block: 1px solid var(--line);
}
/* The fade used to be a mask on this box. A mask over a transform-animated
   subtree is the other half of the WebKit compositing problem the belt hit, and
   it is not needed for the effect: two gradients painted on top of the rail
   read the same and never touch the animated layer. --ink-3 spelt out at zero
   alpha rather than `transparent`, which some engines interpolate through
   black and turn into a grey smear. */
.partners__rail::before,
.partners__rail::after {
  content: '';
  position: absolute;
  top: 0;
  bottom: 0;
  width: 8%;
  z-index: 1;
  pointer-events: none;
}
.partners__rail::before { left: 0; background: linear-gradient(90deg, var(--ink-3), rgba(23, 23, 26, 0)); }
.partners__rail::after { right: 0; background: linear-gradient(270deg, var(--ink-3), rgba(23, 23, 26, 0)); }
/* The rail keeps the clipping and the fades; this is what actually scrolls. */
.partners__scroll {
  overflow-x: auto;
  overflow-y: hidden;
  scroll-behavior: auto;
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.partners__scroll::-webkit-scrollbar { display: none; }
.partners__track { display: flex; width: max-content; }
/* Toward WCAG 2.2.2: something that moves on its own for more than five seconds
   should be stoppable, and prefers-reduced-motion is an OS preference rather
   than a control the page offers. The belt stops on hover, on focus and while a
   finger is down - all three in site.js now that it is a scroller rather than a
   CSS animation. */
.partners__set { display: flex; flex: none; }
.pbrand {
  --cell-h: clamp(84px, 8vw, 116px);
  --cell-pad: 18px;
  flex: 0 0 clamp(146px, 15vw, 206px);
  display: grid;
  place-items: center;
  height: var(--cell-h);
  padding: var(--cell-pad) clamp(10px, 1.6vw, 26px);
  border-right: 1px solid var(--line);
}
.pbrand img {
  width: auto;
  /* Per-logo fill factor (set inline via --fill) taken against the cell's own
     inner height, so the marks scale with the ribbon instead of being pinned to
     a pixel height that only ever suited the widest breakpoint. The source
     marks run 1.2:1 to 7.6:1 — one shared height leaves the stacked lockups
     tiny and the wordmarks huge — so each carries its own fraction, tuned so
     they all read at roughly the same optical weight while actually filling the
     cell. The wordmarks end up width-bound; max-width stops them touching the
     rule. Shown in their own brand colours. */
  max-height: calc((var(--cell-h) - var(--cell-pad) * 2) * var(--fill, 0.6));
  max-width: 100%;
  object-fit: contain;
}

@media (prefers-reduced-motion: reduce) {
  /* No auto-motion. The obvious fallback - leave it a rail and turn on
     overflow-x - is a trap: nothing inside a cell can take focus, so the
     scroller never enters the tab order and a keyboard-only visitor cannot
     move it. Three of the eight marks would sit past the right edge with no
     way to reach them, which is worse than the fixed grid this ribbon replaced.
     So drop the motion apparatus entirely and lay the one remaining set out as
     that grid: every mark on screen, nothing to scroll. The edge fade goes with
     it - it was describing travel that no longer happens. */
  .partners__rail { overflow: visible; }
  .partners__rail::before,
  .partners__rail::after { display: none; }
  .partners__scroll { overflow: visible; }
  .partners__track { display: block; width: auto; }
  .partners__set:last-child { display: none; }   /* drop the duplicate set */
  .partners__set {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1px;                       /* 1px of the backing shows through as the rule */
    background: var(--line);
  }
  .pbrand { border-right: 0; background: var(--ink-3); }
}
@media (prefers-reduced-motion: reduce) and (max-width: 700px) {
  .partners__set { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

/* stack the lead above the ribbon before the row gets tight */
@media (max-width: 900px) {
  .partners__in { grid-template-columns: 1fr; gap: clamp(22px, 4vw, 34px); }
}
@media (max-width: 600px) {
  /* Drive the cap off --cell-h rather than height, so the marks shrink with the
     cell instead of overflowing it. The padding comes down too: 18px top and
     bottom is under a third of the desktop cell but nearly half of the phone
     one, which is what left the marks looking stranded in their cells. */
  .pbrand {
    --cell-h: clamp(74px, 22vw, 96px);
    --cell-pad: 12px;
    flex-basis: clamp(132px, 40vw, 168px);
  }
}

/* ============================================================ closing CTA */

.cta {
  position: relative;
  padding-block: clamp(64px, 8vw, 120px);
  background:
    radial-gradient(120% 140% at 50% 0%, rgba(255, 74, 28, 0.13), transparent 62%),
    var(--ink-2);
  border-top: 1px solid var(--line);
  text-align: center;
}
.cta__in { display: flex; flex-direction: column; align-items: center; gap: 16px; }
.cta__h { font-size: var(--t-xl); }
.cta__sub { color: var(--mute); max-width: 46ch; }
.cta__row { display: flex; flex-wrap: wrap; gap: 12px; justify-content: center; margin-top: 12px; }

/* ============================================================ ABOUT · hero (split, type left) */

.ahero {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 0.88fr);
  min-height: var(--band-h);
  align-items: stretch;
  gap: clamp(24px, 4vw, 64px);
  padding-left: var(--pad-x);
  /* Opts out of the breadcrumb reserve in shell.css. This hero leads with the
     photo on a phone, and the trail is meant to sit over it - that is what the
     scrim behind .crumbs is for. Reserving space here would push a dead 76px
     strip above the picture instead. */
  --crumbs-reserve: 0px;
}
.ahero__text {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(40px, 6vw, 80px);
  max-width: 620px;
}
.ahero__h { font-size: clamp(2.1rem, 1.25rem + 3.1vw, 3.85rem); margin: 18px 0 22px; letter-spacing: -0.03em; }
.ahero__p { color: var(--mute); font-size: var(--t-md); max-width: 40ch; }

/* the plate is absolutely positioned so its intrinsic 3:4 ratio can't
   push the first screen past 100vh — the grid row sets the height, not the file */
.ahero__media { position: relative; min-height: 320px; }
.ahero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The two cars sit low in this portrait file - roughly 54%-81% down. The band
     only ever shows about half the photo's height, so anchoring near the top
     (38%) filled the tile with sunset and cut the cars off at the bottom edge.
     72% puts the whole of both cars inside the crop and still keeps sky above. */
  object-position: 50% 72%;
}

@media (max-width: 900px) {
  .ahero {
    grid-template-columns: 1fr;
    /* `minmax(0, 1fr)` was a leftover-space track with a hard 0 minimum, and its
       only child is position:absolute — so the row contributed no intrinsic
       height and could only ever receive `--band-h` minus the text. At 375px the
       text alone is taller than the band, so the row resolved to 0px and the
       photo vanished outright: the preloaded fetchpriority=high LCP image was
       painting into a zero-height box. `auto` lets the row take a real size,
       which aspect-ratio below then supplies. */
    grid-template-rows: auto auto;
    padding-left: 0;
    gap: 0;
  }
  .ahero__text { padding-inline: var(--pad-x); order: 2; padding-block: 28px 36px; max-width: none; }
  /* aspect-ratio is what gives the track something to size to, since the img
     inside is out of flow; --band-h keeps the band from taking over a tablet. */
  .ahero__media { order: 1; min-height: 0; aspect-ratio: 4 / 3; max-height: var(--band-h); }
}

/* ============================================================ ABOUT · pull quote (paper, centred) */

.quote { background: var(--paper); color: var(--on-paper); padding-block: clamp(60px, 7vw, 108px); text-align: center; }
.quote__q {
  margin: 0 auto;
  max-width: 22ch;
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(1.6rem, 0.9rem + 3vw, 3.1rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
}
.quote__by {
  margin-top: 26px;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--on-paper-mute);
}

/* ============================================================ ABOUT · numbered ledger rows */

.pills__head { margin-bottom: clamp(30px, 4vw, 52px); }
.pills__h { font-size: var(--t-xl); margin-top: 14px; }
.pills__list { border-top: 1px solid var(--line); }

.pil {
  display: grid;
  grid-template-columns: 84px minmax(0, 1fr) minmax(0, 1.25fr);
  gap: clamp(16px, 3vw, 44px);
  align-items: baseline;
  padding-block: clamp(24px, 3vw, 38px);
  border-bottom: 1px solid var(--line);
  transition: background 0.25s var(--ease);
}
.pil:hover { background: rgba(255, 255, 255, 0.025); }
/* stagger the indent so the rows read as a ledger, not a table */
.pil:nth-child(even) { padding-left: clamp(0px, 4vw, 64px); }
.pil__no { font-family: var(--mono); font-size: var(--t-sm); color: var(--torch); letter-spacing: 0.1em; }
.pil__h { font-size: var(--t-md); }
.pil__p { color: var(--mute); font-size: var(--t-sm); }

@media (max-width: 760px) {
  .pil { grid-template-columns: 46px minmax(0, 1fr); }
  .pil__p { grid-column: 2; }
  .pil:nth-child(even) { padding-left: 0; }
}

/* ============================================================ ABOUT · uneven mosaic */

.wk { padding-block: var(--sec-y); }
/* don't cap the header width — a 46ch box forced the heading to stack awkwardly;
   constrain the caption instead so the heading flows on one or two lines */
.wk__head { margin-bottom: clamp(24px, 3vw, 40px); }
.wk__h { font-size: var(--t-xl); margin: 12px 0 12px; }
.wk__p { color: var(--mute); max-width: 42ch; }

.wk__grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: clamp(120px, 15vw, 200px);
  gap: 14px;
}
.wk__cell { padding: 0; overflow: hidden; border: 1px solid var(--line); position: relative; }
.wk__cell img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease); }
.wk__cell:hover img { transform: scale(1.06); }
.wk__cell::after {
  content: ''; position: absolute; inset: 0;
  box-shadow: inset 0 0 0 2px transparent;
  transition: box-shadow 0.25s var(--ease); pointer-events: none;
}
.wk__cell:hover::after { box-shadow: inset 0 0 0 2px var(--torch); }

/* Placed explicitly so no tile ends up a wide, short strip. A 2-column tile on a
   single row is a 3.2:1 letterbox, and these are all 4:3 files, so it showed
   about 40% of the photo's height and took the roof off whatever car was in it.
   What forced that shape was mixing 2-column and 1-column tiles in one row band:
   the band's height has to suit both, and it cannot. So the bands don't mix -
   every tile below lands between 1.5:1 and 1.6:1 and keeps ~86% of its photo. */
.wk__cell--1 { grid-column: 1 / span 2; grid-row: 1 / span 2; }
.wk__cell--2 { grid-column: 3;          grid-row: 1; }
.wk__cell--3 { grid-column: 4;          grid-row: 1; }
.wk__cell--4 { grid-column: 3 / span 2; grid-row: 2 / span 2; }
.wk__cell--5 { grid-column: 1;          grid-row: 3; }
.wk__cell--6 { grid-column: 2;          grid-row: 3; }

@media (max-width: 760px) {
  .wk__grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 33vw; }
  /* Drop the desktop placement and let all six flow one per column. A tile
     spanning both columns at this row height is a 2.8:1 strip - the same crop
     the desktop grid above exists to avoid. One column each reads ~1.4:1. */
  .wk__cell { grid-column: auto; grid-row: auto; }
}

/* ============================================================ ABOUT · counter strip */

.ledger { border-top: 1px solid var(--line-strong); background: var(--ink-2); }
.ledger__in { display: grid; grid-template-columns: repeat(3, 1fr); }
.ledger__i { padding: clamp(28px, 4vw, 52px) 0; }
.ledger__i + .ledger__i { border-left: 1px solid var(--line); padding-left: clamp(16px, 3vw, 44px); }
.ledger__i b {
  display: block;
  font-family: var(--display); font-weight: 800;
  font-size: clamp(2rem, 1.1rem + 3.2vw, 4rem);
  line-height: 1; letter-spacing: -0.04em;
  color: var(--torch);
}
.ledger__i span { display: block; margin-top: 10px; color: var(--mute); font-size: var(--t-sm); }
@media (max-width: 660px) {
  .ledger__in { grid-template-columns: 1fr; }
  .ledger__i + .ledger__i { border-left: 0; border-top: 1px solid var(--line); padding-left: 0; }
}

/* ============================================================ SERVICES · hero (centred over crop + index) */

.shero {
  position: relative;
  min-height: var(--band-h);
  display: grid;
  grid-template-rows: 1fr auto;
  align-items: center;
  isolation: isolate;
  text-align: center;
}
.shero__media { position: absolute; inset: 0; z-index: -2; }
.shero__media img { width: 100%; height: 100%; object-fit: cover; }
.shero::before {
  content: '';
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg, rgba(10,10,11,0.30), rgba(10,10,11,0.34) 45%, rgba(10,10,11,0.80));
}
/* this hero carries the six-service index as well as the type, so it needs a
   tighter block than the other banners to stay clear of the fold */
.shero__in {
  padding: clamp(26px, 3.4vw, 44px) var(--pad-x);
  max-width: 760px;
  margin-inline: auto;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.shero__h { font-size: var(--t-hero); letter-spacing: -0.04em; }
.shero__p { color: rgba(255,255,255,0.86); font-size: var(--t-md); max-width: 44ch; }

.shero__idx {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--line-strong);
  background: rgba(10, 10, 11, 0.62);
}
.shero__idx a {
  display: flex; align-items: center; gap: 12px;
  padding: 16px clamp(14px, 2vw, 26px);
  border-right: 1px solid var(--line);
  font-size: var(--t-sm);
  transition: background 0.2s var(--ease);
}
.shero__idx a:hover { background: var(--torch-dim); }
.shero__idx li:nth-child(3n) a { border-right: 0; }
.shero__idx li:nth-child(-n+3) a { border-bottom: 1px solid var(--line); }
.sidx__no { font-family: var(--mono); font-size: var(--t-xs); color: var(--torch); }
.sidx__n { flex: 1; text-align: left; }
.shero__idx svg { width: 16px; height: 16px; color: var(--mute-dim); }

@media (max-width: 820px) {
  .shero__idx { grid-template-columns: repeat(2, 1fr); }
  .shero__idx li:nth-child(3n) a { border-right: 1px solid var(--line); }
  .shero__idx li:nth-child(2n) a { border-right: 0; }
  .shero__idx li:nth-child(-n+4) a { border-bottom: 1px solid var(--line); }
  .sidx__n { font-size: 0.8125rem; }
}
@media (max-width: 480px) {
  .shero__idx a { padding: 13px 16px; }
}

/* ============================================================ SERVICES · overview cards (2x2) */

.svs__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
}
.svc {
  display: flex;
  flex-direction: column;
  background: var(--ink-3);
  border: 1px solid var(--line);
  overflow: hidden;
  scroll-margin-top: calc(var(--header-h) + 24px);
  transition: border-color 0.25s var(--ease), transform 0.25s var(--ease);
}
.svc:hover { border-color: var(--torch); transform: translateY(-3px); }
.svc__media { overflow: hidden; aspect-ratio: 16 / 9; }
.svc__media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.5s var(--ease); }
.svc:hover .svc__media img { transform: scale(1.05); }

.svc__body { display: flex; flex-direction: column; flex: 1; padding: clamp(20px, 2.6vw, 32px); }
.svc__top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.svc__no { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.2em; color: var(--mute-dim); }
.svc__ico { color: var(--torch); display: grid; }
.svc__ico svg { width: 26px; height: 26px; }
.svc__h { font-size: var(--t-lg); margin-bottom: 10px; }
.svc__p { color: var(--mute); font-size: var(--t-sm); margin-bottom: 18px; }
.svc__tags { display: flex; flex-wrap: wrap; gap: 7px; margin-bottom: 22px; }
.svc__tags li {
  font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.04em;
  color: var(--mute); border: 1px solid var(--line); padding: 4px 9px;
}
.svc__go {
  margin-top: auto;
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--display); font-weight: 700; font-size: var(--t-sm);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--torch);
}
.svc__go svg { width: 18px; height: 18px; transition: transform 0.25s var(--ease); }
.svc:hover .svc__go svg { transform: translateX(5px); }

@media (max-width: 760px) { .svs__grid { grid-template-columns: 1fr; } }

/* ============================================================ HOME · FAQ accordion */

.faq { border-top: 1px solid var(--line); }
.faq__in {
  display: grid;
  /* The heading column only ever holds a two-word title and one line of note,
     so at 0.82fr it ran ~180px wider than its own text and the 72px gap landed
     on top of that slack — the list read as detached from the heading rather
     than paired with it. Narrower column, tighter gutter, same sticky heading. */
  grid-template-columns: minmax(0, 0.62fr) minmax(0, 1.85fr);
  gap: clamp(24px, 2.6vw, 48px);
  align-items: start;
}
.faq__head { position: sticky; top: calc(var(--header-h) + 24px); }
.faq__h { font-size: var(--t-xl); margin: 12px 0 18px; }
.faq__note { font-size: var(--t-sm); color: var(--mute); }
.faq__note a { color: var(--torch); display: inline-flex; align-items: center; gap: 6px; }
.faq__note a svg { width: 15px; height: 15px; }

.faq__list { border-top: 1px solid var(--line); }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__q {
  list-style: none;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  padding: clamp(18px, 2.2vw, 26px) 0;
  font-family: var(--display);
  font-weight: 600;
  font-size: clamp(1.05rem, 0.98rem + 0.5vw, 1.35rem);
  letter-spacing: -0.01em;
  color: var(--white);
  transition: color 0.2s var(--ease);
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q:hover { color: var(--torch); }
.faq__mark { flex: none; display: grid; place-items: center; width: 26px; height: 26px; color: var(--torch); }
.faq__mark svg { width: 20px; height: 20px; grid-area: 1 / 1; }
.faq__item[open] .faq__mark svg:first-child { display: none; }   /* plus -> minus when open */
.faq__item:not([open]) .faq__mark svg:last-child { display: none; }
.faq__a { padding: 0 0 clamp(20px, 2.2vw, 26px); }
.faq__a p { color: var(--mute); font-size: var(--t-body); max-width: 62ch; }
/* Several answers are a lead-in line then a list of parts, finishes or exclusions.
   base.css strips list markers globally, so put them back — same disc/torch marker
   convention the product copy uses in detail.css. */
.faq__a ul {
  color: var(--mute); font-size: var(--t-body); max-width: 62ch;
  padding-left: 20px; list-style: disc;
}
.faq__a li + li { margin-top: 6px; }
.faq__a li::marker { color: var(--torch); }
.faq__a p + ul, .faq__a ul + p, .faq__a p + p { margin-top: 12px; }
.faq__item[open] .faq__q { color: var(--torch); }

@media (max-width: 800px) {
  .faq__in { grid-template-columns: 1fr; gap: 24px; }
  .faq__head { position: static; }
}

/* ============================================================ SERVICES · process rule */

.steps { background: var(--ink-2); border-top: 1px solid var(--line); padding-block: clamp(56px, 7vw, 96px); }
.steps__h { font-size: var(--t-lg); margin: 14px 0 clamp(28px, 4vw, 48px); }
.steps__list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(16px, 2.5vw, 34px);
  border-top: 1px solid var(--line-strong);
}
.step { padding-top: 22px; position: relative; }
.step::before {
  content: ''; position: absolute; top: -1px; left: 0; width: 34px; height: 3px; background: var(--torch);
}
.step__no { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.16em; color: var(--mute-dim); }
.step__h { font-size: var(--t-md); margin: 10px 0 8px; }
.step__p { color: var(--mute); font-size: var(--t-sm); }
@media (max-width: 860px) { .steps__list { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 460px) { .steps__list { grid-template-columns: 1fr; } }

/* ============================================================ CONTACT · hero band */

.khero {
  position: relative;
  min-height: var(--band-h);
  display: grid;
  grid-template-rows: minmax(0, 1fr) auto;
  isolation: isolate;
}
/* same treatment as .ahero__media: the 4:3 file must not dictate the fold */
.khero__media { position: relative; overflow: hidden; min-height: 200px; }
.khero__media img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 52%;
}
.khero__media::after {
  content: ''; position: absolute; inset: 0;
  background: linear-gradient(180deg, rgba(10,10,11,0.55) 0%, rgba(10,10,11,0.15) 40%, var(--ink) 100%);
}
.khero__in { padding-block: clamp(24px, 3.5vw, 44px) clamp(32px, 4vw, 56px); }
.khero__h { font-size: clamp(2.1rem, 1.3rem + 3.4vw, 4.25rem); margin: 14px 0 26px; letter-spacing: -0.03em; }
.khero__meta { display: flex; flex-wrap: wrap; gap: 12px 32px; }
.khero__mail, .khero__wa { display: inline-flex; align-items: center; gap: 11px; font-size: var(--t-sm); color: var(--mute); transition: color 0.2s var(--ease); }
.khero__mail:hover, .khero__wa:hover { color: var(--white); }
.khero__mail svg { width: 18px; height: 18px; color: var(--torch); }
.khero__wa svg { width: 18px; height: 18px; color: #25D366; }

/* ============================================================ CONTACT · location cards */

/* a touch tighter than the global section rhythm — this block runs tall */
.locs { padding-block: clamp(52px, 6.5vw, 100px); }
.locs__head { margin-bottom: clamp(24px, 3vw, 40px); }
.locs__h { font-size: var(--t-xl); margin-top: 14px; }

.locs__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--gap);
  align-items: stretch;
}
.loc {
  display: flex; flex-direction: column;
  padding: clamp(20px, 2.2vw, 28px);
  background: var(--ink-3);
  border: 1px solid var(--line);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - var(--cut)) 100%, 0 100%);
  transition: border-color 0.25s var(--ease);
}
.loc:hover { border-color: var(--line-strong); }
/* The HQ card used to span two rows because two branch cards stacked beside
   it. With one partner card left that made it twice its neighbour's height,
   so it sits in a single row like everything else and the grid's own
   align-items: stretch keeps the pair level. */
.loc--hq { background: var(--ink-4); border-color: var(--line-strong); }
.loc__tag {
  font-family: var(--mono); font-size: var(--t-xs);
  letter-spacing: 0.2em; text-transform: uppercase; color: var(--torch); margin-bottom: 16px;
}
.loc__h { font-size: var(--t-md); }
.loc--hq .loc__h { font-size: var(--t-lg); }
.loc__city { color: var(--mute); font-size: var(--t-sm); margin-top: 6px; }
.loc__addr {
  margin: 14px 0;
  font-style: normal;
  font-size: var(--t-sm);
  color: var(--mute);
  line-height: 1.6;
  padding-left: 16px;
  border-left: 2px solid var(--torch);
}
.loc__people { display: grid; gap: 2px; margin-bottom: 16px; }
.loc--hq .loc__people { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 6px; }
.loc__p {
  display: flex; align-items: center; gap: 10px;
  padding: 8px 11px;
  background: rgba(255, 255, 255, 0.035);
  transition: background 0.18s var(--ease);
}
.loc__p:hover { background: rgba(37, 211, 102, 0.14); }
.loc__p svg { width: 17px; height: 17px; color: #25D366; flex: none; }
.loc__p b { font-size: var(--t-sm); font-weight: 600; }
.loc__p span { font-family: var(--mono); font-size: var(--t-xs); color: var(--mute); margin-left: auto; }
.loc__mail {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  font-size: var(--t-sm);
  color: var(--mute);
  transition: color 0.18s var(--ease);
}
.loc__mail:hover { color: var(--white); }
.loc__mail svg { width: 16px; height: 16px; color: var(--torch); flex: none; }

/* every card embeds an interactive map of its address; it grows to fill the
   card so all three bottoms line up, but stays modest so the row isn't tall */
/* explicit height — an <iframe>'s default 150px would otherwise win over min-height */
.loc__map-embed {
  /* Grows into whatever height the taller card sets, so a card with fewer
     contacts fills its column instead of leaving a gap under the map and the
     two bottom edges line up. min-height keeps it usable when nothing stretches
     it - a single card, or the stacked phone layout. */
  flex: 1;
  min-height: 120px;
  margin-bottom: 16px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--ink-2);
}
/* only the tall HQ card lets its map grow to fill; branches stay compact */
.loc__map-embed iframe {
  display: block;
  width: 100%;
  height: 100%;
  border: 0;
  /* dark-map recipe: invert the light Google tiles then spin hue back so water
     and parks keep their colour — matches the carbon UI */
  filter: invert(0.9) hue-rotate(180deg) brightness(0.95) contrast(0.95) saturate(0.85);
}

.loc__map {
  margin-top: auto;
  display: inline-flex; align-items: center; gap: 9px;
  font-family: var(--display); font-weight: 700; font-size: var(--t-sm);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--torch);
}
.loc__map svg { width: 17px; height: 17px; }

@media (max-width: 780px) {
  .locs__grid { grid-template-columns: 1fr; }
}
@media (max-width: 420px) { .loc--hq .loc__people { grid-template-columns: 1fr; } }

/* ============================================================ CONTACT · social band (paper) */

.socs { background: var(--paper); color: var(--on-paper); padding-block: clamp(52px, 6vw, 88px); }
.socs__in { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(28px, 4vw, 64px); align-items: center; }
.socs__h { font-size: var(--t-lg); margin-top: 12px; }
.socs__row { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; }
.soc {
  display: flex; align-items: center; gap: 12px;
  padding: 15px 18px;
  border: 1px solid var(--line-paper);
  font-size: var(--t-sm);
  transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.soc:hover { background: var(--on-paper); color: var(--paper); border-color: var(--on-paper); }
.soc svg { width: 19px; height: 19px; }
@media (max-width: 800px) { .socs__in { grid-template-columns: 1fr; } }
@media (max-width: 420px) { .socs__row { grid-template-columns: 1fr; } }

/* Phone type scale — see the note in shell.css. Original values x 0.9. */
@media (max-width: 767px) {
  .cap__h      { font-size: clamp(0.855rem, 0.792rem + 0.315vw, 1.062rem); }
  .ahero__h    { font-size: clamp(1.89rem, 1.125rem + 2.79vw, 3.465rem); }
  .quote__q    { font-size: clamp(1.44rem, 0.81rem + 2.7vw, 2.79rem); }
  .ledger__i b { font-size: clamp(1.8rem, 0.99rem + 2.88vw, 3.6rem); }
  .faq__q      { font-size: clamp(0.945rem, 0.882rem + 0.45vw, 1.215rem); }
  .khero__h    { font-size: clamp(1.89rem, 1.17rem + 3.06vw, 3.825rem); }
}

/* ============================================================ press
   Neither of these carries a transition of its own — only the arrow svg does —
   so the transform transition is declared here rather than extended. The
   arrow's own translateX on hover is unaffected by the parent moving. */
.caps__all,
.sig__go { transition: transform 90ms var(--ease-in); }

.caps__all:active,
.sig__go:active { transform: translateY(1px); }
