/* ============================================================
   DUCKIT — persistent shell: header, mobile nav, WhatsApp dock,
   footer, lightbox. Shared by all five pages.
   ============================================================ */

/* ============================================================ header */

.hdr {
  position: sticky;
  top: 0;
  z-index: 80;
  height: var(--header-h);
  display: flex;
  align-items: center;
  background: rgba(10, 10, 11, 0.72);
  backdrop-filter: blur(14px) saturate(1.3);
  -webkit-backdrop-filter: blur(14px) saturate(1.3);
  border-bottom: 1px solid var(--line);
}

.hdr__in {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--pad-x);
  display: flex;
  align-items: center;
  gap: clamp(16px, 3vw, 48px);
}

.hdr__logo { flex: none; display: block; }
.hdr__logo img {
  width: 156px;
  height: 40px;
  object-fit: contain;
  transform-origin: left center;
  transition: transform 280ms var(--ease);
}

/* The header densifies once the page leaves the top. An --ink slab fades in
   rather than tweening background-color, so it stays compositor work; .hdr is
   already its own stacking context (sticky + z-index:80), so a z-index:-1
   pseudo paints above .hdr's own background but below .hdr__in.

   It stops well short of opaque on purpose. At 1 it would completely occlude
   the backdrop-filter above, and the move would read as the frosted glass
   switching off rather than as the bar getting denser. 0.55 over the base
   rgba(10,10,11,0.72) lands near 0.87 effective with the blur still showing.

   content:'' is load-bearing — without it the pseudo is never generated and
   none of this renders at all. */
.hdr::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--ink);
  opacity: 0;
  z-index: -1;
  pointer-events: none;
  transition: opacity 280ms var(--ease);
}
.hdr.is-stuck::after { opacity: 0.55; }
.hdr.is-stuck .hdr__logo img { transform: scale(0.9); }

/* site.js is deferred, so a visitor who reloads mid-page would otherwise watch
   the header tween into its stuck state the moment the script runs. It sets the
   initial state under this class, forces a reflow, then removes it. */
.hdr.no-anim::after,
.hdr.no-anim .hdr__logo img { transition: none; }

.hdr__nav { margin-left: auto; }
.hdr__list { display: flex; align-items: center; gap: clamp(4px, 1.6vw, 8px); }

.hdr__link {
  position: relative;
  display: block;
  padding: 10px 14px;
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--mute);
  transition: color 0.2s var(--ease);
}
.hdr__link:hover { color: var(--white); }

/* current page: torch bar under the label + full-white type */
.hdr__link[aria-current='page'] { color: var(--white); }
.hdr__link[aria-current='page']::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 2px;
  height: 2px;
  background: var(--torch);
}

.hdr__cta { flex: none; margin-left: 8px; padding: 12px 20px; }

/* --- Services dropdown (desktop) --- */
.hdr__item { position: relative; }
.hdr__item--menu > .hdr__link { display: inline-flex; align-items: center; gap: 5px; }

.hdr__chev {
  width: 13px; height: 13px; margin-right: -3px;
  transition: transform 0.28s var(--ease);
}
.hdr__item--menu:hover .hdr__chev,
.hdr__item--menu:focus-within .hdr__chev { transform: rotate(180deg); }

.hdr__menu {
  position: absolute;
  top: calc(100% - 8px);
  left: 6px;
  min-width: 268px;
  display: flex;
  flex-direction: column;
  padding: 8px;
  background: var(--ink-3);
  border: 1px solid var(--line-strong);
  border-top: 2px solid var(--torch);
  box-shadow: 0 26px 60px -14px rgba(0, 0, 0, 0.75);
  opacity: 0;
  visibility: hidden;
  transform: translateY(8px);
  transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
  z-index: 5;
}
.hdr__item--menu:hover .hdr__menu,
.hdr__item--menu:focus-within .hdr__menu {
  opacity: 1; visibility: visible; transform: none;
}

