/* JMD Menswear landing-page styles.
 * Source: /Users/creator/Downloads/JMD-Menswear-Landing-Page/jmd-menswear-landing-2.html
 * Token names and palette match docs/design/jmd-brand-context.md.
 */

:root {
  /* Brand palette */
  --navy:        #010092;
  --midnight:    #000846;
  --white:       #ffffff;
  --ink:         #090A18;
  --cotton:      #F7F7F4;
  --fitting:     #E7E7EA;
  --steel:       #8C8FA3;
  --steel-strong:#54576E; /* WCAG AA 4.5:1 on --cotton — used where --steel is too light */
  --silver:      #C9CBD6;
  --gold:        #C8A24A;
  --gold-deep:   #7A5D20; /* WCAG AA 4.5:1 on --cotton — used where --gold is too light on light bg */
  --rental:      #138A52;

  /* Look-tone accents (brand-context "additional draft colors") */
  --charcoal:    #2A2C33;
  --burgundy:    #4A1A1F;


  /* RGB channels for alpha treatments; keeps color values centralized in tokens. */
  --white-rgb: 255,255,255;
  --steel-rgb: 140,143,163;
  --gold-rgb: 200,162,74;
  --midnight-rgb: 0,8,70; /* channels of --midnight (#000846) for alpha overlays */

  /* Type stacks */
  --font-display: 'Libre Franklin', 'Helvetica Now Display', 'Helvetica Neue', Arial, sans-serif;
  --font-body:    'Inter', 'Libre Franklin', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono:    'JetBrains Mono', 'SFMono-Regular', ui-monospace, Menlo, monospace;
  --font-italic:  'Iowan Old Style', 'Charter', Georgia, serif;

  /* Type scale */
  --fs-xxs:   10px;
  --fs-xs:    11px;
  --fs-sm:    12px;
  --fs-md:    13px;
  --fs-base:  14px;
  --fs-body:  15px;
  --fs-lead:  16px;
  --fs-deck:  17px;
  --fs-card:  20px;
  --fs-look:  22px;
  --fs-section-title: clamp(34px, 6vw, 56px);
  --fs-quote:         clamp(34px, 7vw, 64px);
  --fs-headline:      clamp(48px, 11vw, 96px);

  /* Layout */
  --pad-x:    24px;
  --container: 1280px;
  --radius:   4px;
  --tap-min:  44px;

  /* Section rhythm */
  --section-pad-y: 72px;
  --hero-pad-top:  56px;
  --hero-pad-bot:  72px;
}

/* Reset / base */
*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--cotton);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-lead);
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }
button { font: inherit; }

/* Layout primitives */
.container { width: 100%; max-width: var(--container); margin: 0 auto; padding-inline: var(--pad-x); }
.display { font-family: var(--font-display); font-weight: 800; line-height: 1.0; letter-spacing: 0; margin: 0; }

/* 1. Announcement bar */
.announce {
  background: var(--midnight);
  color: var(--white);
  border-bottom: 1px solid rgba(var(--white-rgb),0.08);
  font-size: var(--fs-sm);
}
/* padding-block only: keep .container's inline gutter so the status dot/text aren't clipped at the edge */
.announce-row { display: flex; align-items: center; gap: 16px; padding-block: 9px; overflow: hidden; }
.announce-status {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-weight: 700;
  text-transform: uppercase;
  /* Mobile-first: tighter tracking keeps the live status line from wrapping
     to several rows on narrow screens. Restored to 0.12em at >=700px. */
  letter-spacing: 0.05em;
  font-size: var(--fs-xs);
}
/* Mobile-first: hide the secondary plaza message so it doesn't crowd and
   truncate beside the status line; the plaza name still appears in the store
   card and footer. Shown again at >=700px where the bar has room. */
.announce-pipe, .announce-msg { display: none; }
.status-dot {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: var(--steel);
  box-shadow: 0 0 0 3px rgba(var(--steel-rgb),0.18);
  /* Glow/halo is animated via box-shadow so the dot never changes its own
     box size — keeps the announce bar from shifting/clipping when state flips. */
  transition: background 200ms ease, box-shadow 200ms ease;
}
/* Open right now: glowing green light with a gentle pulse. */
.status-dot.is-open {
  background: #2FD27A;
  /* Static glow first (the cue kept under reduced motion), then the pulse. */
  box-shadow: 0 0 0 3px rgba(47,210,122,0.22), 0 0 6px 1px rgba(47,210,122,0.65);
  animation: status-dot-pulse 2.4s ease-in-out infinite;
}
/* Closed / not currently open: clearly red, no green glow. */
.status-dot.is-closed {
  background: #E5484D;
  box-shadow: 0 0 0 3px rgba(229,72,77,0.22);
}
@keyframes status-dot-pulse {
  0%, 100% { box-shadow: 0 0 0 3px rgba(47,210,122,0.22), 0 0 6px 1px rgba(47,210,122,0.55); }
  50%      { box-shadow: 0 0 0 4px rgba(47,210,122,0.30), 0 0 10px 2px rgba(47,210,122,0.80); }
}
.announce-pipe { width: 1px; height: 12px; background: rgba(var(--white-rgb),0.16); flex-shrink: 0; }
.announce-msg { color: rgba(var(--white-rgb),0.72); font-size: var(--fs-sm); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* 2. Sticky nav (issue #84: refined sticky bar + mobile menu, centered logo) */
.nav {
  background: var(--white);
  border-bottom: 1px solid var(--fitting);
  position: sticky;
  top: 0;
  z-index: 50;
  /* Subtle elevation that strengthens once the page is scrolled. The base
     shadow is barely-there; .is-scrolled (set by assets/js/nav.js) lifts it. */
  box-shadow: 0 1px 0 rgba(var(--steel-rgb), 0.06);
  transition: box-shadow 200ms ease, background 200ms ease;
}
.nav.is-scrolled {
  box-shadow: 0 6px 24px -16px rgba(0, 8, 70, 0.45);
}
/* Mobile-first: a compact sticky bar so it doesn't eat the small-screen viewport.
   The taller desktop treatment is restored at the >=700px breakpoint. */
/* padding-block only: keep .container's inline gutter so the logo and CTA don't bleed to the screen edge */
.nav-row { position: relative; z-index: 2; display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: 4px 12px; min-height: 72px; padding-block: 8px; overflow: visible; }
/* The .brand box is pinned to the bar's prior logo footprint so enlarging the
   logo (issue #100) never changes the navbar height: the box keeps the height
   the logo used to occupy, while the <img> renders ~12% larger and overflows
   the box symmetrically (centered + overflow visible). The extra pixels land in
   the row's existing padding, so header height and padding stay untouched. */
.brand { grid-column: 2; grid-row: 1; justify-self: center; display: flex; align-items: center; height: clamp(46px, 13vw, 60px); }
.brand img { height: clamp(58px, 16.1vw, 74px); width: auto; max-width: 100%; }
/* Progressive enhancement: the inline link row IS the navigation with no JS, at
   every width. On mobile (no JS) it wraps onto its own full-width row beneath the
   bar so the links stay reachable. nav.js sets `.nav-js` on <html>, which hands
   mobile off to the hamburger panel (see the max-width rule below). The toggle is
   hidden until then, so JS-off mobile never shows a dead control. */
.nav-links { grid-column: 1 / -1; grid-row: 2; justify-self: center; display: flex; flex-wrap: wrap; justify-content: center; gap: 4px 14px; font-size: var(--fs-sm); }
.nav-links a {
  text-transform: uppercase;
  letter-spacing: 0.12em;
  font-weight: 700;
  color: var(--ink);
  padding: 12px 4px;
  min-height: var(--tap-min);
  display: inline-flex;
  align-items: center;
  border-bottom: 2px solid transparent;
  transition: border-color 150ms ease;
}
.nav-links a:hover,
.nav-links a[aria-current="page"] { border-bottom-color: var(--navy); }
.nav-cta {
  grid-column: 3;
  grid-row: 1;
  justify-self: end;
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--navy);
  color: var(--white);
  border: 1px solid var(--navy);
  padding: 11px 14px;
  min-height: var(--tap-min);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  font-weight: 800;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background 180ms ease;
}
.nav-cta:hover { background: var(--midnight); }
/* Compact directions glyph for the icon-only CTA on the narrowest phones. Hidden
   by default — the text label is the CTA everywhere except <=360px (see below). */
.nav-cta-icon {
  display: none;
  width: 18px;
  height: 18px;
  background: currentColor;
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M8 2l5 11-5-2.4L3 13z" fill="black"/></svg>') center/contain no-repeat;
          mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 16 16"><path d="M8 2l5 11-5-2.4L3 13z" fill="black"/></svg>') center/contain no-repeat;
}

/* Mobile menu toggle (hamburger). Hidden until nav.js attaches (`.nav-js`), so a
   no-JS visitor never sees a dead control; revealed only below the desktop
   breakpoint, where it replaces the wrapping link row. 44px tap target. */
.nav-toggle {
  grid-column: 1;
  grid-row: 1;
  justify-self: start;
  display: none;
  align-items: center;
  justify-content: center;
  width: var(--tap-min);
  height: var(--tap-min);
  margin-inline-start: -10px; /* optically align the bars with the gutter */
  padding: 0;
  background: transparent;
  border: 0;
  color: var(--ink);
  cursor: pointer;
}
.nav-toggle-bars { position: relative; display: block; width: 22px; height: 16px; }
.nav-toggle-bars span {
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
  transition: transform 200ms ease, opacity 200ms ease, top 200ms ease;
}
.nav-toggle-bars span:nth-child(1) { top: 0; }
.nav-toggle-bars span:nth-child(2) { top: 7px; }
.nav-toggle-bars span:nth-child(3) { top: 14px; }
.nav.is-menu-open .nav-toggle-bars span:nth-child(1) { top: 7px; transform: rotate(45deg); }
.nav.is-menu-open .nav-toggle-bars span:nth-child(2) { opacity: 0; }
.nav.is-menu-open .nav-toggle-bars span:nth-child(3) { top: 7px; transform: rotate(-45deg); }

/* Backdrop scrim behind the open mobile panel. Sits above page content but
   below the sticky header row, so the logo + toggle stay visible and clickable. */
.nav-scrim {
  position: fixed;
  inset: 0;
  z-index: 1;
  background: rgba(0, 8, 70, 0.32);
  backdrop-filter: blur(2px);
  -webkit-backdrop-filter: blur(2px);
  opacity: 0;
  transition: opacity 200ms ease;
}
.nav.is-menu-open .nav-scrim { opacity: 1; }
.nav-scrim[hidden] { display: none; }

/* Compact rounded mobile panel, dropped just below the nav row (not a
   full-screen drawer). Premium feel via cream surface, hairline border, soft
   elevation — JMD tokens only. */
.nav-menu {
  position: absolute;
  z-index: 3;
  top: calc(100% + 8px);
  left: var(--pad-x);
  right: var(--pad-x);
  padding: 8px;
  background: var(--cotton);
  border: 1px solid var(--fitting);
  border-radius: 14px;
  box-shadow: 0 24px 48px -24px rgba(0, 8, 70, 0.55);
  display: flex;
  flex-direction: column;
  gap: 2px;
  transform-origin: top center;
  transform: translateY(-6px) scale(0.98);
  opacity: 0;
  transition: opacity 200ms ease, transform 200ms ease;
}
.nav.is-menu-open .nav-menu { transform: translateY(0) scale(1); opacity: 1; }
.nav-menu[hidden] { display: none; }
.nav-menu a {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  padding: 10px 14px;
  border-radius: 10px;
  color: var(--ink);
  font-size: var(--fs-md);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  transition: background 150ms ease, color 150ms ease;
}
.nav-menu a:hover { background: rgba(var(--steel-rgb), 0.14); }
.nav-menu a[aria-current="page"] { color: var(--navy); background: rgba(var(--steel-rgb), 0.14); }
.nav-menu-sep { height: 1px; margin: 6px 8px; background: var(--fitting); }
.nav-menu .nav-menu-cta {
  justify-content: center;
  background: var(--navy);
  color: var(--white);
  letter-spacing: 0.04em;
}
.nav-menu .nav-menu-cta:hover { background: var(--midnight); }
.nav-menu .nav-menu-call { color: var(--navy); }

/* Once nav.js attaches (`.nav-js` on <html>), hand mobile navigation off to the
   hamburger panel: hide the wrapping link row and reveal the toggle. Without JS
   this rule never applies, so the link row remains the navigation. */
@media (max-width: 819.98px) {
  .nav-js .nav-links { display: none; }
  .nav-js .nav-toggle { display: inline-flex; }
  /* True-center the logo on phones. The default `1fr auto 1fr` grid floors the
     CTA column at the (wide) Directions button but the toggle column at only the
     44px hamburger, which pushes the centered logo left. Mirroring the side
     columns (equal `minmax(0,1fr)` tracks) centers the auto-width brand column
     regardless of the toggle/CTA widths. The CTA is compacted (no arrow, tighter
     padding) to fit its mirrored track; the mobile panel still carries a
     full-width Directions button so the CTA stays easy to find. */
  .nav-row { grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr); }
  .nav-cta { padding-inline: 12px; }
  .nav-cta .btn-arrow { display: none; }
}

