/* D'Car Guys — page styles shared by index.html and zh.html.
   Loaded from each page's <helmet>, after the design-system stylesheet, so
   equal-specificity rules here win. zh.html overrides only the font stacks
   and the CJK type metrics in its own inline <style>. */

/* Archivo, self-hosted: the latin subset of the variable font (wght 400-800
   in one file), preloaded from each page's <head>. swap keeps text visible
   while it loads; the page makes no third-party font request. */
@font-face{font-family:"Archivo";src:url(/assets/fonts/archivo-latin-var.woff2) format("woff2");font-weight:400 800;font-style:normal;font-display:swap;
  unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

/* ── Tokens ─────────────────────────────────────────────────────────────── */
:root{
  --ease-out:cubic-bezier(0.23, 1, 0.32, 1);
  /* one container: content max 1312px, left edge 64px at 1440 */
  --gutter:clamp(16px,5vw,64px);
  --content-max:1312px;

  /* Spacing scale, 4px base. Every margin, padding and gap below uses a step
     or one of the roles built from them. */
  --s-1:4px; --s-2:8px; --s-3:12px; --s-4:16px; --s-5:20px;
  --s-6:24px; --s-8:32px; --s-10:40px; --s-12:48px; --s-16:64px;

  /* Spacing roles. Rhythm: tight inside a group (4-16), generous between
     groups (24-48), and two section paddings: lead sections (Services,
     Gallery, Close) keep the full beat, support sections (Process, Coverage,
     Location) a shorter one, so the page has priority rather than one beat. */
  --space-section-lead:clamp(64px,10vw,132px);
  --space-section-support:clamp(48px,6vw,88px);
  --section-y:var(--space-section-lead);          /* legacy alias (404.html) */
  --space-head-gap:clamp(32px,4vw,56px);          /* section H2 (+ lede) -> content */
  --space-title-lede:var(--s-4);                   /* heading -> its one-line lede */
  --space-group:clamp(24px,3vw,48px);             /* between groups in a section */
  --space-row:clamp(24px,2.5vw,32px);             /* list-row padding (services) */
  --space-col:clamp(24px,4vw,56px);               /* text columns */
  --space-col-wide:clamp(40px,5vw,72px);          /* a major two-part split */
  --space-tile:clamp(16px,2.4vw,32px);            /* gutter between photo tiles */
  /* the tallest a gallery photo may be: the viewport under the nav, less its
     caption (~64px) and ~96px of air, so a photo and its caption always fit
     on screen together; this also narrows the jump at the 1200px switch */
  --gal-tile-max-h:max(260px, calc(100svh - var(--navh,70px) - 160px)); /* floor: short landscape screens left ~130px tiles */

  --text-muted:color-mix(in srgb, var(--color-text) 78%, transparent);
  --text-subtle:color-mix(in srgb, var(--color-text) 70%, transparent);
  /* brand ink: accent-700 in the signature tone, near-black in mono; set on
     .page from the component (accentInk) */
  --accent-ink:var(--color-accent-700);
}

/* ── Base ───────────────────────────────────────────────────────────────── */
body{margin:0;text-wrap:pretty}
html{scroll-behavior:smooth;scroll-padding-top:var(--navh,70px)}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
a{color:var(--color-text);text-decoration:none}
a:hover{color:var(--color-accent-700)}
:focus-visible{outline-color:var(--color-accent-700)}
::selection{background:color-mix(in srgb, var(--color-accent-700) 22%, transparent)}
h1,h2,h3,h4{text-wrap:balance}
main:focus{outline:none}
@keyframes riseIn{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@keyframes cueDrift{0%,100%{transform:translateY(-4px)}50%{transform:translateY(6px)}}
@keyframes fadeIn{from{opacity:0}to{opacity:1}}

.page{background:var(--color-bg);color:var(--color-text);font-family:var(--font-body);min-height:100vh}
.wrap{width:100%;max-width:calc(var(--content-max) + 2 * 64px);margin-inline:auto;padding-inline:var(--gutter)}
.section{padding-block:var(--space-section-lead)}
.section--support{padding-block:var(--space-section-support)}
.rule{display:block;height:2px;border:0;margin:0;background:var(--color-divider)}

/* Skip link: the first focusable element, off screen until focused */
.skip-link{position:absolute;top:0;left:var(--gutter);z-index:100;transform:translateY(-120%)}
.skip-link:focus{transform:translateY(var(--s-2))}

/* ── Type scale (7 roles) ───────────────────────────────────────────────
   Sizes in rem (1rem = 16px at the browser default), so a reader's own
   font-size setting scales the whole scale. Display tracking loosens where a
   heading drops to ~48px and below (see the media queries after the hero),
   so word spaces never close up on phones. */
.t-label{font-size:0.75rem;line-height:1.5;font-weight:600;letter-spacing:0.08em;text-transform:uppercase}
.t-small{font-size:0.875rem;line-height:1.6}
.t-body{font-size:1rem;line-height:1.7}
.t-lead{font-size:clamp(1.0625rem,1.6vw,1.25rem);line-height:1.55}
.t-h3{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:clamp(1.25rem,1.7vw,1.5rem);line-height:1.2;letter-spacing:-0.01em}
.t-h2{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:clamp(2.125rem,6.2vw,4.75rem);line-height:0.98;letter-spacing:-0.035em}
/* support sections step the H2 down, so the lead sections read first */
.section--support .t-h2{font-size:clamp(1.75rem,4.4vw,3.5rem)}
/* step number: one style for Services and Process */
.t-num{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:0.875rem;line-height:1.5;letter-spacing:0.04em;font-feature-settings:'tnum' 1;color:var(--accent-ink)}
.muted{color:var(--text-muted)}
.subtle{color:var(--text-subtle)}
/* reading measure: Archivo's "0" is wide (1ch ~ 0.57em against an average
   letter of ~0.44em), so 60ch set 74-82 characters a line. The service copy
   runs at 52ch; the short section ledes at 56ch, since pretty wrapping and
   their unbreakable "(3-year warranty)" runs already pull lines in. Both set
   ~65-72 characters of English at desktop widths. Chinese keeps the wider
   measures (~34 Han a line for body, ~28 for the hero sub). */
.measure{max-width:56ch}
:lang(zh) .measure,:lang(zh) .svc-copy{max-width:60ch}
:lang(zh) .hero-sub{max-width:52ch}
.nowrap{white-space:nowrap}
.sr-only{position:absolute;width:1px;height:1px;margin:-1px;padding:0;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.section-title{margin:0 0 var(--space-head-gap)}
/* a heading with a one-line lede under it: the pair is one group */
.section-head{margin-bottom:var(--space-head-gap)}
.section-head .section-title{margin-bottom:var(--space-title-lede)}
p,h1,h2,h3,h4{margin:0}

/* ── Buttons: two sizes (md 44 / lg 52), every variant a 2px border box ── */
.btn{min-height:44px;padding:0 var(--s-4);border:2px solid transparent;font-size:1rem;line-height:1.2;gap:var(--s-2);white-space:nowrap;
  transition:background-color 150ms ease,border-color 150ms ease,color 150ms ease,transform 160ms var(--ease-out)}
.btn-lg{min-height:52px;padding:0 var(--s-6);font-size:1.0625rem;gap:var(--s-2)}
.btn svg{flex:none}
.btn:active{transform:scale(0.97)}
/* Every state names its text colour: the page's a:hover and the design
   system's .nav a / .nav a:hover would otherwise repaint the label. Light
   text on the brand red only reaches 4.5:1 on accent-700 and darker. */
a.btn-primary,.nav a.btn-primary,button.btn-primary{background:var(--color-accent-700);border-color:var(--color-accent-700);color:var(--color-bg)}
a.btn-primary:hover,.nav a.btn-primary:hover,button.btn-primary:hover{background:var(--color-accent-800);border-color:var(--color-accent-800);color:var(--color-bg)}
a.btn-primary:active,.nav a.btn-primary:active,button.btn-primary:active{background:var(--color-accent-900);border-color:var(--color-accent-900);color:var(--color-bg)}
a.btn-primary:focus-visible,.nav a.btn-primary:focus-visible{color:var(--color-bg);outline:2px solid var(--color-accent-700);outline-offset:3px}
/* the one outline style: 2px in the text colour of its surface */
.btn-outline,a.btn-outline,.nav a.btn-outline,a.btn-outline:hover,.nav a.btn-outline:hover,a.btn-outline:active,.nav a.btn-outline:active{background:transparent;border-color:currentColor;color:var(--color-text)}
.btn-outline:hover,a.btn-outline:hover,.nav a.btn-outline:hover{background:color-mix(in srgb, var(--color-text) 8%, transparent)}
.btn-outline:active,a.btn-outline:active,.nav a.btn-outline:active{background:color-mix(in srgb, var(--color-text) 14%, transparent)}

/* ── Nav ───────────────────────────────────────────────────────────────── */
.site-nav{position:sticky;top:0;z-index:50;display:block;padding:0;gap:0;background:var(--color-bg);border-bottom:2px solid var(--color-divider)}
.nav-inner{display:flex;align-items:center;justify-content:space-between;flex-wrap:nowrap;gap:clamp(8px,2vw,24px);padding-block:var(--s-3)}
.nav-brand{flex:0 0 auto;margin:0;font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:1.25rem;line-height:1.2;letter-spacing:-0.01em;white-space:nowrap}
/* each link carries 8px of padding either side, so its hit box is 44px tall
   (and 44px wide for the two-character zh 作品) while the visible gap between
   labels stays 20-28px */
.nav-links{display:flex;align-items:center;flex-wrap:nowrap;gap:clamp(4px,1vw,12px);min-width:0}
.nav .nav-link{flex:0 0 auto;display:inline-flex;align-items:center;justify-content:center;min-height:44px;min-width:44px;padding-inline:var(--s-2);font-size:0.875rem;line-height:1.6;white-space:nowrap}
/* the design system's .nav a sets 14px; keep the type scale inside the nav */
.nav a.btn{font-size:1rem}
.nav a.btn-lg{font-size:1.0625rem}
.nav a.t-lead{font-size:clamp(1.0625rem,1.6vw,1.25rem)}
.nav-actions{display:flex;align-items:center;gap:clamp(4px,1vw,8px);flex:0 0 auto}
.nav .lang-link{display:inline-flex;align-items:center;justify-content:center;min-width:44px;min-height:44px;font-size:0.875rem;line-height:1.6;color:var(--color-text);white-space:nowrap}
.nav .lang-link:hover{color:var(--color-accent-700)}
.nav-toggle{align-items:center;justify-content:center;width:44px;height:44px;padding:0;background:transparent;border:2px solid currentColor;color:var(--color-text);cursor:pointer;-webkit-tap-highlight-color:transparent}
.nav-toggle svg{overflow:visible}
.nav-toggle path{transform-box:fill-box;transform-origin:center;transition:transform 220ms var(--ease-out),opacity 150ms ease}
.nav-toggle[aria-expanded="true"] .bar-top{transform:translateY(6px) rotate(45deg)}
.nav-toggle[aria-expanded="true"] .bar-mid{opacity:0}
.nav-toggle[aria-expanded="true"] .bar-bot{transform:translateY(-6px) rotate(-45deg)}
@media (prefers-reduced-motion:reduce){.nav-toggle path{transition:none}}

/* Under 768px (the same line as the WhatsApp bar) the links fold into the
   menu (see _applyLayout, which also folds them early if they would ever
   collide) and the nav WhatsApp button drops to its icon, label kept for
   screen readers. While the sticky bar (or the open menu) carries WhatsApp,
   the nav icon leaves the layout. It is ordered first in the group, so the
   language link and the menu button stay pinned right and never move. */
@media (max-width:767px){
  .nav-cta{position:relative;order:-1;width:44px;padding:0}
  .nav-cta-label{position:absolute;width:1px;height:1px;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
  .wa-bar-on .nav-cta,.menu-open .nav-cta{display:none}
}

/* Mobile menu panel */
.nav-panel{position:absolute;left:0;right:0;top:100%;z-index:60;display:flex;flex-direction:column;padding:var(--s-2) var(--gutter) var(--s-4);background:var(--color-bg);border-bottom:2px solid var(--color-divider);
  opacity:0;transform:translateY(-8px);visibility:hidden;pointer-events:none;
  transition:opacity 150ms var(--ease-out),transform 150ms var(--ease-out),visibility 0s linear 150ms}
.nav-panel.is-open{opacity:1;transform:none;visibility:visible;pointer-events:auto;
  transition:opacity 200ms var(--ease-out),transform 200ms var(--ease-out),visibility 0s}
@media (prefers-reduced-motion:reduce){.nav-panel,.nav-panel.is-open{transform:none}}
/* scrim over the page below the nav while the menu is open; a tap on it
   closes the menu (the outside-tap handler in wireMenu) */
.nav-scrim{position:fixed;left:0;right:0;top:var(--navh,70px);bottom:0;z-index:55;background:color-mix(in srgb, var(--color-text) 36%, transparent);
  opacity:0;visibility:hidden;transition:opacity 150ms var(--ease-out),visibility 0s linear 150ms}
.menu-open .nav-scrim{opacity:1;visibility:visible;transition:opacity 200ms var(--ease-out),visibility 0s}
.nav .nav-panel-link{display:flex;align-items:center;min-height:48px;border-top:2px solid var(--color-divider)}
.nav-panel-cta{margin-top:var(--s-3);width:100%}

/* ── Hero: a pinned turntable. One column at every width: the copy, the
   car, and the finish swatches centred directly under it. Rows are sized to
   their content (the car's row may shrink, never grow past the car) and the
   stack is centred in the pin, so spare height sits outside the group rather
   than as bands around the car. The bottom padding keeps the scroll cue
   clear of the swatches. ───────────────────────────────────────────────── */
.hero{position:relative;height:170vh}
.hero-pin{position:sticky;top:var(--navh,70px);height:calc(100dvh - var(--navh,70px));overflow:hidden;display:grid;
  grid-template-columns:minmax(0,1fr);grid-template-rows:auto minmax(0,auto) auto;grid-template-areas:"copy" "car" "swatch";
  align-content:center;row-gap:clamp(8px,2vh,20px);
  /* the copy keeps a floor of air under the nav */
  padding:clamp(32px,4vh,56px) max(var(--gutter), calc((100% - var(--content-max)) / 2)) clamp(44px,7vh,60px)}
/* short landscape screens: the car's row is the first thing squeezed, so
   the floor drops back to 16px there */
@media (max-height:560px) and (orientation:landscape){.hero-pin{padding-top:var(--s-4)}}
.hero-copy{grid-area:copy;min-width:0;max-width:680px}
.hero-title{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:clamp(2.25rem,min(7.2vw,11vh),6.5rem);line-height:0.96;letter-spacing:-0.04em;margin:0;animation:riseIn .7s var(--ease-out) .08s both}
.hero-sub{max-width:46ch;margin:clamp(12px,2vh,24px) 0 0;animation:riseIn .7s var(--ease-out) .16s both}
.hero-cta{margin-top:clamp(12px,2.4vh,24px);animation:riseIn .7s var(--ease-out) .24s both}
.hero-car{grid-area:car;position:relative;min-height:0;display:flex;align-items:center;justify-content:center}
/* Frames are 840x290; capped so the car is never upscaled past ~1.1x at DPR1
   until higher-resolution renders arrive. */
/* The box is the frame's shape (all 15 frames are 840x290) and the image
   fills it absolutely, so the row's height never depends on which frame is
   loaded or decoding: nothing below the car moves as the turntable turns.
   On a short screen max-height caps the box and contain scales the car. */
.hero-car-stack{position:relative;width:100%;max-width:920px;max-height:100%;aspect-ratio:840/290}
.hero-car-stack img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;display:block}
.hero-cue{position:absolute;left:50%;bottom:clamp(8px,2vh,20px);transform:translateX(-50%);display:flex;flex-direction:column;align-items:center;color:var(--color-text);opacity:.9;transition:opacity .5s ease;pointer-events:none}
/* set from _applyLayout when the car row is too short to share with the cue
   (short landscape screens): the cue would sit on the car */
.hero-cue.is-cramped{display:none}
.hero-cue svg{display:block;animation:cueDrift 1.8s ease-in-out infinite}
.hero-cue svg + svg{margin-top:-9px;opacity:.45;animation-delay:.14s}

/* Finish swatches, tied to the turntable (see finishes in the logic): a
   22px colour dot and the finish name, in a 44px hit box. The finish on
   screen gets a ring round its dot and full-strength text. */
.swatches{grid-area:swatch;justify-self:center;display:flex;flex-wrap:wrap;justify-content:center;gap:var(--s-2);animation:riseIn .7s var(--ease-out) .3s both}
.swatch{display:inline-flex;align-items:center;gap:var(--s-2);min-height:44px;min-width:44px;margin:0;padding:0 var(--s-3);background:none;border:0;border-radius:0;
  color:var(--text-muted);font-family:var(--font-body);font-size:0.875rem;line-height:1.2;font-weight:600;cursor:pointer;
  -webkit-tap-highlight-color:transparent;touch-action:manipulation;transition:color 150ms ease}
.swatch:hover,.swatch[aria-pressed="true"]{color:var(--color-text)}
.swatch:focus-visible{outline:2px solid var(--color-accent-700);outline-offset:2px}
.swatch-chip{width:22px;height:22px;flex:none;border-radius:50%;background:linear-gradient(140deg,color-mix(in srgb, var(--chip) 55%, #fff) 0%,var(--chip) 42%,color-mix(in srgb, var(--chip) 70%, #000) 100%);
  box-shadow:inset 0 0 0 1px color-mix(in srgb, #000 25%, transparent);transition:box-shadow 150ms ease,transform 160ms var(--ease-out)}
.swatch[aria-pressed="true"] .swatch-chip{box-shadow:0 0 0 2px var(--color-bg),0 0 0 4px var(--color-text)}
.swatch:active .swatch-chip{transform:scale(0.9)}

/* Phones and portrait tablets: a shorter pin and a larger headline, clearly
   above the section H2s (34px lead, 28px support on phones). */
@media (max-width:699px), (max-width:899px) and (orientation:portrait){
  .hero{height:135vh;height:135svh}
  .hero-pin{row-gap:var(--s-4)}
  .hero-title{font-size:clamp(2.75rem,13vw,3.75rem);letter-spacing:-0.025em}
  /* the car spans the full viewport width; frames carry ~19px of transparent
     margin each side, so a 1.04 scale fills the width without cutting either end */
  .hero-car{margin-inline:calc(-1 * var(--gutter))}
  .hero-car-stack{max-width:none;transform:scale(1.04)}
}
/* short landscape screens (and zoomed desktops): the headline is capped by
   the height, so it keeps its two lines beside the swatches */
@media (max-height:640px) and (orientation:landscape){
  .hero-title{font-size:clamp(1.75rem,min(11vh,7.5vw),3.5rem);letter-spacing:-0.025em}
}
/* Short landscape screens under 1024px wide (a phone on its side, a
   desktop at 200% zoom): width to spare and no height, so the copy and the
   car sit side by side (the 5 : 7 split) and the car's height follows its
   column's width instead of the few pixels left under a stacked copy. The
   subline steps aside there; the headline and the WhatsApp button carry
   the screen, and Services repeats that copy. Placed after the phone rules
   so the car's edge bleed is undone here. */
@media (max-height:640px) and (orientation:landscape) and (max-width:1023px){
  .hero-pin{grid-template-columns:minmax(0,5fr) minmax(0,7fr);grid-template-rows:auto auto;grid-template-areas:"copy car" "copy swatch";
    column-gap:var(--space-col-wide);row-gap:var(--s-2);align-content:center;align-items:center;padding-bottom:clamp(40px,9vh,56px)}
  .hero-sub{display:none}
  .hero-cta{margin-top:var(--s-4)}
  /* sized from the copy column (cqi) so each headline line stays whole */
  .hero-copy{container-type:inline-size}
  .hero-title{font-size:clamp(1.75rem,min(16.5cqi,11vh),3.5rem)}
  .hero-car{align-self:end;margin-inline:0}
  .hero-car-stack{max-height:none;transform:none}
  .swatches{justify-self:center;align-self:start}
}
/* Short portrait phones (320x568 and the like): the stacked copy left the
   car ~50px tall, so the subline steps aside here too */
@media (max-width:699px) and (orientation:portrait) and (max-height:600px){
  .hero-sub{display:none}
}
/* Wide hero, landscape from 1024px: the copy becomes one band across the
   top (the headline in the 7 column, the subline and WhatsApp button in the
   5, bottom-aligned with it), and the car takes the full content width
   under it at 80% of that width (up to 940px), with the swatches centred below. The car's row is
   the one that gives when the screen is short: it shrinks with the height
   left over, never the copy. Placed after the short-landscape rules so it
   replaces them at these widths. */
@media (min-width:1024px) and (orientation:landscape){
  .hero-pin{grid-template-columns:minmax(0,7fr) minmax(0,5fr);grid-template-rows:auto auto minmax(0,auto) auto;
    grid-template-areas:"title sub" "title cta" "car car" "swatch swatch";column-gap:var(--space-col-wide);row-gap:0;align-content:center;
    padding-block:clamp(24px,4vh,48px) clamp(56px,9vh,88px)}
  .hero-copy{display:contents}
  .hero-title{grid-area:title;align-self:end;font-size:clamp(2.25rem,min(6.6vw,11vh),6.5rem);letter-spacing:-0.04em}
  .hero-sub{grid-area:sub;align-self:end;margin:0;max-width:46ch}
  .hero-cta{grid-area:cta;justify-self:start;align-self:end;margin-top:var(--s-5)}
  .hero-car{margin-top:clamp(16px,4vh,48px)}
  .hero-car-stack{width:80%;max-width:940px}
  .swatches{justify-self:center;align-self:start;margin-top:var(--s-2)}
}
/* Display tracking by size: -0.035em closes the word spaces once a heading
   is ~48px or smaller, so those sizes run at -0.02em. */
@media (max-width:767px){
  .t-h2,.close-title{letter-spacing:-0.02em}
}
@media (max-width:1099px){
  .section--support .t-h2{letter-spacing:-0.02em}
}

/* ── Services: two groups, wrap (the look) and protection, as equals ──── */
.svc-groups{display:grid;gap:var(--space-group)}
.svc-group-label{margin-bottom:var(--s-3);font-family:inherit}
.svc-row{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--s-3) var(--space-col-wide);padding:var(--space-row) 0;border-top:2px solid var(--color-divider)}
.svc-head .t-num{margin-bottom:var(--s-1)}
.svc-copy{max-width:52ch}
@media (min-width:768px){.svc-row{grid-template-columns:minmax(0,5fr) minmax(0,7fr)}}

/* ── Gallery: after photo by default, the before on hover / tap / Enter ───
   Narrow: heading + hint, the 2x2 grid, then the quote button under the
   photos (DOM order). Wide: a sticky heading column beside the grid, with
   the button pinned under the heading. The button stays after the grid in
   the DOM, so it shares the heading's column and sticks at the heading's
   measured height (--gal-head-h, set in _applyLayout). The heading reserves
   the button's room in its padding, so the two release together.
   reading-flow puts it before the photos in focus order where supported. */
.gallery-layout{display:grid;grid-template-columns:minmax(0,1fr);align-items:start}
.gallery-head{margin-bottom:var(--space-head-gap)}
.gallery-head .section-title{margin-bottom:var(--space-title-lede)}
.gal-cta{justify-self:start;margin-top:var(--space-group)}
/* Show more / less: under the grid, left-aligned, the count after it */
.gal-more{display:flex;flex-wrap:wrap;align-items:center;gap:var(--s-2) var(--s-4);margin-top:var(--space-group)}
.gal-more-btn{margin:0;font-family:var(--font-heading);cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.gal-more-btn:focus-visible{outline:2px solid var(--color-accent-700);outline-offset:3px}
.gal-count{font-variant-numeric:tabular-nums}
.gallery-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-group) var(--space-tile);width:100%;max-width:calc(0.8 * var(--gal-tile-max-h))}
@media (min-width:640px){.gallery-grid{grid-template-columns:repeat(2,minmax(0,1fr));max-width:calc(1.6 * var(--gal-tile-max-h) + var(--space-tile))}}
/* wide screens: heading column + 2x2 grid, so tiles stay big without the
   section growing to twice the viewport. The heading column is never
   narrower than the heading itself, so it stays one line at the switch. */
@media (min-width:1200px){
  .gallery-layout{grid-template-columns:minmax(min-content,1fr) minmax(0,2.3fr);column-gap:var(--space-col-wide);reading-flow:grid-order}
  .gallery-head,.gal-cta{grid-column:1;grid-row:1;position:sticky}
  .gallery-head{top:calc(var(--navh,70px) + var(--s-8));margin-bottom:0;padding-bottom:calc(var(--space-group) + 52px)}
  .gallery-head .section-title{white-space:nowrap}
  .gal-cta{top:calc(var(--navh,70px) + var(--s-8) + var(--gal-head-h,150px) + var(--space-group));margin-top:calc(var(--gal-head-h,150px) + var(--space-group))}
  .gallery-grid{grid-column:2;grid-row:1;order:1}
  .gal-more{grid-column:2;grid-row:2}
}
.gal-swap{position:relative;display:block;width:100%;aspect-ratio:4/5;margin:0;padding:0;border:0;border-radius:0;background:var(--color-neutral-200);color:inherit;font:inherit;text-align:left;cursor:pointer;overflow:hidden;-webkit-tap-highlight-color:transparent;touch-action:manipulation;-webkit-user-select:none;user-select:none}
.gal-swap:focus-visible{outline:2px solid var(--color-accent-700);outline-offset:3px}
.gal-layer{position:absolute;inset:0;display:block;transition:opacity .28s ease}
.gal-layer img{width:100%;height:100%;object-fit:cover;display:block}
.gal-before{opacity:0}
.gal-tag{position:absolute;top:var(--s-3);left:var(--s-3);z-index:3;padding:var(--s-1) var(--s-2);transition:opacity .2s ease}
.gal-tag-after{background:var(--accent-ink);color:var(--color-bg)}
.gal-tag-before{background:var(--color-bg);color:var(--color-text);opacity:0}
.gal-swap[aria-pressed="true"] .gal-before,.gal-swap[aria-pressed="true"] .gal-tag-before{opacity:1}
.gal-swap[aria-pressed="true"] .gal-tag-after{opacity:0}
@media (hover:hover){
  .gal-swap:hover .gal-before,.gal-swap:hover .gal-tag-before{opacity:1}
  .gal-swap:hover .gal-tag-after{opacity:0}
}
.gal-cap{padding-top:var(--s-3)}
.gal-cap .t-h3{margin-bottom:2px} /* optical: caption title to its finish line */
/* "Original -> Pearl": a drawn arrow (Archivo has no U+2192), sized to the
   caption text; screen readers get the word in .sr-only instead */
.cap-arrow{display:inline-block;width:1.1em;height:1.1em;margin-inline:0.2em;vertical-align:-0.2em}

/* ── Process: titles aligned across columns by a subgrid ───────────────── */
.process-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-group) var(--space-col)}
@media (min-width:480px){.process-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:900px){.process-grid{grid-template-columns:repeat(4,minmax(0,1fr))}}
.process-step{display:grid;grid-row:span 3;grid-template-rows:subgrid;row-gap:var(--s-2);align-content:start}

/* ── Coverage: pick an option, the render shows it. Under 960px one column
   with the render FIRST (full-bleed on phones), then the options, then the
   description, so a tap changes the picture on the same screen; phone
   options sit in an even two-column grid. From 960px the options (~40%) sit
   beside the render (~60%) and the description runs the full width under
   both, on the same two columns: option name, covered parts and the key
   under the options; the quote line and button under the render. ───────── */
.cov-layout{display:grid;grid-template-columns:minmax(0,1fr);grid-template-areas:"stage" "picker" "detail";gap:var(--space-group)}
.cov-picker{grid-area:picker;display:grid;gap:var(--s-6)}
/* when the picker column cannot hold four options on one row (960-1439px,
   and phones), they sit in an even 2 x 2 rather than 3 + 1 */
.cov-picker{container-type:inline-size}
@container (max-width:499px){
  .cov-picker .cov-options{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .cov-picker .cov-opt{min-width:0;padding-inline:var(--s-3)}
}
.cov-group-label{margin-bottom:var(--s-3)}
.cov-options{display:flex;flex-wrap:wrap;gap:var(--s-2)}
/* pressed: filled in the text colour */
.cov-opt{margin:0;font-family:var(--font-heading);cursor:pointer;-webkit-tap-highlight-color:transparent;touch-action:manipulation}
.cov-opt[aria-pressed="true"],.cov-opt[aria-pressed="true"]:hover{background:var(--color-text);border-color:var(--color-text);color:var(--color-bg)}
.cov-opt:focus-visible{outline:2px solid var(--color-accent-700);outline-offset:3px}
.cov-stage{grid-area:stage;margin:0;min-width:0}
.cov-car{position:relative;width:100%;max-width:920px;aspect-ratio:840/290}
.cov-car img{position:absolute;inset:0;width:100%;height:100%;display:block}
/* film: out in 150ms, in over 260ms, so a swap crossfades */
.cov-film{opacity:0;pointer-events:none;transition:opacity 150ms var(--ease-out)}
.cov-film.is-on{opacity:1;transition:opacity 260ms var(--ease-out)}
.cov-caption{margin-top:var(--s-3)}
.cov-detail{grid-area:detail;display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-group) var(--space-col-wide);border-top:2px solid var(--color-divider);padding-top:var(--s-6)}
/* covered parts: one run, dot-separated, wrapping after a dot */
.cov-parts{list-style:none;margin:var(--s-2) 0 0;padding:0}
.cov-parts li{display:inline}
.cov-parts li:not(:last-child)::after{content:"\00a0\00b7 ";color:var(--text-subtle)}
.cov-note{margin-top:var(--s-1)}
/* the key: a chip in the film's highlight colour (sampled from the renders) */
.cov-key{display:inline-flex;align-items:center;gap:var(--s-2);margin-right:var(--s-1);color:var(--color-text);font-weight:600}
.cov-key-chip{width:12px;height:12px;flex:none;background:#ff563c;opacity:.75;box-shadow:inset 0 0 0 1.5px #ff563c}
.cov-quote{max-width:52ch}
.cov-ask .btn{margin-top:var(--s-4)}
@media (max-width:959px){
  .cov-opt{min-height:52px;padding-inline:var(--s-5)}
}
/* phones: the render bleeds to the screen edges (frames carry ~19px of
   transparent margin each side); options in two equal columns */
@media (max-width:599px){
  .cov-options{display:grid;grid-template-columns:repeat(2,minmax(0,1fr))}
  .cov-opt{min-width:0;padding-inline:var(--s-3)}
  .cov-car{width:calc(100% + 2 * var(--gutter));margin-inline:calc(-1 * var(--gutter))}
  .cov-ask .btn{width:100%}
}
@media (min-width:960px){
  .cov-layout{grid-template-columns:minmax(0,2fr) minmax(0,3fr);grid-template-areas:"picker stage" "detail detail";column-gap:var(--space-col-wide);align-items:start}
  /* top-aligned with the options (their group label's height) */
  .cov-stage{padding-top:var(--s-6)}
  .cov-detail{grid-template-columns:minmax(0,2fr) minmax(0,3fr)}
}

/* ── Location ──────────────────────────────────────────────────────────── */
.loc-grid{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(100%,320px),1fr));gap:var(--space-group) var(--space-col-wide)}
.loc-grid .t-h3{margin-bottom:var(--s-4)}
.loc-grid .t-label{margin-bottom:var(--s-2)}
.loc-block + .loc-block{margin-top:var(--s-6)}
/* the bay photo: one 4:5 tile, square corners as the gallery; its src is
   set by the logic once it comes near the screen. The container is a grid
   on purpose: the loader waits for display:grid as its sign that this
   stylesheet has applied (before it does, the page is short and every
   photo looks near). */
.shop-photo{display:grid}
.shop-photo-img{display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;border-radius:0;background:var(--color-neutral-200)}
.shop-photo-img:not([src]){color:transparent} /* no alt text painted before the src is set */
.loc-block .t-body + .link-list{margin-top:var(--s-1)}
.link-u,.link-u:hover{text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.link-u:hover{text-decoration-thickness:2px}

/* Stacked links (Location, footer): each is a block-level hit box. 32px on
   a fine pointer keeps the list's rhythm; 44px on phones and touch screens. */
.link-list{list-style:none;margin:0;padding:0}
.link-list a{display:inline-flex;align-items:center;min-height:32px}

/* ── Close ─────────────────────────────────────────────────────────────── */
.close{padding-block:var(--space-section-lead);background:var(--accent-ink);color:var(--color-bg)}
.close-title{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:clamp(2.25rem,6.2vw,5.25rem);line-height:0.98;letter-spacing:-0.035em;margin:0 0 var(--space-title-lede);color:var(--color-bg)}
.close-lede{max-width:44ch;text-wrap:balance;margin:0 0 var(--space-group)}
.close-actions{display:flex;flex-wrap:wrap;gap:var(--s-3)}
@media (max-width:479px){.close-actions .btn{flex:1 1 100%}}
.close a.btn-light{background:var(--color-bg);border-color:var(--color-bg);color:var(--color-text)}
.close a.btn-light:hover{background:#fff;border-color:#fff;color:var(--color-text)}
.close a.btn-light:active{background:var(--color-neutral-300);border-color:var(--color-neutral-300);color:var(--color-text)}
.close a.btn-outline,.close a.btn-outline:hover,.close a.btn-outline:active{color:var(--color-bg)}
.close a.btn-outline:hover{background:color-mix(in srgb, var(--color-bg) 14%, transparent)}
.close a.btn-outline:active{background:color-mix(in srgb, var(--color-bg) 24%, transparent)}
.close a:focus-visible{outline:2px solid var(--color-bg);outline-offset:3px}
.close-email{margin-top:var(--s-6)}
.close-email a,.close-email a:hover{color:var(--color-bg);text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:1px}
.close-email a:hover{text-decoration-thickness:2px}

/* ── Footer: wordmark, service links, one contact line, legal ──────────── */
.site-footer{padding-block:var(--space-section-support)}
.footer-mark{font-family:var(--font-heading);font-weight:var(--font-heading-weight);font-size:1.5rem;line-height:1;letter-spacing:-0.02em;margin:0 0 var(--space-group)}
.footer-grid{display:grid;grid-template-columns:minmax(0,1fr);gap:var(--space-group) var(--space-col);border-top:2px solid var(--color-divider);padding-top:var(--s-8)}
@media (min-width:768px){.footer-grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
.footer-grid .t-label{margin-bottom:var(--s-2)}
.footer-contact{display:flex;flex-wrap:wrap;column-gap:var(--s-6)}
.footer-legal{margin-top:var(--space-group)}

/* Touch: every stacked or inline text link gets a 44px hit box */
@media (max-width:767px), (pointer:coarse){
  .link-list a{min-height:44px}
  .close-email a{display:inline-flex;align-items:center;min-height:44px}
}

/* ── Sticky WhatsApp bar: phones only, shown once the hero has released and
   hidden while the close's own buttons are on screen. ──────────────────── */
.wa-bar{display:none}
@media (max-width:767px){
  /* keyboard focus and anchor jumps stop above the bar, not under it */
  html{scroll-padding-bottom:calc(76px + env(safe-area-inset-bottom,0px))}
  .wa-bar{position:fixed;left:0;right:0;bottom:0;z-index:40;display:flex;gap:var(--s-2);padding:var(--s-2) var(--s-3) calc(var(--s-2) + env(safe-area-inset-bottom,0px));background:var(--color-bg);border-top:2px solid var(--color-divider);transform:translateY(110%);visibility:hidden;transition:transform .32s var(--ease-out),visibility 0s linear .32s}
  .wa-bar.is-on{transform:none;visibility:visible;transition:transform .32s var(--ease-out),visibility 0s}
  .wa-bar .btn-primary{flex:1 1 auto;min-width:0;padding-inline:var(--s-4)}
  .wa-bar .wa-bar-call{flex:none;width:52px;padding:0}
  .site-footer{padding-bottom:calc(var(--space-section-support) + 76px + env(safe-area-inset-bottom,0px))}
  /* the menu has the floor: the bar steps down while it is open */
  .menu-open .wa-bar.is-on{transform:translateY(110%);visibility:hidden;transition:transform .32s var(--ease-out),visibility 0s linear .32s}
}
@media (prefers-reduced-motion:reduce){.wa-bar,.wa-bar.is-on,.menu-open .wa-bar.is-on,.nav-scrim,.menu-open .nav-scrim{transition:none}}

/* ── Reduced motion ────────────────────────────────────────────────────── */
@media (prefers-reduced-motion:reduce){
  .hero-title,.hero-sub,.hero-cta,.swatches{animation-name:fadeIn}
  .hero-cue svg{animation:none!important}
  .btn:active{transform:none}
  .swatch:active .swatch-chip{transform:none}
}

/* ── Without JavaScript ─────────────────────────────────────────────────
   support.js hides <x-dc> the moment it runs and mounts the page into
   #dc-root, so rules scoped to x-dc only ever reach a visit without
   JavaScript, where the raw template is what renders. There the {{ }}
   placeholders (lists, bound text, the mono-tone nav button) are hidden,
   along with the sections whose content only exists in the script, and the
   close keeps its brand colour (its inline value is a placeholder). The
   WhatsApp links already carry real hrefs. */
x-dc .page{--accent-ink:var(--color-accent-700)!important}
x-dc sc-for,x-dc [data-live],x-dc sc-if[value="{{ isMono }}"],x-dc .swatches,x-dc .cov-picker,x-dc .cov-what,
x-dc #services,x-dc #gallery,x-dc #process,x-dc .rule,x-dc .hero-cue{display:none}
@media (max-width:767px){x-dc .nav-links{display:none}}