.hdr__mlink {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 13px;
  font-family: var(--display);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.045em;
  text-transform: uppercase;
  color: var(--mute);
  white-space: nowrap;
  transition: color 0.16s var(--ease), background 0.16s var(--ease);
}
.hdr__mlink:hover { color: var(--white); background: rgba(255, 255, 255, 0.055); }

/* The Car Model menu is a marque -> series tree, so the two levels have to read
   as different ranks rather than as one flat list. The series rows drop the
   marque icon and sit in from it, using the space the icon left. */
.hdr__mlink--marque { color: var(--white); }
.hdr__mlink--series {
  padding-left: 42px;
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--white);
}
/* the rule ties each series back to the marque above it */
.hdr__mlink--series::before {
  content: '';
  position: absolute;
  left: 22px;
  width: 8px;
  height: 1px;
  background: var(--line-strong);
}
.hdr__mlink--series { position: relative; }
.hdr__mlink--series:hover::before { background: var(--torch); }

/* A marque tree makes this menu much longer than the six-row Services one, so
   it is capped and allowed to scroll rather than running off a short laptop. */
.hdr__menu {
  max-height: calc(100svh - var(--header-h) - 40px);
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line-strong) transparent;
}

/* The panel used to arrive as one flat block. Its rows now rack in, which is
   the whole point of a menu that lists six benches — you see them counted out.
   The colour/background transitions above are extended, not replaced, or the
   hover state would stop animating.

   Delays are set only in the open state. On close they must not apply, or
   dismissing the menu would drag out over the full stagger; leaving is
   immediate, arriving is sequenced. */
.hdr__mlink {
  opacity: 0;
  transform: translateY(-6px);
  transition: color 0.16s var(--ease), background 0.16s var(--ease),
    opacity 200ms var(--ease), transform 200ms var(--ease);
}
.hdr__item--menu:hover .hdr__mlink,
.hdr__item--menu:focus-within .hdr__mlink { opacity: 1; transform: none; }

.hdr__item--menu:hover .hdr__mlink:nth-child(1),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(1) { transition-delay: 30ms; }
.hdr__item--menu:hover .hdr__mlink:nth-child(2),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(2) { transition-delay: 60ms; }
.hdr__item--menu:hover .hdr__mlink:nth-child(3),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(3) { transition-delay: 90ms; }
.hdr__item--menu:hover .hdr__mlink:nth-child(4),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(4) { transition-delay: 120ms; }
.hdr__item--menu:hover .hdr__mlink:nth-child(5),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(5) { transition-delay: 150ms; }
.hdr__item--menu:hover .hdr__mlink:nth-child(n+6),
.hdr__item--menu:focus-within .hdr__mlink:nth-child(n+6) { transition-delay: 180ms; }
.hdr__mico { width: 17px; height: 17px; flex: none; color: var(--torch); }

/* --- Car Model menu: marques on the left, one marque's series beside them ---
   Every chassis at once made this panel as wide as its widest row: .hdr__mlink
   is nowrap, so a 3 Series row carrying six chassis codes dragged the panel
   187px past the right edge of a 1280 viewport, and the list ran the height of
   the screen. Now the marques are the menu and the series arrive one marque at
   a time, in a pane of fixed width where the chassis line can wrap. */
.hdr__menu--cars {
  padding: 0;
  /* anchored to the item's right edge: at this width, opening from the left
     would put it through the Enquire button and off the page */
  left: auto;
  right: 0;
  width: min(620px, calc(100vw - 32px));
  min-width: 0;
}
.hdr__cars { display: grid; grid-template-columns: 216px minmax(0, 1fr); }
/* The panel hangs off the item's right edge, and that edge moves left with the
   viewport - at 1025, the narrowest width the desktop nav is shown at, 620
   would hang 7px off the left of the page. */