/* Narrowest phones: collapse the Directions CTA to an icon-only tap target so it
   can never collide with the centered logo. The full "Directions" text label is
   kept on every wider phone (361px+) and in the mobile panel's full-width button,
   so the action stays discoverable; here the aria-label ("Directions to JMD
   Menswear") carries the accessible name. An icon-only CTA is a fixed ~44px square
   regardless of label width, which guarantees clearance from the brand column at
   320px (the smallest width the navbar supports). */
@media (max-width: 360px) {
  .nav-row,
  .nav--floating .nav-row { padding-inline: 12px; }
  .brand { height: 38px; }
  .brand img { height: 47px; }
  .nav-cta {
    width: var(--tap-min);
    padding: 0;
    justify-content: center;
  }
  .nav-cta .nav-cta-label { display: none; }
  .nav-cta .nav-cta-icon { display: inline-block; }
}

/* ---------------------------------------------------------------------------
 * Production navbar treatment (issue #84 selection): a hybrid of the demo's
 * Option 2 (floating rounded shell) + Option 3 (desktop logo-left / links-right).
 * Applied via `class="nav nav--floating nav--split"`. Mobile keeps the shared
 * centered-logo + hamburger panel. These modifiers are inert without their class,
 * so they are safe to ship even while the demo options remain for comparison.
 * ------------------------------------------------------------------------ */

/* Floating rounded shell — the bar becomes a contained pill below the
   announcement bar, lifting further on scroll (Femme-inspired, JMD tokens). */
.nav--floating {
  background: transparent;
  border-bottom: 0;
  box-shadow: none;
  top: 12px;
  padding-block: 6px;
}
.nav--floating .nav-row {
  background: var(--white);
  border: 1px solid var(--fitting);
  border-radius: 18px;
  box-shadow: 0 14px 36px -22px rgba(0, 8, 70, 0.45);
  padding-inline: 20px;
  transition: box-shadow 200ms ease;
}
.nav--floating.is-scrolled .nav-row {
  box-shadow: 0 20px 44px -20px rgba(0, 8, 70, 0.6);
}
.nav--floating .nav-menu { top: calc(100% + 4px); }

/* Split composition is a DESKTOP concept: logo left, links right, CTA far right.
   Below 820px every layout collapses to the shared centered-logo + hamburger
   header, so these overrides apply only once the inline link row appears. */
@media (min-width: 820px) {
  .nav--split .nav-row { grid-template-columns: auto 1fr auto; }
  .nav--split .brand { grid-column: 1; justify-self: start; }
  .nav--split .nav-links { grid-column: 2; justify-self: end; }
  .nav--split .nav-cta { grid-column: 3; justify-self: end; }
}

/* Buttons / CTAs */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 14px 22px;
  border-radius: var(--radius);
  font-weight: 800;
  font-size: var(--fs-body);
  letter-spacing: 0.04em;
  text-transform: uppercase;
  border: 1px solid transparent;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease;
  min-height: 48px;
}
.btn-primary { background: var(--navy); color: var(--white); border-color: var(--navy); }
.btn-primary:hover { background: var(--midnight); border-color: var(--midnight); }
.btn-inverse { background: var(--white); color: var(--navy); border-color: var(--white); }
.btn-inverse:hover { background: rgba(var(--white-rgb),0.92); }
.btn-secondary { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn-secondary:hover { background: var(--navy); color: var(--white); }
.btn-ghost-light { background: transparent; color: var(--white); border-color: rgba(var(--white-rgb),0.4); }
.btn-ghost-light:hover { background: var(--white); color: var(--navy); border-color: var(--white); }
.btn-arrow {
  display: inline-block;
  width: 14px;
  height: 14px;
  background: currentColor;
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path d="M2 7h9.5M7.5 3l4 4-4 4" fill="none" stroke="black" stroke-width="1.6" stroke-linecap="square" stroke-linejoin="miter"/></svg>') center/contain no-repeat;
          mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path d="M2 7h9.5M7.5 3l4 4-4 4" fill="none" stroke="black" stroke-width="1.6" stroke-linecap="square" stroke-linejoin="miter"/></svg>') center/contain no-repeat;
}

/* 3. Hero */
.hero { background: var(--navy); color: var(--white); position: relative; overflow: hidden; }
.hero-eyebrow { border-bottom: 1px solid rgba(var(--white-rgb),0.14); padding: 14px 0; overflow: hidden; }
.hero-eyebrow-track-clip { overflow: hidden; }
.eyebrow-track {
  display: flex;
  align-items: center;
  gap: 28px;
  color: rgba(var(--white-rgb),0.88);
  font-family: var(--font-mono);
  /* Match the hero subcopy size (var(--fs-deck), see .hero-sub) per Karan's reference;
     heavier weight + tighter tracking keep the larger uppercase mono clean. */
  font-size: var(--fs-deck);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  white-space: nowrap;
  animation: marquee 38.9s linear infinite;
}
.eyebrow-track span { display: inline-flex; align-items: center; gap: 28px; flex-shrink: 0; }
.eyebrow-track span::after { content: ""; width: 3px; height: 3px; background: rgba(var(--white-rgb),0.45); border-radius: 50%; flex-shrink: 0; }
.eyebrow-track span:last-child::after { display: none; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }
/* padding-block only: keep .container's inline gutter so the headline/subcopy/CTAs don't bleed to the screen edge */
.hero-body { padding-block: var(--hero-pad-top) var(--hero-pad-bot); position: relative; }
.hero-kicker {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(var(--white-rgb),0.7);
  margin-bottom: 28px;
}
.hero-kicker::before { content: ""; width: 28px; height: 1px; background: rgba(var(--white-rgb),0.4); }
.hero-headline { font-size: var(--fs-headline); line-height: 0.94; letter-spacing: -0.005em; margin: 0 0 24px; max-width: 12ch; }
.hero-headline em { font-family: var(--font-italic); font-style: italic; font-weight: 400; color: rgba(var(--white-rgb),0.94); }
.hero-sub { font-size: var(--fs-deck); line-height: 1.55; color: rgba(var(--white-rgb),0.78); max-width: 38ch; margin: 0 0 32px; }
.hero-actions { display: flex; flex-direction: column; gap: 12px; margin-bottom: 36px; }
.hero-meta { display: flex; flex-direction: column; gap: 6px; font-family: var(--font-mono); font-size: var(--fs-sm); color: rgba(var(--white-rgb),0.6); letter-spacing: 0.03em; }
.hero-meta strong { color: var(--white); font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em; font-size: var(--fs-xs); }
.hero-hours-stack { display: flex; flex-direction: column; gap: 4px; align-items: flex-start; line-height: 1.45; }
.hero-mark { position: absolute; right: -48px; bottom: -120px; width: 60vw; max-width: 540px; opacity: 0.07; pointer-events: none; user-select: none; }

/* Section primitives */
.section { padding: var(--section-pad-y) 0; }
.section-cream { background: var(--cotton); }
.section-navy { background: var(--navy); color: var(--white); }
.section-head { display: flex; flex-direction: column; gap: 12px; margin-bottom: 40px; max-width: 56ch; }
.section-eyebrow {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.section-eyebrow::before { content: ""; width: 24px; height: 1px; background: var(--silver); }
.section-navy .section-eyebrow { color: rgba(var(--white-rgb),0.85); }
.section-navy .section-eyebrow::before { background: rgba(var(--white-rgb),0.6); }
.section-title { font-size: var(--fs-section-title); line-height: 1.02; letter-spacing: -0.005em; }
.section-deck { color: var(--steel-strong); font-size: var(--fs-deck); line-height: 1.55; margin: 0; max-width: 48ch; }
.section-navy .section-deck { color: rgba(var(--white-rgb),0.85); }

/* 4b. Custom-shoes spotlight (issue #175) — a standalone split-feature entry
 * point to the custom-shoes page. Mobile-first single column (copy/CTA before
 * the visual); balanced content-left / media-right split from 960px up. Reuses
 * existing navy/cream/gold tokens, .btn variants, and focus styles. */
.custom-shoes-feature__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 36px;
  align-items: center;
}
.custom-shoes-feature__content {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 20px;
  max-width: 52ch;
}
.custom-shoes-feature__title {
  font-size: var(--fs-section-title);
  line-height: 1.03;
  letter-spacing: -0.01em;
  margin: 0;
}
.custom-shoes-feature__deck {
  color: rgba(var(--white-rgb), 0.85);
  font-size: var(--fs-deck);
  line-height: 1.6;
  margin: 0;
  max-width: 46ch;
}
.custom-shoes-feature__cta { margin-top: 4px; }
.custom-shoes-feature__media {
  margin: 0;
  border: 1px solid rgba(var(--gold-rgb), 0.4);
  border-radius: var(--radius);
  background: var(--midnight);
  padding: 20px;
  overflow: hidden;
}
.custom-shoes-feature__img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  border-radius: var(--radius);
}
@media (min-width: 960px) {
  .custom-shoes-feature__grid {
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 56px;
  }
  .custom-shoes-feature__media { padding: 28px; }
}