@media (max-width: 1180px) {
  .hdr__menu--cars { width: 540px; }
  .hdr__cars { grid-template-columns: 186px minmax(0, 1fr); }
}
.hdr__cars-marques { padding: 8px; border-right: 1px solid var(--line); }
.hdr__cars-panes { padding: 8px; min-width: 0; }
.hdr__cars-pane[hidden] { display: none; }
.hdr__cars-h {
  padding: 4px 13px 10px;
  font-family: var(--mono);
  font-weight: 600;
  font-size: 0.6875rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--mute);
}
/* the series sit in their own pane now, so they no longer need to be indented
   away from a marque above them */
.hdr__menu--cars .hdr__mlink--series { padding-left: 13px; }
.hdr__menu--cars .hdr__mlink--series::before { display: none; }
/* a chassis line is free to wrap in here - it is what used to stretch the
   panel, and there is nothing beside it to push out of the way */
.hdr__menu--cars .hdr__mlink { white-space: normal; }
.hdr__menu--cars .hdr__mlink--marque .hdr__mtxt { min-width: 0; flex: 1; }
/* the marque whose series are showing */
.hdr__mlink.is-on { color: var(--white); background: rgba(255, 255, 255, 0.055); }
.hdr__mlink.is-on .hdr__mchev { color: var(--torch); }
.hdr__mchev { width: 13px; height: 13px; flex: none; margin-left: auto; color: var(--mute-dim); }

/* the Car Model menu adds the chassis each series covers under its name */
.hdr__mtxt { display: flex; flex-direction: column; gap: 3px; }
/* The chassis codes under a series. They were 10px, weight 400, at the dim
   grey and 0.08em tracked - which is fine for two of them and unreadable for
   the six a 3 Series carries, wrapped over three lines. Bigger, heavier,
   brighter and tracked in, with room between the lines it wraps onto. */
.hdr__msub {
  font-family: var(--mono);
  font-size: 0.75rem;
  font-style: normal;
  font-weight: 500;
  letter-spacing: 0.02em;
  line-height: 1.6;
  text-transform: none;
  color: var(--mute);
}
.hdr__mlink:hover .hdr__msub { color: var(--white); }
/* --- burger --- */
.burger {
  display: none;
  margin-left: auto;
  width: 46px;
  height: 46px;
  place-items: center;
  color: var(--white);
}
.burger svg { width: 24px; height: 24px; }
.burger .x { display: none; }
.burger[aria-expanded='true'] .menu { display: none; }
.burger[aria-expanded='true'] .x { display: block; }

/* ============================================================ mobile drawer */

.drawer {
  position: fixed;
  inset: var(--header-h) 0 0;
  z-index: 79;
  display: flex;
  flex-direction: column;
  padding: 28px var(--pad-x) 40px;
  background: var(--ink);
  overflow-y: auto;
  transform: translateY(-8px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), visibility 0.28s;
}
.drawer.open { opacity: 1; transform: none; visibility: visible; }

/* The panel faded in as one flat sheet. Its rows now rack down in sequence —
   the numbered nav (01, 02, 03 …) is already counting itself out, so the motion
   just says the same thing.

   As with the desktop menu, the delays live only in the open state: closing has
   to be immediate or dismissing the drawer would drag across the whole stagger.
   The drawer itself is `visibility: hidden` while closed, so children sitting
   at opacity 0 costs nothing. */
.drawer > nav > *,
.drawer__foot {
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 260ms var(--ease), transform 260ms var(--ease);
}
.drawer.open > nav > *,
.drawer.open .drawer__foot { opacity: 1; transform: none; }

.drawer.open > nav > :nth-child(1) { transition-delay: 70ms; }
.drawer.open > nav > :nth-child(2) { transition-delay: 115ms; }
.drawer.open > nav > :nth-child(3) { transition-delay: 160ms; }
.drawer.open > nav > :nth-child(4) { transition-delay: 205ms; }
.drawer.open > nav > :nth-child(5) { transition-delay: 250ms; }
.drawer.open > nav > :nth-child(6) { transition-delay: 295ms; }
.drawer.open > nav > :nth-child(n+7) { transition-delay: 340ms; }
.drawer.open .drawer__foot { transition-delay: 385ms; }

.drawer__link {
  display: flex;
  align-items: baseline;
  gap: 14px;
  padding: 18px 0;
  border-bottom: 1px solid var(--line);
  font-family: var(--display);
  font-size: clamp(1.65rem, 8vw, 2.25rem);
  font-weight: 800;
  letter-spacing: -0.02em;
  line-height: 1;
  color: var(--mute);
}
.drawer__link[aria-current='page'] { color: var(--white); }
.drawer__link[aria-current='page'] .drawer__no { color: var(--torch); }
.drawer__no { font-family: var(--mono); font-size: 0.6875rem; font-weight: 500; letter-spacing: 0.1em; color: var(--mute-dim); }

/* Services sub-links in the drawer */
.drawer__link--parent { border-bottom: 0; padding-bottom: 8px; }
.drawer__sublist {
  display: grid;
  padding: 0 0 18px 30px;
  border-bottom: 1px solid var(--line);
}
/* The parent and its children were both --display and differed only in size, so
   a sub-item read as a smaller version of the same thing rather than as a
   different rank. The site already separates these two jobs by typeface —
   display for the headline items, mono for the technical/secondary labels
   (the 01-05 numbers, eyebrows, chassis codes) — so the children move to mono.
   Different in kind, not just in degree. */
/* Same reading as the desktop menu's: --mute-dim at this size measures 4.3:1
   on the drawer's ground, under the 4.5 AA wants, and the weight was doing it
   no favours either. */
.drawer__sub {
  position: relative;
  padding: 12px 0;   /* 21px line-box + 24px = 45px, clears the 44px touch target */
  font-family: var(--mono);
  font-size: 0.8125rem;
  font-weight: 500;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--mute);
  transition: color 0.16s var(--ease);
}
/* Same two-rank tree as the desktop dropdown: a marque row, then the series
   under it sitting further in. */
.drawer__sub--marque { color: var(--white); }
.drawer__sub--series { padding-left: 18px; font-size: 0.75rem; }
.drawer__sub--series::before { left: 0; width: 8px; }

.drawer__sub::before {
  content: '';
  position: absolute;
  left: -18px; top: 50%;
  width: 7px; height: 1px;
  background: var(--line-strong);
}
.drawer__sub:hover, .drawer__sub:focus-visible { color: var(--torch); }

.drawer__foot { margin-top: auto; padding-top: 32px; }
.drawer__foot .btn { width: 100%; justify-content: center; }

@media (max-width: 1024px) {
  .hdr__nav, .hdr__cta { display: none; }
  .burger { display: grid; }
}
@media (min-width: 1025px) {
  .drawer { display: none; }
}

/* ============================================================ breadcrumb
   Overlaid on the hero (absolute) so it never changes the header+hero=100vh
   math. The part detail pages have no hero to overlay — there it becomes a
   normal row, or it lands on top of the photo. */

main { position: relative; }

.crumbs {
  position: absolute;
  top: 0; left: 0; right: 0;
  z-index: 6;
  padding-top: clamp(10px, 1.5vw, 16px);
  padding-bottom: 22px;
  background: linear-gradient(180deg, rgba(10, 10, 11, 0.62) 0%, rgba(10, 10, 11, 0.24) 52%, transparent);
  pointer-events: none;
}
.crumbs--flow {
  position: static;
  padding-top: clamp(14px, 2vw, 22px);
  padding-bottom: 0;
  background: none;
}

/* Because .crumbs is taken out of flow, nothing below it reserves its space.
   On desktop that is invisible - the hero is far taller than its content, which
   settles near the bottom. On a phone the hero content grows past the hero's own
   min-height, so it starts at the top of its box and runs straight under the
   trail, which by then has wrapped to two lines. The eyebrow and the breadcrumb
   overlap.

   The reserve has to be the *measured* height: the trail wraps differently per
   page and per width, so any fixed offset is wrong somewhere. site.js publishes
   --crumbs-h; the value below is the no-JS fallback, sized for a two-line trail.
   box-sizing is border-box globally, so this padding sits inside the hero's
   min-height and does not disturb the home hero's header+hero=100svh. */