/* 5. Limited / story */
.limited {
  background: var(--cotton);
  position: relative;
  overflow: hidden;
  border-top: 1px solid var(--fitting);
  border-bottom: 1px solid var(--fitting);
}
.limited::before, .limited::after { content: ""; position: absolute; left: 0; right: 0; height: 1px; background: var(--gold); opacity: 0.5; }
.limited::before { top: 0; }
.limited::after { bottom: 0; }
.limited-mark { position: absolute; right: -8%; top: 50%; transform: translateY(-50%); width: 56vw; max-width: 480px; opacity: 0.045; pointer-events: none; user-select: none; }
.limited-grid { display: grid; grid-template-columns: 1fr; gap: 32px; align-items: start; position: relative; z-index: 1; }
.limited-stamp {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  color: var(--gold-deep); /* WCAG AA 4.5:1 on cream; .limited section is on cream */
  display: inline-flex;
  align-items: center;
  gap: 12px;
}
.limited-stamp::before, .limited-stamp::after { content: ""; width: 24px; height: 1px; background: var(--gold-deep); }
.limited-quote {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-quote);
  line-height: 1.02;
  letter-spacing: -0.01em;
  margin: 0;
  color: var(--ink);
  max-width: 18ch;
}
.limited-quote em { font-family: var(--font-italic); font-style: italic; font-weight: 400; }
.limited-body { color: var(--ink); font-size: var(--fs-lead); line-height: 1.7; max-width: 52ch; }
.limited-body p { margin: 0 0 18px; }
.limited-body p:last-child { margin-bottom: 0; }
.limited-list { list-style: none; padding: 0; margin: 24px 0 0; display: grid; gap: 14px; }
.limited-list li {
  display: grid;
  grid-template-columns: 56px 1fr;
  gap: 16px;
  align-items: baseline;
  border-top: 1px solid var(--fitting);
  padding-top: 14px;
}
.limited-list li:first-child { border-top: none; padding-top: 0; }
.limited-list .num { font-family: var(--font-mono); font-size: var(--fs-xs); color: var(--gold-deep); letter-spacing: 0.18em; }
.limited-list .text { font-size: var(--fs-body); line-height: 1.5; color: var(--ink); }
.limited-list .text strong { display: block; font-family: var(--font-display); font-weight: 800; font-size: var(--fs-base); text-transform: uppercase; letter-spacing: 0.04em; margin-bottom: 2px; }

/* 5b. Showroom / try-on (issue #39) */
.showroom-points {
  list-style: none;
  padding: 0;
  margin: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 20px;
}
.showroom-point { border-top: 1px solid var(--fitting); padding-top: 18px; }
.showroom-point .num {
  display: block;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  letter-spacing: 0.18em;
  color: var(--gold-deep); /* WCAG AA 4.5:1 on cream */
  margin-bottom: 10px;
}
.showroom-point h3 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-card);
  line-height: 1.1;
  letter-spacing: -0.005em;
  margin: 0 0 8px;
}
.showroom-point p {
  margin: 0;
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
  font-size: var(--fs-body);
  line-height: 1.55;
}
.showroom-actions { display: flex; flex-direction: column; gap: 12px; margin-top: 40px; }

/* About page (issue #35) — extends the existing tokens/components; no new palette. */
.about-split { display: grid; grid-template-columns: 1fr; gap: 40px; align-items: start; }
.about-prose { color: var(--ink); font-size: var(--fs-lead); line-height: 1.7; max-width: 56ch; }
.about-prose p { margin: 0 0 18px; }
.about-prose p:last-child { margin-bottom: 0; }

/* Owner/team photo fallback + enhanced carousel mount. */
.about-photo { margin: 0; display: flex; flex-direction: column; gap: 14px; }
.about-photo-frame {
  position: relative;
  aspect-ratio: 4 / 5;
  background: var(--midnight);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.about-photo-frame::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  background: radial-gradient(120% 80% at 30% 25%, rgba(var(--gold-rgb),0.10) 0%, transparent 60%);
}
.about-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}
.about-photo-mark { width: 46%; max-width: 220px; opacity: 0.12; }
.about-photo-label {
  position: absolute;
  bottom: 16px;
  left: 16px;
  right: 16px;
  font-family: var(--font-mono);
  font-size: var(--fs-xxs);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(var(--white-rgb),0.6);
}
.about-photo-cap {
  font-size: var(--fs-base);
  line-height: 1.5;
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
  display: flex;
  flex-direction: column;
  gap: 8px;
  align-items: flex-start;
}

/* About owner/team photo right-fan carousel (issue #142).
   Empty data keeps the safe placeholder above; 1 approved image becomes a static
   frame; 2+ approved images fan only to the right. */
.about-owner-carousel {
  position: relative;
  display: block;
  container-type: inline-size;
  --owner-card-w: min(68vw, 340px);
  --owner-card-aspect: 4 / 5;
  outline: none;
}
.about-owner-carousel:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 6px;
  border-radius: 8px;
}
.about-owner-carousel__viewport {
  position: relative;
  min-height: calc(var(--owner-card-w) * 1.25 + 64px);
  overflow: hidden;
  touch-action: pan-y;
  cursor: grab;
}
.about-owner-carousel--single .about-owner-carousel__viewport,
.about-owner-carousel.is-dragging .about-owner-carousel__viewport { cursor: default; }
.about-owner-carousel:not(.about-owner-carousel--single).is-dragging .about-owner-carousel__viewport { cursor: grabbing; }
.about-owner-carousel__track { position: relative; min-height: inherit; }
.about-owner-carousel__slide {
  position: absolute;
  top: 14px;
  left: 50%;
  width: var(--owner-card-w);
  aspect-ratio: var(--owner-card-aspect);
  transform:
    translateX(-50%)
    translateX(var(--owner-fan-x, 0))
    translateY(var(--owner-fan-y, 0))
    scale(var(--owner-fan-scale, 1))
    rotate(var(--owner-fan-rotate, 0deg));
  transform-origin: 50% 88%;
  opacity: 1;
  pointer-events: none;
  transition: transform 420ms ease, opacity 420ms ease;
  will-change: transform, opacity;
}
.about-owner-carousel__slide.is-active { pointer-events: auto; }
.about-owner-carousel__slide.is-hidden { opacity: 0; }
.about-owner-carousel__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  border: 1px solid var(--fitting);
  border-radius: 12px;
  background: var(--midnight);
  box-shadow: 0 12px 34px rgba(9, 10, 24, 0.16);
  user-select: none;
}
.about-owner-carousel__slide.is-active .about-owner-carousel__img {
  box-shadow: 0 20px 52px rgba(9, 10, 24, 0.24);
}
.about-owner-carousel--single .about-owner-carousel__viewport,
.about-owner-carousel--single .about-owner-carousel__track { min-height: auto; }
.about-owner-carousel--single .about-owner-carousel__slide {
  position: static;
  width: 100%;
  max-width: 380px;
  margin-inline: auto;
  transform: none;
}
.about-owner-carousel__nav {
  position: absolute;
  top: calc(var(--owner-card-w) * 0.56);
  z-index: 40;
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  border: 1px solid var(--silver);
  border-radius: 999px;
  background: rgba(var(--white-rgb), 0.94);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease, transform 160ms ease;
}
.about-owner-carousel__nav:hover { border-color: var(--navy); background: var(--white); }
.about-owner-carousel__nav:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.about-owner-carousel__nav:active { transform: scale(0.94); }
.about-owner-carousel__nav--prev { left: 8px; }
.about-owner-carousel__nav--next { right: 8px; }
.about-owner-carousel__nav::before {
  content: "";
  width: 10px;
  height: 10px;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
}
.about-owner-carousel__nav--prev::before { transform: rotate(-135deg); margin-left: 4px; }
.about-owner-carousel__nav--next::before { transform: rotate(45deg); margin-right: 4px; }
.about-owner-carousel__status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}
@media (min-width: 560px) {
  .about-owner-carousel { --owner-card-w: min(78cqw, 380px); }
}
@media (min-width: 960px) {
  .about-owner-carousel { --owner-card-w: min(78cqw, 360px); }
  .about-owner-carousel__slide {
    left: 42%;
  }
}
@media (prefers-reduced-motion: reduce) {
  .about-owner-carousel__slide,
  .about-owner-carousel__nav {
    transition: none !important;
  }
}

/* Event / occasion keyword list (navy section). */
.about-events {
  list-style: none;
  margin: 0 0 40px;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.about-events li {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: rgba(var(--white-rgb),0.92);
  border: 1px solid rgba(var(--white-rgb),0.28);
  border-radius: 999px;
  padding: 8px 14px;
}

/* Blog / Formalwear Guide (issue #36) — extends existing tokens/components; no new palette. */

/* Guide list (index) */
.posts { display: grid; grid-template-columns: 1fr; gap: 24px; }
.post {
  background: var(--white);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  overflow: hidden;
  transition: border-color 200ms ease, transform 200ms ease;
}
.post:hover { border-color: var(--silver); transform: translateY(-2px); }
.post-link {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 24px 24px 26px;
  border-left: 3px solid var(--gold);
  height: 100%;
}
.post-tag {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--gold-deep); /* WCAG AA 4.5:1 on white */
}
.post-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-look);
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin: 0;
  color: var(--ink);
}
.post-excerpt { margin: 0; color: var(--steel-strong); font-size: var(--fs-body); line-height: 1.55; }
.post-cta {
  margin-top: 4px;
  color: var(--navy);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-md);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.post:hover .post-cta { color: var(--midnight); }

/* In-progress topics (no broken links) */
.posts-soon { margin-top: 48px; border-top: 1px solid var(--fitting); padding-top: 28px; }
.posts-soon-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-card);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  margin: 0 0 16px;
}
.posts-soon-list { margin: 0 0 16px; padding-left: 20px; color: var(--steel-strong); font-size: var(--fs-body); line-height: 1.7; }
.posts-soon-list a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.posts-soon-list a:hover { color: var(--midnight); }
.posts-soon-note { margin: 0; color: var(--steel-strong); font-size: var(--fs-body); }
/* WCAG SC 1.4.1: in-text links carry an underline, not color alone */
.posts-soon-note a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.posts-soon-note a:hover { color: var(--midnight); }

/* Service/event landing-page links (issue #107). */
.service-link-note { margin-bottom: 40px; }
.service-link-note a { color: inherit; text-decoration: underline; text-underline-offset: 2px; }
.service-link-note a:hover { color: var(--white); }
/* The white hover above assumes a DARK section (About §local is .section-navy).
   On a light section it would be ~1.1:1 on --cotton (WCAG 1.4.3), so scope the
   light-section hover to the site's in-text convention (#164 uses this block in
   .section-cream). */
.section-cream .service-link-note a:hover { color: var(--midnight); }

/* Article page */
.article-headline { font-size: clamp(40px, 9vw, 76px); max-width: 16ch; }
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
  margin-bottom: 32px;
}
.crumbs a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.crumbs a:hover { color: var(--midnight); }
.crumb-sep { color: var(--silver); }