/* Pre-JS fallback only — site.js replaces it with the measured height. Sized for
   a two-line trail at 375px: 10 (padding-top) + 2 x 19.44 (12px x 1.62) + 5 (the
   row gap) + 22 (padding-bottom) = 76px. site.js is deferred, so this value is
   what governs first paint; too small and every wrapping trail overlaps for a
   frame before the measurement lands. */
:root { --crumbs-h: 76px; }

/* Gated on height as well as width. The trigger is "hero content outgrew the
   hero's own min-height", which is not a width question: a phone in landscape is
   812px wide - past any sensible mobile breakpoint - but only 375px tall, so
   --band-h collapses to 280px and the content overruns it just as badly. The
   height clause catches that, and a short desktop window, without moving
   anything on a normal desktop.

   --crumbs-reserve is the opt-out. This selector is (0,2,2), so a media-first
   hero cannot cancel it with a plain `.ahero { padding-top: 0 }` at (0,1,0) -
   but a custom property resolves per element, so setting the variable wins. */
@media (max-width: 767px), (max-height: 620px) {
  main > .crumbs:not(.crumbs--flow) + section {
    padding-top: var(--crumbs-reserve, var(--crumbs-h));
  }
}
.crumbs__list {
  display: flex; flex-wrap: wrap; align-items: center; gap: 5px 8px;
  font-family: var(--mono); font-size: var(--t-xs);
  letter-spacing: 0.1em; text-transform: uppercase;
}
.crumbs__i { display: flex; align-items: center; gap: 8px; color: var(--mute); }
.crumbs__i a { color: var(--mute); pointer-events: auto; transition: color 0.2s var(--ease); }
.crumbs__i a:hover { color: var(--white); }
.crumbs__i[aria-current='page'] { color: var(--torch); }
.crumbs__i:not(:first-child)::before { content: '/'; color: var(--mute-dim); }

/* ============================================================ WhatsApp dock (4 contacts) */

.wa {
  position: fixed;
  right: clamp(16px, 3vw, 28px);
  bottom: clamp(16px, 3vw, 28px);
  z-index: 90;
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 12px;
  /* The panel is hidden with visibility, not display, so this container keeps
     its full 300x397 box even when closed. Fixed + pointer-events:auto meant
     that empty rectangle swallowed every touch over it — on a phone that is a
     third of the screen you cannot scroll. Only the button and the open panel
     should take input. */
  pointer-events: none;
}
.wa__btn, .wa__panel { pointer-events: auto; }
.wa__panel:not(.open) { pointer-events: none; }

/* The dock is fixed at z-index 90 and the drawer at 79, so the bubble floated on
   top of the full-screen nav — landing over the drawer's own "WhatsApp us" link.
   The drawer already carries that CTA, so the dock stands down while the menu is
   open instead of fighting it for the same corner. Both are children of <body>
   with .drawer first, which is what makes the sibling combinator reach it. */
.drawer.open ~ .wa { opacity: 0; visibility: hidden; pointer-events: none; }
/* the catalog's phone filter sheet owns the screen while it is open, and the
   dock would sit on top of its Show-results button */
body.sheet-open .wa { display: none; }

.wa__btn {
  position: relative;
  width: 58px;
  height: 58px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: #25D366;
  color: #062E13;
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.45);
  transition: transform 0.22s var(--ease);
}
.wa__btn:hover { transform: scale(1.06); }
.wa__btn svg { width: 30px; height: 30px; }