.article-prose { max-width: 68ch; color: var(--ink); font-size: var(--fs-lead); line-height: 1.75; }
.article-prose p { margin: 0 0 22px; }
.article-prose h2 {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: clamp(24px, 4vw, 32px);
  line-height: 1.15;
  letter-spacing: -0.005em;
  margin: 40px 0 14px;
}
/* In-prose links: underline so they don't rely on color alone (WCAG SC 1.4.1) */
.article-prose a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.article-prose a:hover { color: var(--midnight); }
.article-more { margin: 36px 0 0; font-size: var(--fs-body); color: var(--steel-strong); }
.article-more a { color: var(--navy); text-decoration: underline; text-underline-offset: 2px; }
.article-more a:hover { color: var(--midnight); }

/* FAQ blocks on occasion/service pages (issue #129).
   Native <details>/<summary> accordion — question visible when collapsed,
   answer text present in the static DOM (no JS, no schema-only copy). */
.faq-list { margin: 0; border-top: 1px solid rgba(var(--steel-rgb), 0.4); }
.faq-item { border-bottom: 1px solid rgba(var(--steel-rgb), 0.4); }
.faq-q {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-card);
  line-height: 1.3;
  letter-spacing: -0.005em;
  color: var(--ink);
  margin: 0;
  padding: 20px 40px 20px 0;
  position: relative;
  cursor: pointer;
  list-style: none; /* hide default disclosure marker (Firefox/modern Chrome) */
}
.faq-q::-webkit-details-marker { display: none; } /* hide default marker (Safari/older WebKit) */
.faq-q::after {
  content: "+";
  position: absolute;
  right: 6px;
  top: 50%;
  transform: translateY(-50%);
  font-family: var(--font-body);
  font-size: 24px;
  font-weight: 400;
  line-height: 1;
  color: var(--steel-strong);
}
.faq-item[open] > .faq-q::after { content: "\2212"; } /* minus sign when expanded */
.faq-q:hover { color: var(--navy); }
.faq-q:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.faq-a { margin: 0; padding: 0 40px 20px 0; }

/* 6. Store / location */
.store-grid { display: grid; grid-template-columns: 1fr; gap: 32px; }
.store-card {
  background: rgba(var(--white-rgb),0.04);
  border: 1px solid rgba(var(--white-rgb),0.16);
  border-radius: 6px;
  padding: 28px 26px;
}
.store-card h3 { font-family: var(--font-display); font-weight: 800; font-size: var(--fs-card); margin: 0 0 18px; text-transform: uppercase; letter-spacing: 0.06em; }
.store-card .label {
  font-family: var(--font-mono);
  font-size: var(--fs-xxs);
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: rgba(var(--white-rgb),0.55);
  display: block;
  margin-bottom: 6px;
}
.store-card .value { font-size: var(--fs-lead); line-height: 1.45; color: var(--white); margin: 0 0 18px; }
.store-card .value-large {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-look);
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 0 0 18px;
}
.store-actions { display: flex; flex-direction: column; gap: 10px; margin-top: 8px; }
.store-actions--lg-gap { margin-top: 24px; }

/* Option 2: Weekly rows — The Hours card (issue #34) */
.week-list { display: grid; gap: 8px; margin: 0 0 18px; }
.week-row { display: grid; grid-template-columns: 34px 1fr; gap: 12px; align-items: center; }
.day {
  font: 800 11px/1 var(--font-mono);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: rgba(var(--white-rgb),0.55);
}
.bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  border: 1px solid rgba(var(--white-rgb),0.12);
  border-radius: 999px;
  padding: 8px 12px;
  color: rgba(var(--white-rgb),0.9);
}
.bar.is-open { background: rgba(var(--white-rgb),0.08); border-color: rgba(var(--white-rgb),0.22); }
.bar.is-today { background: var(--white); color: var(--navy); border-color: var(--white); font-weight: 850; }
.bar small {
  font: 700 10px/1 var(--font-mono);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  opacity: 0.72;
}

/* Find Us branded mini-map (issue #153). Decorative aria-hidden container for a
   location-true schematic locator, styled to resemble the attached PR #158 reference
   map. This element paints the base navy wash + a faint, UNLABELLED street-grid
   texture; the map itself is the inline SVG in index.html (red/pink Conyers Exchange /
   JMD plaza footprint like the reference's selected-place mass, Hwy 138 SE as a
   prominent lower arterial with traffic arrows, muted-blue surrounding roads, a
   blue/purple Hobby Lobby big-box, an internal parking-lane grid, amber POI tiles, and
   a branded gold pin seated on the JMD storefront INSIDE the plaza north of Hwy 138 SE).
   Only real, map-verified facts are labelled (see the HTML comment + docs/spec.md
   §4.6/§7). No exact coordinates, no imagery, no runtime deps — positions are
   relative/approximate, never geospatial. */
.map-locator {
  position: relative;
  /* Width-driven sizing: fill the card and let aspect-ratio derive the height so the
     locator always shrinks with the card. A fixed `min-height` here transfers a minimum
     WIDTH through `aspect-ratio` (220px * 5/4 = 275px), which propagates up to the
     `.store-card` grid item and overflows the Find Us card + document on <=374px phones
     (issue #153 review). `min-width: 0` stops the locator from forcing that intrinsic
     minimum onto the card. The floor only ever engaged on narrow single-column mobile —
     tablet/desktop card widths already yield >=220px from the ratio — so dropping it
     leaves Karan's mini-map design and labels unchanged everywhere it was visible. */
  width: 100%;
  min-width: 0;
  aspect-ratio: 5 / 4;
  border: 1px solid rgba(var(--white-rgb),0.16);
  border-radius: 10px;
  overflow: hidden;
  margin-top: 8px;
  /* Base navy wash + a faint, UNLABELLED street-grid texture behind the SVG. */
  background:
    radial-gradient(120% 90% at 30% 18%, rgba(var(--white-rgb),0.05) 0%, transparent 55%),
    linear-gradient(160deg, var(--navy) 0%, var(--midnight) 100%),
    repeating-linear-gradient(0deg, transparent 0, transparent 23px, rgba(var(--white-rgb),0.04) 23px, rgba(var(--white-rgb),0.04) 24px),
    repeating-linear-gradient(90deg, transparent 0, transparent 23px, rgba(var(--white-rgb),0.04) 23px, rgba(var(--white-rgb),0.04) 24px);
  box-shadow: inset 0 0 0 1px rgba(var(--white-rgb),0.03), 0 10px 30px -18px rgba(0,0,0,0.55);
}
/* Location-true schematic mini-map, rendered as inline SVG. Coordinates are in the
   320x256 viewBox; positions are RELATIVE/approximate (from Google Maps / the PR #158
   reference), never geospatial. Brand tokens (navy/gold/white) drive the pin, labels,
   compass and pill; the reference-map fills below (red/pink plaza highlight, blue/purple
   big-box, muted-blue roads, amber POI tiles) are schematic MAP colours — deliberately
   NOT brand tokens — so they live as scoped `--map-*` variables here, not in :root. */
.map-svg {
  display: block; width: 100%; height: 100%;
  --map-road-rgb: 150,170,205;    /* muted blue roads + arterial */
  --map-jmd-rgb: 214,84,78;       /* red/pink selected-place plaza highlight (reference) */
  --map-anchor-rgb: 122,120,206;  /* blue/purple Hobby Lobby big-box (reference) */
  --map-amber-rgb: 224,158,74;    /* amber POI category tiles/dots (reference) */
}

/* Conyers Exchange / JMD plaza footprint — red/pink highlight like the reference mass. */
.map-svg__footprint--jmd {
  fill: rgba(var(--map-jmd-rgb),0.26);
  stroke: rgba(var(--map-jmd-rgb),0.72);
  stroke-width: 1.2;
  stroke-linejoin: round;
}
/* Hobby Lobby big-box — blue/purple footprint east of JMD. */
.map-svg__footprint--anchor {
  fill: rgba(var(--map-anchor-rgb),0.24);
  stroke: rgba(var(--map-anchor-rgb),0.55);
  stroke-width: 1;
}
/* Decorative building/parking blocks (unlabelled texture). */
.map-svg__block { fill: rgba(var(--white-rgb),0.05); stroke: rgba(var(--white-rgb),0.08); stroke-width: 1; }
.map-svg__block--blue { fill: rgba(var(--map-anchor-rgb),0.12); stroke: rgba(var(--map-anchor-rgb),0.2); }

/* Roads: muted blue. The labelled arterial is Hwy 138 SE; others are verified nearby streets. */
.map-svg__road { fill: none; stroke: rgba(var(--map-road-rgb),0.16); stroke-width: 5; stroke-linecap: round; stroke-linejoin: round; }
.map-svg__road--secondary     { stroke: rgba(var(--map-road-rgb),0.22); stroke-width: 7; }
.map-svg__road--drive         { stroke: rgba(var(--map-road-rgb),0.14); stroke-width: 4; }
.map-svg__road--arterial-base { stroke: rgba(var(--map-road-rgb),0.34); stroke-width: 16; }
.map-svg__road--arterial      { stroke: rgba(var(--map-road-rgb),0.2);  stroke-width: 11; }
/* Hwy 138 SE traffic-flow arrows. */
.map-svg__arrow { fill: none; stroke: rgba(var(--white-rgb),0.34); stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }
/* Internal parking aisles inside the plaza. */
.map-svg__aisle { fill: none; stroke: rgba(var(--white-rgb),0.09); stroke-width: 1; }

/* Branded gold pin marking the JMD storefront (the map's hero marker). */
.map-svg__pin { fill: var(--gold); stroke: var(--white); stroke-width: 2; stroke-linejoin: round; }
.map-svg__pin-dot { fill: var(--navy); }

/* POI markers: muted blue place dots + amber category tiles (Starbucks / Chick-fil-A). */
.map-svg__poi      { fill: rgba(var(--map-anchor-rgb),0.5); stroke: rgba(var(--white-rgb),0.35); stroke-width: 1; }
.map-svg__poi-tile { fill: rgba(var(--map-amber-rgb),0.9); }
.map-svg__poi-glyph { fill: none; stroke: var(--midnight); stroke-width: 1.1; stroke-linecap: round; stroke-linejoin: round; }
.map-svg__poi-dot  { fill: rgba(var(--map-amber-rgb),0.85); }

/* Compass + locale pill. */
.map-svg__compass-ring   { fill: rgba(var(--midnight-rgb),0.5); stroke: rgba(var(--white-rgb),0.2); stroke-width: 1; }
.map-svg__compass-needle { fill: var(--gold); }
.map-svg__pill     { fill: rgba(var(--midnight-rgb),0.72); stroke: rgba(var(--white-rgb),0.18); stroke-width: 1; }
.map-svg__pill-dot { fill: var(--gold); }

/* Labels. Halo (paint-order stroke) keeps text legible over the map. */
.map-svg text { font-family: var(--font-mono); }
.map-svg__label--road {
  font-size: 11px; font-weight: 700; letter-spacing: 0.5px; text-transform: uppercase;
  fill: rgba(var(--white-rgb),0.72);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.85); stroke-width: 2.6px; stroke-linejoin: round;
}
.map-svg__label--arterial {
  font-size: 13px; font-weight: 800; letter-spacing: 0.8px; text-transform: uppercase;
  fill: rgba(var(--white-rgb),0.9);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.92); stroke-width: 3.4px; stroke-linejoin: round;
}
.map-svg__label--plaza {
  font-family: var(--font-display); font-size: 8.5px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;
  fill: var(--gold);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.8); stroke-width: 2.4px; stroke-linejoin: round;
}
.map-svg__label--anchor {
  font-family: var(--font-display); font-size: 10px; font-weight: 800; letter-spacing: 0.4px; text-transform: uppercase;
  fill: rgba(var(--white-rgb),0.85);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.85); stroke-width: 2.6px; stroke-linejoin: round;
}
.map-svg__label--landmark {
  font-size: 8.5px; font-weight: 700; letter-spacing: 0.2px; fill: rgba(var(--white-rgb),0.74);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.8); stroke-width: 2.2px; stroke-linejoin: round;
}
.map-svg__label--jmd {
  font-family: var(--font-display); font-size: 10.5px; font-weight: 800; letter-spacing: 0.5px; text-transform: uppercase;
  fill: var(--white);
  paint-order: stroke; stroke: rgba(var(--midnight-rgb),0.92); stroke-width: 3.2px; stroke-linejoin: round;
}
.map-svg__label--pill { font-size: 9.5px; font-weight: 700; letter-spacing: 0.4px; text-transform: uppercase; fill: rgba(var(--white-rgb),0.85); }
.map-svg__label--compass { font-size: 9px; font-weight: 800; fill: rgba(var(--white-rgb),0.75); }

/* 8. Footer */
.foot {
  background: var(--midnight);
  color: rgba(var(--white-rgb),0.7);
  border-top: 1px solid rgba(var(--white-rgb),0.08);
  padding: 36px 0 28px;
  font-size: var(--fs-md);
}
.foot-row { display: flex; flex-direction: column; gap: 24px; align-items: flex-start; }
.foot-mark { display: flex; align-items: center; gap: 10px; }
.foot-mark img { height: 22px; width: auto; }
.foot-mark span { font-family: var(--font-display); font-weight: 800; font-size: var(--fs-md); letter-spacing: 0.18em; text-transform: uppercase; color: var(--white); }
.foot-line { font-family: var(--font-mono); font-size: var(--fs-sm); line-height: 1.6; color: rgba(var(--white-rgb),0.55); }
/* WCAG SC 1.4.1: in-line links in a text block must not rely on color alone */
.foot-line a { color: rgba(var(--white-rgb),0.85); text-decoration: underline; text-underline-offset: 2px; }
.foot-line a:hover { color: var(--white); }
.foot-social { display: flex; flex-wrap: wrap; gap: 6px 20px; }
.foot-social a {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(var(--white-rgb),0.7);
  text-decoration: none;
  /* Comfortable mobile tap target without changing the footer's visual height much */
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding-block: 2px;
}
.foot-social a:hover { color: var(--white); }
.foot-meta { font-family: var(--font-mono); font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: 0.16em; color: rgba(var(--white-rgb),0.72); }

/* Skip link (WCAG 2.4.1): off-screen until focused, then anchored top-left. */
.skip-link {
  position: absolute;
  left: var(--pad-x);
  top: -56px;
  z-index: 100;
  background: var(--navy);
  color: var(--white);
  padding: 12px 18px;
  border-radius: var(--radius);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-md);
  letter-spacing: 0.06em;
  text-transform: uppercase;
  transition: top 150ms ease;
}
.skip-link:focus { top: 12px; }

/* Visible focus state on every interactive element.
 * Two adjacent brand-color rings so the indicator clears WCAG 2.2 SC 1.4.11
 * (≥3:1 against the adjacent background) on BOTH light and dark sections:
 *   - gold (#C8A24A) is only ~2.4:1 on white but ~6:1 on navy,
 *   - navy (#010092) is ~15:1 on white but invisible on navy.
 * The navy box-shadow fills the outline-offset gap as an inner ring, gold the
 * outer ring; whichever background the element sits on, one ring meets 3:1.
 * The outline (not box-shadow) is what survives Windows High Contrast / forced-colors. */
a:focus-visible,
button:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 2px;
  box-shadow: 0 0 0 2px var(--navy);
}

/* Focus not obscured (WCAG 2.4.11): the nav is sticky, so jumping to an in-page
 * anchor (skip link, nav links) must leave the target clear of the sticky bar. */
main[id],
section[id] { scroll-margin-top: 88px; }

/* Breakpoints — mobile first */
@media (min-width: 700px) {
  :root { --pad-x: 40px; }
  /* Restore the fuller desktop announcement bar and sticky nav. */
  .announce-status { letter-spacing: 0.12em; }
  .announce-pipe, .announce-msg { display: revert; }
  .nav-row { gap: 4px 16px; min-height: 112px; padding-block: 10px; }
  .brand { height: clamp(76px, 16vw, 104px); }
  .brand img { height: clamp(85px, 18vw, 116px); }
  .nav-cta { padding: 12px 16px; font-size: var(--fs-md); }
  .hero-actions { flex-direction: row; align-items: center; }
  .hero-actions .btn { min-width: 200px; }
  .posts { grid-template-columns: repeat(2, 1fr); }
  .showroom-points { grid-template-columns: repeat(3, 1fr); gap: 32px; }
  .showroom-actions { flex-direction: row; align-items: center; }
  .showroom-actions .btn { min-width: 200px; }
  .on-the-floor__actions { gap: 16px; }
  .on-the-floor__actions .btn { min-width: 200px; }
  /* Reviews: fixed card width on wider screens is declared after the review base rules. */
  .reviews__actions { gap: 16px; }
  .reviews__actions .btn { min-width: 200px; }
  .limited-grid { grid-template-columns: 1.1fr 1fr; gap: 56px; align-items: center; }
  .store-grid { grid-template-columns: 1fr 1fr; }
  .foot-row { flex-direction: row; align-items: center; justify-content: space-between; gap: 24px; }
  /* Sticky nav grows to 112px here; keep anchor targets clear of it (WCAG 2.4.11). */
  main[id],
  section[id] { scroll-margin-top: 128px; }
}

@media (min-width: 960px) {
  /* About split (issue #35). Source order is photo-first (issue #148) so the photo
     stacks above the "Who we are" copy on mobile single-column layouts. Here the two
     columns are grid-placed explicitly to restore the desktop text-left (wider 1.3fr) /
     photo-right split — relying on source order alone would reverse it. */
  .about-split { grid-template-columns: 1.3fr 1fr; gap: 56px; }
  .about-split .about-split-text { grid-column: 1; grid-row: 1; }
  .about-split .about-photo { grid-column: 2; grid-row: 1; }
}

@media (min-width: 820px) {
  /* Desktop: the inline link row returns to a single row. Default placement is
     logo-left links (col 1); the .nav--split modifier above moves it to the
     right. The mobile toggle/panel are retired. */
  .nav-links { display: flex; flex-wrap: nowrap; grid-column: 1; grid-row: 1; justify-self: start; }
  .nav-toggle { display: none; }
  .nav-menu,
  .nav-scrim { display: none !important; }
}

@media (min-width: 1024px) {
  :root {
    --pad-x: 64px;
    --section-pad-y: 96px;
    --hero-pad-top: 88px;
    --hero-pad-bot: 120px;
  }
  .hero-mark { right: -60px; bottom: -160px; max-width: 700px; opacity: 0.08; }
  .store-grid { grid-template-columns: 1.1fr 1fr 1fr; gap: 24px; }
  .service-links.posts { grid-template-columns: repeat(3, 1fr); }
  .limited-mark { max-width: 620px; }
}

/* Reduced motion: disable marquee and long transitions */
@media (prefers-reduced-motion: reduce) {
  .eyebrow-track { animation: none; }
  *, *::before, *::after {
    transition-duration: 0ms !important;
    animation-duration: 0ms !important;
    animation-iteration-count: 1 !important;
  }
}

/* ===========================================================================
 * On the Floor card carousel (issue #77 / JMD-28)
 * Reusable, dependency-free showroom carousel. Markup + behaviour live in
 * site/assets/js/card-carousel.js. Coverflow-style stage: the active card is
 * centred and full size; neighbours peek, scaled down and dimmed. Position,
 * scale, opacity and depth are all driven by the per-slide --offset / --abs
 * custom properties the script sets. The global prefers-reduced-motion rule
 * above already neutralises the transitions below.
 * ======================================================================== */
.card-carousel {
  /* Tunables */
  --cc-card-w: clamp(220px, 70vw, 320px);
  --cc-step:   clamp(150px, 40vw, 280px); /* horizontal gap between neighbours */
  --cc-aspect: 4 / 5;

  position: relative;
  width: 100%;
  max-width: 960px;
  margin-inline: auto;
  outline: none;
}
.card-carousel:focus-visible { outline: 2px solid var(--navy); outline-offset: 6px; border-radius: 6px; }

.card-carousel__viewport {
  position: relative;
  height: calc(var(--cc-card-w) * 5 / 4 + 24px);
  overflow: hidden;
  perspective: 1200px;
  /* Own horizontal drags for swipe; keep vertical page scroll smooth. */
  touch-action: pan-y;
  cursor: grab;
}
.card-carousel:not(.card-carousel--single) .card-carousel__viewport:active,
.card-carousel.is-dragging .card-carousel__viewport { cursor: grabbing; }
.card-carousel--single .card-carousel__viewport { cursor: default; }
.card-carousel__track { position: relative; width: 100%; height: 100%; }

.card-carousel__slide {
  position: absolute;
  top: 50%;
  left: 50%;
  width: var(--cc-card-w);
  aspect-ratio: var(--cc-aspect);
  transform:
    translate(-50%, -50%)
    translateX(calc(var(--offset) * var(--cc-step)))
    scale(calc(1 - var(--abs) * 0.12));
  opacity: max(0, calc(1 - var(--abs) * 0.4));
  z-index: calc(100 - var(--abs));
  transition: transform 500ms ease, opacity 500ms ease;
  will-change: transform, opacity;
}
/* Only the active card is interactive; neighbours are visual context. */
.card-carousel__slide { pointer-events: none; }
.card-carousel__slide.is-active { pointer-events: auto; }

.card-carousel__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  border-radius: 12px;
  background: var(--fitting);
  box-shadow: 0 8px 30px rgba(9, 10, 24, 0.12);
  user-select: none;
}
.card-carousel__slide.is-active .card-carousel__img {
  box-shadow: 0 18px 50px rgba(9, 10, 24, 0.22);
}
/* Zoomable mode (#101): the active photo is the lightbox trigger — signal it
   with a zoom-in cursor and a clear keyboard focus ring. */
.card-carousel--zoomable .card-carousel__slide.is-active .card-carousel__img {
  cursor: zoom-in;
}
.card-carousel--zoomable .card-carousel__img:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 4px;
}

/* Single-image mode: no stage, just the framed photo. */
.card-carousel--single .card-carousel__viewport { height: auto; }
.card-carousel--single .card-carousel__slide {
  position: static;
  transform: none;
  opacity: 1;
  margin-inline: auto;
}