/* pulse ring — killed under reduced-motion by the global rule */
.wa__btn::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: #25D366;
  z-index: -1;
  animation: wa-pulse 2.6s var(--ease-in) infinite;
}
@keyframes wa-pulse {
  0%   { transform: scale(1);    opacity: 0.55; }
  70%  { transform: scale(1.75); opacity: 0; }
  100% { transform: scale(1.75); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .wa__btn::before { animation: none; opacity: 0; }
}

.wa__panel {
  width: min(300px, calc(100vw - 32px));
  padding: 8px;
  background: var(--ink-3);
  border: 1px solid var(--line-strong);
  box-shadow: 0 20px 50px rgba(0, 0, 0, 0.6);
  transform-origin: bottom right;
  transform: scale(0.94) translateY(8px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.2s var(--ease), transform 0.2s var(--ease), visibility 0.2s;
}
.wa__panel.open { opacity: 1; transform: none; visibility: visible; }

.wa__head {
  padding: 12px 14px 10px;
  font-family: var(--mono);
  font-size: var(--t-xs);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--mute);
}

.wa__row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 11px 14px;
  transition: background 0.16s var(--ease);
}
.wa__row:hover { background: rgba(37, 211, 102, 0.12); }
.wa__row svg { width: 19px; height: 19px; color: #25D366; flex: none; }
.wa__name { font-family: var(--display); font-weight: 700; font-size: 0.9375rem; letter-spacing: 0.01em; }
.wa__num  { display: block; font-family: var(--mono); font-size: var(--t-xs); color: var(--mute); }

/* ============================================================ footer */

.ftr {
  background: var(--ink-2);
  border-top: 1px solid var(--line);
  padding-block: clamp(56px, 7vw, 88px) 0;
}

.ftr__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1.2fr;
  gap: clamp(28px, 4vw, 56px);
  align-items: start;
}

.ftr__logo img { width: 176px; height: 45px; object-fit: contain; }
.ftr__blurb { margin-top: 18px; color: var(--mute); font-size: var(--t-sm); max-width: 34ch; }

/* These were --mute-dim while the links under them are --mute — the heading was
   literally fainter than its own contents, so each column read as one flat list
   with a stray label on top. White and heavier, with the torch rule the site
   uses on its eyebrows, so the rank is unmistakable. Same element on a phone,
   where the columns stack and the headings are the only thing separating them. */
.ftr__h {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--mono);
  font-size: var(--t-xs);
  font-weight: 600;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--white);
  margin-bottom: 18px;
}
.ftr__h::before {
  content: '';
  flex: none;
  width: 16px;
  height: 2px;
  background: var(--torch);
}

.ftr__li { padding: 6px 0; }
.ftr__li a { color: var(--mute); font-size: var(--t-sm); transition: color 0.18s var(--ease); }
.ftr__li a:hover { color: var(--torch); }

.ftr__contact { display: flex; flex-direction: column; gap: 11px; }
.ftr__contact a, .ftr__contact p { color: var(--mute); font-size: var(--t-sm); }
.ftr__contact a:hover { color: var(--white); }

/* icon + text rows: icon in a fixed gutter so the text lines up */
.ftr__addr, .ftr__mail { display: flex; align-items: flex-start; gap: 11px; }
.ftr__mail { align-items: center; }
.ftr__addr svg, .ftr__mail svg { width: 16px; height: 16px; flex: none; color: var(--torch); margin-top: 2px; }
.ftr__mail svg { margin-top: 0; }