/* Navigation arrows */
.card-carousel__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 200;
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  border: 1px solid var(--silver);
  border-radius: 50%;
  background: rgba(var(--white-rgb), 0.92);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 160ms ease, background 160ms ease, transform 160ms ease;
}
.card-carousel__nav:hover { border-color: var(--navy); }
.card-carousel__nav:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.card-carousel__nav:active { transform: translateY(-50%) scale(0.94); }
.card-carousel__nav--prev { left: 4px; }
.card-carousel__nav--next { right: 4px; }
.card-carousel__nav::before {
  content: "";
  width: 10px;
  height: 10px;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
}
.card-carousel__nav--prev::before { transform: rotate(-135deg); margin-left: 4px; }
.card-carousel__nav--next::before { transform: rotate(45deg); margin-right: 4px; }
@media (min-width: 720px) {
  .card-carousel__nav--prev { left: 12px; }
  .card-carousel__nav--next { right: 12px; }
}

/* Controls row: play/pause + pagination dots */
.card-carousel__controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  margin-top: 12px;
}
.card-carousel__playpause {
  position: relative;
  width: 32px;
  height: 32px;
  flex: none;
  /* Flex (not grid) so the two pause bars lay out side-by-side. Grid auto-flow
     stacked the ::before/::after bars into separate rows -> a top/bottom glyph
     instead of the standard two vertical bars (#95). */
  display: flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--silver);
  border-radius: 50%;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
}
.card-carousel__playpause:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
/* Pause glyph (two bars) shown while playing */
.card-carousel__playpause::before,
.card-carousel__playpause::after {
  content: "";
  width: 3px;
  height: 11px;
  background: currentColor;
}
.card-carousel__playpause::before { margin-right: 3px; }
/* Play glyph (triangle) shown while paused */
.card-carousel__playpause.is-paused::before { display: none; }
.card-carousel__playpause.is-paused::after {
  width: 0;
  height: 0;
  background: transparent;
  border-top: 6px solid transparent;
  border-bottom: 6px solid transparent;
  border-left: 10px solid currentColor;
  margin-left: 2px;
}

.card-carousel__dots {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
  justify-content: center;
}
.card-carousel__dot {
  width: 9px;
  height: 9px;
  padding: 0;
  border: 0;
  border-radius: 50%;
  background: var(--silver);
  cursor: pointer;
  transition: background 160ms ease, transform 160ms ease;
}
.card-carousel__dot:hover { background: var(--steel); }
.card-carousel__dot.is-active { background: var(--navy); transform: scale(1.3); }
.card-carousel__dot:focus-visible { outline: 2px solid var(--navy); outline-offset: 3px; }

/* Capped, rolling indicator for >3 images (#95): the dots are presentational
   progress markers (a fixed window of 3), not a tab-per-slide list, so they
   take no pointer/hover interaction. Real navigation stays on the arrows,
   keyboard, swipe, and the announced "Slide X of N" status. */
.card-carousel__dots--capped .card-carousel__dot { pointer-events: none; cursor: default; }

/* Visually-hidden live-region status */
.card-carousel__status {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

/* ===========================================================================
 * Showroom photo lightbox (issue #101)
 * Opt-in enlarged view for the On the Floor carousel. Created in the document
 * body by site/assets/js/card-carousel.js, so it overlays the whole viewport
 * free of the carousel's clipping/stacking context. Background scroll is locked
 * via the .jmd-lightbox-lock class while it's open.
 * ======================================================================== */
.jmd-lightbox-lock { overflow: hidden; }

.jmd-lightbox {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
  background: rgba(9, 10, 24, 0.92);
  opacity: 0;
  transition: opacity 200ms ease;
}
.jmd-lightbox.is-open { opacity: 1; }
.jmd-lightbox[hidden] { display: none; }

/* Centering frame for the photo + close control. */
.jmd-lightbox__stage {
  position: relative;
  display: flex;
  max-width: min(96vw, 1200px);
  max-height: 90vh;
}
.jmd-lightbox__img {
  display: block;
  max-width: 100%;
  max-height: 90vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: 10px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.55);
  background: var(--fitting);
}

/* Circular X, anchored to the photo's top-right corner. */
.jmd-lightbox__close {
  position: absolute;
  top: -14px;
  right: -14px;
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--silver);
  border-radius: 50%;
  background: rgba(var(--white-rgb), 0.96);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 160ms ease, transform 160ms ease;
}
.jmd-lightbox__close:hover { border-color: var(--navy); }
.jmd-lightbox__close:focus-visible { outline: 2px solid var(--white); outline-offset: 3px; }
.jmd-lightbox__close:active { transform: scale(0.94); }
.jmd-lightbox__close::before,
.jmd-lightbox__close::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 2px;
  background: currentColor;
}
.jmd-lightbox__close::before { transform: rotate(45deg); }
.jmd-lightbox__close::after { transform: rotate(-45deg); }

/* On small screens keep the X fully on-screen (corners can clip off the photo
   when it's narrower than the viewport). */
@media (max-width: 520px) {
  .jmd-lightbox { padding: 12px; }
  .jmd-lightbox__close { top: 6px; right: 6px; }
}

/* ===========================================================================
 * On the Floor — live showroom photo section (issue #63 / JMD-28)
 * Wraps the card carousel (above) as the website's Sanity-fed photo feed.
 * Two presentation states share the same markup:
 *   - photos present  -> #on-the-floor-carousel is populated and shown; the
 *                         static fallback text is hidden (.has-photos on section).
 *   - no photos / no JS / images failed -> carousel root stays empty (hidden via
 *                         :empty) and the static "visit us" fallback stays.
 * The "Visit the showroom" CTA below is persistent across both states.
 * ======================================================================== */
.on-the-floor .section-head { margin-inline: auto; text-align: center; align-items: center; }
.on-the-floor .section-deck { text-align: center; }

/* Until an image actually loads (and with no JS) the carousel root is empty —
 * keep it out of the layout so it never adds blank space above the fallback. */
#on-the-floor-carousel:empty { display: none; }

/* No-JS / crawler-visible static projection (issue #108). Real showroom <img>
 * elements rendered in the initial HTML so the photos are discoverable without
 * JS. .has-photos (the JS carousel actually mounted, after probing that the
 * images load) hides this grid so nothing shows twice. We deliberately do NOT
 * hide the static "visit us" fallback just because this markup exists: with no
 * JS, CSS cannot tell whether these <img> actually rendered, so hiding the
 * fallback on mere presence would leave a broken-image grid with no graceful
 * text whenever the URLs 404 (e.g. an offline fixture build writing jmd/dev
 * URLs). The fallback is therefore retired only by .has-photos (below), i.e.
 * only once an image has genuinely loaded. */
.on-the-floor__static {
  list-style: none;
  margin: 0 auto;
  padding: 0;
  max-width: 720px;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px;
}
.on-the-floor__static-item { margin: 0; }
.on-the-floor__static-photo {
  display: block;
  width: 100%;
  height: 100%;
  /* Mirror the carousel's 4 / 5 crop for a uniform grid. --cc-aspect is scoped
     to .card-carousel and does not cascade to this no-JS grid, so carry the
     literal here (the var stays as a courtesy match if it's ever in scope). */
  aspect-ratio: var(--cc-aspect, 4 / 5);
  object-fit: cover;
  object-position: center center;
  border-radius: 12px;
  background: var(--fitting);
}
.on-the-floor.has-photos .on-the-floor__static { display: none; }

@media (min-width: 700px) {
  .on-the-floor__static { grid-template-columns: repeat(3, 1fr); max-width: 900px; }
}

/* Static fallback text / graceful empty state. Hidden once real photos mount. */
.on-the-floor__fallback {
  max-width: 48ch;
  margin-inline: auto;
  text-align: center;
}
.on-the-floor.has-photos .on-the-floor__fallback { display: none; }
.on-the-floor__fallback-lead {
  font-size: var(--fs-card);
  color: var(--ink);
  margin: 0 0 8px;
}
/* No-JS contradiction guard (issue #108): when the static projection above
 * rendered real showroom photos, the "photos are on their way" lead would
 * contradict them. The generator emits the .on-the-floor__static <ul> ONLY for a
 * non-empty feed (renderStaticProjection returns "" otherwise), so its presence
 * as a preceding sibling is a JS-free signal that photos are shown -- hide just
 * the lead, keeping the state-agnostic sub-copy (and the persistent CTAs below)
 * as a caption and as a graceful fallback if any image URL 404s. With an empty
 * feed there is no <ul>, so the full "on their way" fallback still shows. */
.on-the-floor__static + .on-the-floor__fallback .on-the-floor__fallback-lead {
  display: none;
}
.on-the-floor__fallback-sub {
  color: var(--steel-strong);
  font-size: var(--fs-deck);
  line-height: 1.55;
  margin: 0;
}

/* Persistent showroom CTA — shown in both the photo and empty states. */
.on-the-floor__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 32px;
}

/* ===========================================================================
 * Customer reviews / testimonials (issue #112)
 * A horizontal, scroll-snap row of review cards adapting the "testimonials-
 * stars" pattern (gold stars, short quote, attribution) to JMD's navy / gold /
 * cotton system. Lives on cotton (between #showroom and #find); white cards with
 * a hairline border + soft shadow read as premium against it.
 * Two presentation states share the same markup:
 *   - reviews present -> #reviews-carousel is populated and shown; the static
 *                        no-data fallback is hidden (.has-reviews on section).
 *   - no data / no JS / no safe entries -> carousel root stays empty (hidden via
 *                        :empty) and the graceful fallback text stays.
 * No autoplay (manual scroll + buttons), so prefers-reduced-motion is honoured;
 * smooth scrolling is gated in assets/js/testimonials.js.
 * ======================================================================== */
.reviews .section-head { margin-inline: auto; text-align: center; align-items: center; }
.reviews .section-deck { text-align: center; }

/* Empty until a safe review mounts (and with no JS) — keep it out of the layout
 * so it never adds blank space above the fallback. */
#reviews-carousel:empty { display: none; }

/* Scroll viewport: native swipe/trackpad scrolling + scroll-snap; the prev/next
 * buttons drive it for mouse/keyboard. Scrollbar hidden (controls are the
 * affordance); a focus ring is shown when the viewport itself is tabbed to. */
.review-track-viewport {
  /* Mobile card width is viewport-based so the first card can be centered on the
   * screen, not merely within the padded section content box. */
  --review-card-mobile-width: min(86vw, calc(100vw - (2 * var(--pad-x)) - 8px), 420px);
  --review-card-mobile-gutter: max(
    0px,
    calc((100vw - var(--review-card-mobile-width)) / 2 - var(--pad-x) + 2px)
  );
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
  /* Center the first mobile card at scrollLeft=0 while preserving the next-card peek. */
  scroll-padding-inline: var(--review-card-mobile-gutter);
  /* Top/bottom padding leaves room for the card hover lift + focus rings. */
  padding: 6px 2px 10px;
  margin-inline: -2px;
}
.review-track-viewport::-webkit-scrollbar { display: none; }
.review-track-viewport:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 4px;
  border-radius: 10px;
}