.ftr__person { display: flex; align-items: center; gap: 11px; margin-top: 2px; }
.ftr__person svg { width: 16px; height: 16px; flex: none; color: #25D366; }
.ftr__person b { color: var(--white); font-weight: 600; }
.ftr__person span { font-family: var(--mono); font-size: var(--t-xs); margin-left: auto; }

.ftr__social { display: flex; gap: 8px; margin-top: 22px; }
.ftr__social a {
  width: 40px; height: 40px;
  display: grid; place-items: center;
  border: 1px solid var(--line);
  color: var(--mute);
  transition: color 0.18s var(--ease), border-color 0.18s var(--ease), background 0.18s var(--ease);
}
.ftr__social a:hover { color: var(--white); border-color: var(--torch); background: var(--torch-dim); }
.ftr__social svg { width: 18px; height: 18px; }

.ftr__base {
  margin-top: clamp(44px, 5vw, 68px);
  padding-block: 22px;
  border-top: 1px solid var(--line);
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.ftr__base p { font-size: var(--t-xs); color: var(--mute-dim); }
.ftr__base a { color: var(--mute); text-decoration: underline; text-underline-offset: 3px; }
.ftr__base a:hover { color: var(--torch); }

@media (max-width: 1024px) {
  .ftr__grid { grid-template-columns: 1fr 1fr; }
  .ftr__brand { grid-column: 1 / -1; }
}
@media (max-width: 560px) {
  /* single column — center everything for the phone footer */
  .ftr__grid { grid-template-columns: 1fr; text-align: center; }
  .ftr__brand { display: flex; flex-direction: column; align-items: center; }
  .ftr__blurb { margin-inline: auto; }
  .ftr__social { justify-content: center; }
  .ftr__contact { align-items: center; }
  .ftr__addr, .ftr__mail, .ftr__person { justify-content: center; align-items: center; }
  .ftr__addr svg, .ftr__mail svg { margin-top: 0; }
  .ftr__person span { margin-left: 0; }
  .ftr__base { flex-direction: column; align-items: center; text-align: center; }
}

/* ============================================================ lightbox */

.lb {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: grid;
  grid-template-rows: auto 1fr auto;
  background: rgba(6, 6, 7, 0.96);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.26s var(--ease), visibility 0.26s;
}
.lb.open { opacity: 1; visibility: visible; }

.lb__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  padding: 16px clamp(16px, 3vw, 28px);
}
.lb__count { font-family: var(--mono); font-size: var(--t-xs); letter-spacing: 0.14em; color: var(--mute); }

.lb__x {
  width: 44px; height: 44px;
  display: grid; place-items: center;
  border: 1px solid var(--line-strong);
  color: var(--white);
  transition: background 0.18s var(--ease), border-color 0.18s var(--ease);
}
.lb__x:hover { background: var(--torch); border-color: var(--torch); }
.lb__x svg { width: 20px; height: 20px; }

/* Flex, not grid. As a grid the single row sized itself to the image, so the
   image's own `max-height: 100%` resolved against the image — circular, and a
   tall shot spilled past the stage and out of the viewport. A flex item's
   percentage max-height resolves against the container's real height. */
.lb__stage {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  padding-inline: clamp(16px, 8vw, 96px);
  min-height: 0;
  overflow: hidden;
}
.lb__img {
  max-width: 100%;
  /* the stage already sits inside a 100vh fixed overlay, so 100% is the tighter
     of the two — the dvh keeps it honest if mobile browser chrome moves */
  max-height: min(100%, 100dvh);
  width: auto;
  height: auto;
  object-fit: contain;
}

.lb__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 52px; height: 52px;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, 0.07);
  border: 1px solid var(--line-strong);
  color: var(--white);
  transition: background 0.18s var(--ease);
}
.lb__nav:hover { background: var(--torch); }
.lb__nav svg { width: 22px; height: 22px; }
.lb__nav--prev { left: clamp(8px, 2vw, 26px); }
.lb__nav--next { right: clamp(8px, 2vw, 26px); }

.lb__cap {
  padding: 16px clamp(16px, 3vw, 28px) 26px;
  text-align: center;
  font-size: var(--t-sm);
  color: var(--mute);
  min-height: 3.2em;
}
.lb__cap b { display: block; color: var(--white); font-family: var(--display); font-weight: 700; font-size: var(--t-md); letter-spacing: -0.01em; }

body.lb-lock { overflow: hidden; }

/* Phone type scale, matching the token step-down in base.css. These headings set
   their own clamp() instead of using a --t- token, so they have to be stepped
   here too or they stay at desktop size while everything around them shrinks.
   Every number is the original x 0.9 — the vw coefficient included, so the type
   still grows with the viewport and the ramp keeps its original shape. */
@media (max-width: 767px) {
  .drawer__link { font-size: clamp(1.485rem, 7.2vw, 2.025rem); }
}