.review-track {
  list-style: none;
  margin: 0;
  padding: 0 var(--review-card-mobile-gutter);
  display: flex;
  gap: 18px;
}

.review-card {
  scroll-snap-align: center;
  /* Mobile: ~one card centered with the next peeking. Caps so a lone card isn't huge. */
  flex: 0 0 var(--review-card-mobile-width);
  max-width: 420px;
}
.review-card__inner {
  height: 100%;
  background: var(--white);
  border: 1px solid var(--fitting);
  border-radius: 14px;
  padding: 26px 24px;
  display: flex;
  flex-direction: column;
  gap: 16px;
  box-shadow: 0 1px 0 rgba(var(--white-rgb), 0.6),
    0 20px 44px -30px rgba(1, 8, 70, 0.45);
  transition: transform 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
.review-card:hover .review-card__inner {
  transform: translateY(-2px);
  border-color: var(--silver);
}

/* Star rating. The wrapper carries role="img" + an accessible "N out of 5 stars"
 * label; the glyphs are decorative (aria-hidden) gold/silver masked stars. */
.review-stars { display: inline-flex; gap: 4px; }
.review-star {
  width: 18px;
  height: 18px;
  background: var(--silver);
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="black"/></svg>') center/contain no-repeat;
          mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z" fill="black"/></svg>') center/contain no-repeat;
}
.review-star.is-on { background: var(--gold); }

.review-card__figure { margin: 0; display: flex; flex-direction: column; gap: 18px; flex: 1; }
.review-card__quote { margin: 0; position: relative; }
.review-card__quote::before {
  content: "\201C";
  position: absolute;
  top: -0.35em;
  left: -0.06em;
  font-family: var(--font-italic);
  font-size: 3rem;
  line-height: 1;
  color: rgba(var(--gold-rgb), 0.32);
  pointer-events: none;
}
.review-card__quote-text {
  margin: 0;
  color: var(--ink);
  font-size: var(--fs-lead);
  line-height: 1.6;
}

.review-card__foot {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: auto;
  padding-top: 16px;
  border-top: 1px solid var(--fitting);
}
.review-card__monogram {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--navy);
  color: var(--white);
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-md);
  letter-spacing: 0.04em;
  box-shadow: inset 0 0 0 1px rgba(var(--gold-rgb), 0.55);
}
.review-card__who { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.review-card__name {
  font-style: normal;
  font-weight: 800;
  font-size: var(--fs-body);
  color: var(--ink);
  letter-spacing: -0.005em;
}
.review-card__source {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--steel-strong); /* WCAG AA on white */
}
.review-card__link {
  margin-left: auto;
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--navy);
  text-decoration: none;
}
.review-card__link:hover { color: var(--midnight); text-decoration: underline; text-underline-offset: 3px; }
.review-card__link .btn-arrow { width: 12px; height: 12px; }

/* Prev/next controls. Hidden by JS when every card already fits (no overflow),
 * disabled at each end. Focus state comes from the global a/button rule. */
.review-controls {
  display: flex;
  gap: 12px;
  justify-content: center;
  margin-top: 26px;
}
.review-nav {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  border: 1px solid var(--navy);
  background: var(--white);
  color: var(--navy);
  display: grid;
  place-items: center;
  cursor: pointer;
  transition: background 180ms ease, color 180ms ease, border-color 180ms ease, opacity 180ms ease;
}
.review-nav:hover:not(:disabled) { background: var(--navy); color: var(--white); }
.review-nav:disabled { opacity: 0.4; cursor: default; border-color: var(--silver); color: var(--steel); }
.review-nav__icon {
  width: 16px;
  height: 16px;
  background: currentColor;
  -webkit-mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path d="M5 2l5 5-5 5" fill="none" stroke="black" stroke-width="1.7" stroke-linecap="square" stroke-linejoin="miter"/></svg>') center/contain no-repeat;
          mask: url('data:image/svg+xml;utf8,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path d="M5 2l5 5-5 5" fill="none" stroke="black" stroke-width="1.7" stroke-linecap="square" stroke-linejoin="miter"/></svg>') center/contain no-repeat;
}
.review-nav--prev .review-nav__icon { transform: rotate(180deg); }

/* Graceful no-data / no-JS fallback. Hidden once real cards mount. */
.reviews__fallback { max-width: 50ch; margin-inline: auto; text-align: center; }
.reviews.has-reviews .reviews__fallback { display: none; }
.reviews__fallback-lead {
  font-size: var(--fs-card);
  color: var(--ink);
  margin: 0 0 8px;
}
.reviews__fallback-sub {
  color: var(--steel-strong);
  font-size: var(--fs-deck);
  line-height: 1.55;
  margin: 0;
}

/* Persistent showroom-first CTAs — shown in both the reviews and empty states. */
.reviews__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  justify-content: center;
  margin-top: 32px;
}

/* Wider screens return to the fixed-width multi-card carousel; declared after the
 * mobile-first review rules so the reset wins in the cascade. */
@media (min-width: 700px) {
  .review-track-viewport {
    --review-card-mobile-width: 360px;
    --review-card-mobile-gutter: 0px;
    scroll-padding-inline: 0;
  }
  .review-track { padding-inline: 0; }
  .review-card { scroll-snap-align: start; flex: 0 0 360px; max-width: 360px; }
}

/* ==========================================================================
 * Custom shoes showroom page (issue #167 / JMD-51)
 * Curated made-to-order examples gallery + collection builder handoff.
 * Reuses existing tokens, .section, .article-prose, .btn systems — no new palette.
 * ========================================================================== */
.shoe-gallery {
  list-style: none;
  margin: 32px 0 8px;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}
.shoe-card {
  display: flex;
  flex-direction: column;
  gap: 14px;
}
.shoe-card__frame {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--midnight);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  overflow: hidden;
}
.shoe-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}
.shoe-card__meta { display: flex; flex-direction: column; gap: 4px; }
.shoe-card__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-card);
  line-height: 1.1;
  letter-spacing: -0.005em;
  margin: 0;
}
.shoe-card__sub {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--gold-deep); /* WCAG AA 4.5:1 on cream */
  margin: 0;
}
.shoe-card__model {
  font-size: var(--fs-base);
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
  margin: 0;
}

/* Collection builder handoff block */
.shoe-build {
  margin: 40px 0 8px;
  padding: 28px;
  background: var(--cotton);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 16px;
}
.shoe-build__lead {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-look);
  line-height: 1.2;
  margin: 0;
  color: var(--ink);
}
.shoe-build__cta { align-self: flex-start; }
.shoe-build__note {
  margin: 0;
  font-size: var(--fs-base);
  line-height: 1.55;
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
}

@media (min-width: 560px) {
  .shoe-gallery { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 860px) {
  .shoe-gallery { grid-template-columns: repeat(3, 1fr); gap: 28px; }
}

/* ==========================================================================
 * Custom-shoes Patina catalog browser + product-detail dialog (issue #178).
 * Progressive enhancement over the six-card static fallback. Two states share one
 * markup:
 *   - catalog mounted   -> #shoe-catalog is populated; the static grid hides
 *                          (.has-catalog on .shoe-showroom).
 *   - no JS / no data / init failure -> #shoe-catalog stays empty (hidden via
 *                          :empty) and the crawlable .shoe-gallery stays visible.
 * Reuses existing tokens/.btn/.section systems — no new palette.
 * ========================================================================== */
#shoe-catalog:empty { display: none; }
.shoe-showroom.has-catalog .shoe-gallery { display: none; }

.shoe-cat { margin: 28px 0 8px; }

/* Controls: filter segmented control + search row */
.shoe-cat__controls {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 8px;
}
.shoe-cat__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.shoe-cat__filter {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--steel-strong);
  background: var(--white);
  border: 1px solid var(--fitting);
  border-radius: 999px;
  padding: 9px 16px;
  min-height: var(--tap-min);
  cursor: pointer;
  transition: border-color 160ms ease, color 160ms ease, background 160ms ease;
}
.shoe-cat__filter:hover { border-color: var(--silver); }
.shoe-cat__filter:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.shoe-cat__filter[aria-pressed="true"] {
  background: var(--navy);
  border-color: var(--navy);
  color: var(--white);
}
.shoe-cat__search-row {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  align-items: center;
}
.shoe-cat__search {
  position: relative;
  display: flex;
  align-items: center;
  flex: 1 1 260px;
  min-width: 0;
}
.shoe-cat__search-icon {
  position: absolute;
  left: 14px;
  width: 15px;
  height: 15px;
  border: 2px solid var(--steel);
  border-radius: 50%;
  pointer-events: none;
}
.shoe-cat__search-icon::after {
  content: "";
  position: absolute;
  top: 12px;
  left: 11px;
  width: 7px;
  height: 2px;
  background: var(--steel);
  transform: rotate(45deg);
  transform-origin: left center;
}
.shoe-cat__search-input {
  width: 100%;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  color: var(--ink);
  background: var(--white);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  padding: 11px 14px 11px 38px;
  min-height: var(--tap-min);
}
.shoe-cat__search-input:focus-visible { outline: 2px solid var(--navy); outline-offset: 1px; border-color: var(--navy); }
.shoe-cat__reset {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--steel-strong);
  background: transparent;
  border: 1px solid var(--fitting);
  border-radius: 6px;
  padding: 11px 16px;
  min-height: var(--tap-min);
  cursor: pointer;
}
.shoe-cat__reset:hover { border-color: var(--silver); color: var(--ink); }
.shoe-cat__reset:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }

.shoe-cat__count {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--steel-strong);
  margin: 4px 0 18px;
}

/* Results grid — mirrors the static gallery cadence (1/2/3 columns). */
.shoe-cat__grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: 1fr;
  gap: 24px;
}
.shoe-cat-card { display: flex; }
.shoe-cat-card__btn {
  display: flex;
  flex-direction: column;
  gap: 14px;
  width: 100%;
  text-align: left;
  padding: 0;
  background: none;
  border: none;
  cursor: pointer;
  color: inherit;
  font: inherit;
}
.shoe-cat-card__btn:focus-visible {
  outline: 2px solid var(--navy);
  outline-offset: 4px;
  border-radius: 8px;
}
.shoe-cat-card__frame {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--midnight);
  border: 1px solid var(--fitting);
  border-radius: 6px;
  overflow: hidden;
}
.shoe-cat-card__frame.is-failed::after {
  content: "Image unavailable";
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  font-family: var(--font-mono);
  font-size: var(--fs-xxs);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--silver);
  background: var(--midnight);
}
.shoe-cat-card__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
  transition: transform 260ms ease;
}
.shoe-cat-card__btn:hover .shoe-cat-card__img { transform: scale(1.03); }
.shoe-cat-card__meta { display: flex; flex-direction: column; gap: 4px; }
.shoe-cat-card__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-card);
  line-height: 1.1;
  letter-spacing: -0.005em;
}
.shoe-cat-card__sub {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--gold-deep);
}
.shoe-cat-card__model {
  font-size: var(--fs-base);
  color: var(--steel-strong);
}
.shoe-cat-card__cta {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--navy);
  display: inline-flex;
  align-items: center;
  gap: 6px;
}
.shoe-cat-card__cta::after { content: "\2192"; }

.shoe-cat__empty {
  font-size: var(--fs-body);
  line-height: 1.55;
  color: var(--steel-strong);
  padding: 24px 0;
  margin: 0;
}
.shoe-cat__empty[hidden] { display: none; }

.shoe-cat__more-wrap { display: flex; justify-content: center; margin: 28px 0 8px; }
.shoe-cat__more-wrap[hidden] { display: none; }

@media (min-width: 560px) {
  .shoe-cat__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 860px) {
  .shoe-cat__grid { grid-template-columns: repeat(3, 1fr); gap: 28px; }
  .shoe-cat__controls { flex-direction: row; align-items: center; justify-content: space-between; }
  .shoe-cat__search-row { flex: 0 1 auto; }
}

/* -------- Product-detail dialog -------- */
.shoe-dialog-lock { overflow: hidden; }
.shoe-dialog {
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(0px, 3vw, 40px);
  background: rgba(var(--midnight-rgb), 0.9);
  opacity: 0;
  transition: opacity 200ms ease;
}
.shoe-dialog.is-open { opacity: 1; }
.shoe-dialog[hidden] { display: none; }

.shoe-dialog__panel {
  position: relative;
  width: min(1080px, 100%);
  max-height: 100%;
  overflow: auto;
  background: var(--cotton);
  border-radius: 10px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5);
  -webkit-overflow-scrolling: touch;
}
.shoe-dialog__close {
  position: absolute;
  top: 12px;
  right: 12px;
  z-index: 2;
  width: var(--tap-min);
  height: var(--tap-min);
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--silver);
  border-radius: 50%;
  background: rgba(var(--white-rgb), 0.96);
  color: var(--ink);
  cursor: pointer;
  transition: border-color 160ms ease, transform 160ms ease;
}
.shoe-dialog__close:hover { border-color: var(--navy); }
.shoe-dialog__close:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.shoe-dialog__close::before,
.shoe-dialog__close::after {
  content: "";
  position: absolute;
  width: 16px;
  height: 2px;
  background: var(--ink);
}
.shoe-dialog__close::before { transform: rotate(45deg); }
.shoe-dialog__close::after { transform: rotate(-45deg); }

.shoe-dialog__body {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
}
.shoe-dialog__gallery {
  padding: 20px;
  background: var(--white);
}
.shoe-dialog__stage {
  position: relative;
  aspect-ratio: 1 / 1;
  background: var(--midnight);
  border: 1px solid var(--fitting);
  border-radius: 8px;
  overflow: hidden;
  touch-action: pan-y;
}
.shoe-dialog__main-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center center;
}
.shoe-dialog__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border: none;
  border-radius: 50%;
  background: rgba(var(--white-rgb), 0.9);
  color: var(--ink);
  cursor: pointer;
}
.shoe-dialog__nav:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.shoe-dialog__nav[hidden] { display: none; }
.shoe-dialog__nav--prev { left: 10px; }
.shoe-dialog__nav--next { right: 10px; }
.shoe-dialog__nav::before {
  content: "";
  width: 10px;
  height: 10px;
  border-top: 2px solid currentColor;
  border-right: 2px solid currentColor;
}
.shoe-dialog__nav--prev::before { transform: rotate(-135deg); margin-left: 4px; }
.shoe-dialog__nav--next::before { transform: rotate(45deg); margin-right: 4px; }

.shoe-dialog__thumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-top: 12px;
}
.shoe-dialog__thumbs[hidden] { display: none; }
.shoe-dialog__thumb {
  width: 60px;
  height: 60px;
  padding: 0;
  border: 2px solid transparent;
  border-radius: 6px;
  overflow: hidden;
  background: var(--midnight);
  cursor: pointer;
}
.shoe-dialog__thumb img { width: 100%; height: 100%; object-fit: cover; display: block; }
.shoe-dialog__thumb.is-active { border-color: var(--navy); }
.shoe-dialog__thumb.is-failed { opacity: 0.4; }
.shoe-dialog__thumb:focus-visible { outline: 2px solid var(--navy); outline-offset: 2px; }
.shoe-dialog__gallery-status {
  position: absolute;
  width: 1px; height: 1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
}

.shoe-dialog__info { padding: 24px 24px 28px; }
.shoe-dialog__title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-look);
  line-height: 1.1;
  margin: 0 0 6px;
  color: var(--ink);
}
.shoe-dialog__sub {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--gold-deep);
  margin: 0 0 4px;
}
.shoe-dialog__model {
  font-size: var(--fs-base);
  color: var(--steel-strong);
  margin: 0 0 18px;
}
.shoe-dialog__specs {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 6px 16px;
  margin: 0 0 18px;
}
.shoe-dialog__specs[hidden] { display: none; }
.shoe-dialog__spec-label {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--steel-strong);
  margin: 0;
}
.shoe-dialog__spec-value {
  font-size: var(--fs-base);
  color: var(--ink);
  margin: 0;
}
.shoe-dialog__desc-p {
  font-size: var(--fs-base);
  line-height: 1.6;
  color: var(--charcoal);
  margin: 0 0 12px;
}
/* Enabled model actions render as one two-column row (Customize | Order) at every
   supported width — never stacked. The minmax(0,1fr) tracks let each button shrink
   below its content width so long labels wrap INSIDE the button instead of forcing
   a second row or horizontal overflow (#181). */
.shoe-dialog__actions {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: 12px;
  margin: 8px 0 14px;
}
.shoe-dialog__actions[hidden] { display: none; }
/* Let each action button fill its column and wrap its label internally so the pair
   stays side by side and readable at narrow (375px) widths without clipping. */
.shoe-dialog__action {
  min-width: 0;
  white-space: normal;
  text-align: center;
  padding-left: 14px;
  padding-right: 14px;
}
.shoe-dialog__disclosure {
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--steel-strong);
  margin: 0;
}

@media (min-width: 760px) {
  .shoe-dialog__body { grid-template-columns: 1.05fr 0.95fr; }
  .shoe-dialog__gallery { border-right: 1px solid var(--fitting); }
}

/* Mobile: nearly full-screen dialog with an easy-to-reach persistent close. */
@media (max-width: 759px) {
  .shoe-dialog { padding: 0; }
  .shoe-dialog__panel { width: 100%; height: 100%; max-height: 100%; border-radius: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .shoe-dialog { transition: none; }
  .shoe-cat-card__img { transition: none; }
  .shoe-cat-card__btn:hover .shoe-cat-card__img { transform: none; }
}

/* Active-slide caption (title / Patina Goodyear Welt / model number). Mirrors
   the static .shoe-card__* meta typography for visual continuity. */
.card-carousel__caption {
  margin-top: 18px;
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: 4px;
}
.card-carousel__caption-title {
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-card);
  line-height: 1.1;
  letter-spacing: -0.005em;
  color: var(--ink);
}
.card-carousel__caption-sub {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--gold-deep); /* WCAG AA 4.5:1 on cream */
}
.card-carousel__caption-meta {
  font-size: var(--fs-base);
  color: var(--steel-strong); /* WCAG AA 4.5:1 on cream */
}
/* An empty caption span (missing field) should not add gap. */
.card-carousel__caption-title:empty,
.card-carousel__caption-sub:empty,
.card-carousel__caption-meta:empty { display: none; }

/* ===========================================================================
   Analytics consent control (issue #214)
   ---------------------------------------------------------------------------
   Visitor-facing half of the #102 measurement seam. The markup is built by
   site/assets/js/analytics-consent.js (no JS means no runtime to consent to, so
   no dead control ships). Non-modal by design: the page stays usable and no
   choice is forced. Colours/spacing come from the tokens above only.

   Layered under the lightbox / product dialog (z-index 1000) and over the
   sticky nav (50), so an open enlarged photo is never covered by the banner.
   =========================================================================== */
.consent {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 900;
  display: flex;
  justify-content: center;
  padding: 0 var(--pad-x) 16px;
  /* The region is a full-width flex row; only the panel itself is interactive, so
     the page behind the empty gutters stays clickable. */
  pointer-events: none;
}
/* `.consent` sets display, which would otherwise defeat the UA [hidden] rule. */
.consent[hidden] { display: none; }

.consent__panel {
  pointer-events: auto;
  position: relative;
  width: 100%;
  max-width: 640px;
  padding: 18px calc(var(--tap-min) + 4px) 18px 18px;
  /* A consent notice must never swallow a small viewport: past this height the panel
     scrolls instead of growing, so the page behind it stays reachable. */
  max-height: min(70vh, 520px);
  overflow-y: auto;
  background: var(--midnight);
  color: rgba(var(--white-rgb), 0.82);
  /* WCAG 2.2 SC 1.4.11: this panel floats over both the navy hero and cream sections,
     so its boundary carries the full gold token (~4.6:1 on navy, ~7.6:1 on the panel)
     rather than the low-alpha rule used by cards that sit inside a section. */
  border: 1px solid var(--gold);
  border-radius: var(--radius);
  box-shadow: 0 12px 32px rgba(var(--midnight-rgb), 0.32);
}

.consent__title {
  margin: 0 0 8px;
  font-family: var(--font-display);
  font-weight: 800;
  font-size: var(--fs-md);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--white);
}
.consent__body { margin: 0; font-size: var(--fs-base); line-height: 1.6; }
.consent__status {
  margin: 8px 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  line-height: 1.6;
  color: rgba(var(--white-rgb), 0.72);
}

.consent__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 12px 16px;
  margin-top: 16px;
}
.consent__action { flex: 1 1 auto; }

/* WCAG SC 1.4.1: the disclosure link must not rely on colour alone. */
.consent__link {
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(var(--white-rgb), 0.85);
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
}
.consent__link:hover { color: var(--white); }

.consent__dismiss {
  position: absolute;
  top: 6px;
  right: 6px;
  width: var(--tap-min);
  height: var(--tap-min);
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0;
  background: transparent;
  border: 0;
  border-radius: var(--radius);
  color: rgba(var(--white-rgb), 0.8);
  font-size: var(--fs-look);
  line-height: 1;
  cursor: pointer;
}
.consent__dismiss:hover { color: var(--white); }

/* Persistent reopen/change path, mounted into the shared footer row. */
.foot-consent { display: flex; align-items: center; flex: 0 0 auto; }
.consent__trigger {
  white-space: nowrap;
  font-family: var(--font-mono);
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: rgba(var(--white-rgb), 0.7);
  background: transparent;
  /* SC 1.4.11 again: the border is what identifies this as a control, so it clears
     3:1 on --midnight (~4.2:1) rather than reading as a hairline. */
  border: 1px solid rgba(var(--white-rgb), 0.45);
  border-radius: var(--radius);
  padding: 8px 14px;
  min-height: var(--tap-min);
  cursor: pointer;
}
.consent__trigger:hover { color: var(--white); border-color: rgba(var(--white-rgb), 0.7); }

/* Visually-hidden description carrying the current choice to assistive tech. */
.consent__sr {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (min-width: 700px) {
  .consent__panel { padding: 20px calc(var(--tap-min) + 8px) 20px 20px; }
  .consent__action { flex: 0 0 auto; }
}
