/* Prem Roy Motoring - V1
   ------------------------------------------------------------------
   Ported from Krishna's draft stylesheet (prm-620.pages.dev, captured
   2026-09-22). His original is kept verbatim at
   v1-krishna/assets/css/site.css.

   His design tokens are UNCHANGED - they already match the values
   sampled from the brand logo, and his ground rule holds: white page,
   black type, colour on navigation, rules and calls to action only,
   never as a background wash.

   Removed here are only the rules for things V1 does not ship:
     .eyebrow        banned framework-wide - no kicker above a headline
     .buildnote      draft-only annotation
     .car / .cars    the nine placeholder vehicles
     .field .form-*  form UI - V1 has no forms of any kind
     .consent .chip .choice .choices .count .empty .filters
     .nav-toggle     the mobile menu needed JS; the nav wraps instead
     .map-frame      third-party embed; nothing loads from a third party
   ------------------------------------------------------------------ */

:root {
  --ink:          #0B0B0C;
  --ink-soft:     #3A3A3E;
  --ink-faint:    #76767E;
  --hair:         #E3E3E7;
  --hair-strong:  #C9C9D0;
  --paper:        #FFFFFF;
  --paper-warm:   #FAFAF8;

  --indigo:       #2E1D6B;
  --indigo-deep:  #1B1142;
  --indigo-soft:  #EDEBF5;

  --gold:         #8A7524;
  --gold-bright:  #A8912F;
  --gold-soft:    #F6F2E2;

  --wa:           #1E8E58;

  --serif: ui-serif, Georgia, "Iowan Old Style", "Times New Roman", Times, serif;
  --sans:  system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;

  --shell:  1220px;
  --gut:    clamp(1.25rem, 4vw, 3rem);
}
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}
img { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
h1, h2, h3, h4 {
  font-family: var(--serif);
  font-weight: 500;
  letter-spacing: -0.012em;
  line-height: 1.12;
  margin: 0;
  color: var(--ink);
}
h1 { font-size: clamp(2.5rem, 5.6vw, 4.15rem); }
h2 { font-size: clamp(1.85rem, 3.4vw, 2.75rem); }
h3 { font-size: clamp(1.2rem, 1.9vw, 1.5rem); }
p { margin: 0 0 1.05em; }
p:last-child { margin-bottom: 0; }
.shell { width: 100%; max-width: var(--shell); margin-inline: auto; padding-inline: var(--gut); }
.lede { font-size: clamp(1.05rem, 1.5vw, 1.22rem); color: var(--ink-soft); max-width: 62ch; }
.rule-gradient {
  height: 2px; border: 0; margin: 0;
  background: linear-gradient(90deg, var(--indigo) 0%, var(--indigo) 30%, var(--gold) 78%, var(--gold-bright) 100%);
}
.topbar {
  background: var(--indigo-deep);
  color: #EDEAF6;
  font-size: 0.79rem;
  letter-spacing: 0.02em;
}
.topbar .shell {
  display: flex; gap: 1.5rem; align-items: center; justify-content: space-between;
  min-height: 38px; flex-wrap: wrap;
}
.topbar a { color: #EDEAF6; text-decoration: none; }
.topbar a:hover { color: #E6CF7E; }
.topbar .sep { color: #6A5E9A; }
.masthead {
  position: sticky; top: 0; z-index: 60;
  background: rgba(255,255,255,0.94);
  backdrop-filter: saturate(160%) blur(10px);
  border-bottom: 1px solid var(--hair);
}
.masthead .shell {
  display: flex; align-items: center; gap: 1.5rem;
  min-height: 84px;
}
.brand { display: flex; align-items: center; text-decoration: none; flex: 0 0 auto; }
.brand img { width: 196px; }
.nav { margin-left: auto; display: flex; align-items: center; gap: 1.9rem; }
.nav a {
  position: relative;
  text-decoration: none;
  font-size: 0.86rem;
  letter-spacing: 0.085em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--ink);
  padding: 0.35rem 0;
}
.nav a::after {
  content: ""; position: absolute; left: 0; right: 100%; bottom: 0; height: 2px;
  background: linear-gradient(90deg, var(--indigo), var(--gold));
  transition: right 0.28s ease;
}
.nav a:hover::after, .nav a[aria-current="page"]::after { right: 0; }
.nav a[aria-current="page"] { color: var(--indigo); }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  font-family: var(--sans);
  font-size: 0.85rem; font-weight: 600;
  letter-spacing: 0.075em; text-transform: uppercase;
  padding: 0.92rem 1.6rem;
  border: 1px solid transparent;
  text-decoration: none; cursor: pointer;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}
.btn-primary { background: var(--indigo); color: #fff; }
.btn-primary:hover { background: var(--indigo-deep); }
.btn-gold { background: var(--gold); color: #fff; }
.btn-gold:hover { background: var(--gold-bright); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: #fff; }
.btn-wa { background: var(--wa); color: #fff; }
.btn-wa:hover { background: #176F45; }
.btn-sm { padding: 0.62rem 1.05rem; font-size: 0.76rem; }
.btn svg { width: 17px; height: 17px; fill: currentColor; flex: 0 0 auto; }
.btn-row { display: flex; flex-wrap: wrap; gap: 0.85rem; }
.hero { padding: clamp(3.5rem, 7vw, 6.25rem) 0 clamp(3rem, 5vw, 4.5rem); }
.hero-grid {
  display: grid; grid-template-columns: 1.08fr 0.92fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items: center;
}
.hero h1 { margin-bottom: 1.4rem; }
.hero h1 em { font-style: italic; color: var(--indigo); }
.hero .btn-row { margin-top: 2rem; }
.hero-marks {
  margin-top: 2.9rem; padding-top: 1.5rem; border-top: 1px solid var(--hair);
  display: flex; flex-wrap: wrap; gap: 1.1rem 2.2rem;
  font-size: 0.76rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--ink-faint); font-weight: 600;
}
.section { padding: clamp(3.25rem, 6vw, 5.5rem) 0; }
.section-warm { background: var(--paper-warm); border-block: 1px solid var(--hair); }
.section-head { max-width: 66ch; margin-bottom: clamp(2rem, 3.5vw, 3rem); }
.grid-3 { display: grid; grid-template-columns: repeat(3, 1fr); gap: clamp(1.25rem, 2.5vw, 2rem); }
.grid-2 { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1.5rem, 3vw, 3rem); }
.pillar { border-top: 2px solid var(--indigo); padding-top: 1.25rem; }
.pillar:nth-child(2) { border-top-color: #5B4A8E; }
.pillar:nth-child(3) { border-top-color: var(--gold); }
.pillar h3 { margin-bottom: 0.55rem; }
.pillar p { color: var(--ink-soft); font-size: 0.97rem; margin: 0; }
.panel {
  border: 1px solid var(--hair);
  background: #fff;
  padding: clamp(1.6rem, 3vw, 2.6rem);
}
.panel-accent { border-top: 3px solid var(--indigo); }
.panel-accent-gold { border-top: 3px solid var(--gold); }
.contact-card { border: 1px solid var(--hair); padding: 1.5rem 1.6rem; }
.contact-card h3 { font-size: 1.12rem; margin-bottom: 0.7rem; }
.contact-card address { font-style: normal; color: var(--ink-soft); font-size: 0.96rem; }
.contact-card a { color: var(--indigo); text-decoration: none; border-bottom: 1px solid var(--hair-strong); }
.contact-card a:hover { border-bottom-color: var(--indigo); }
.footer { background: var(--indigo-deep); color: #C9C3E0; padding: clamp(3rem, 5vw, 4rem) 0 0; margin-top: 0; }
.footer a { color: #C9C3E0; text-decoration: none; }
.footer a:hover { color: #E6CF7E; }
.footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.2fr; gap: 2rem; }
.footer h4 {
  font-family: var(--sans); font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.17em; text-transform: uppercase; color: #E6CF7E;
  margin: 0 0 0.9rem;
}
.footer ul { list-style: none; margin: 0; padding: 0; font-size: 0.92rem; }
.footer li { margin-bottom: 0.45rem; }
.footer .mark { font-family: var(--serif); font-size: 1.35rem; color: #fff; margin-bottom: 0.6rem; }
.footer .blurb { font-size: 0.92rem; max-width: 34ch; }
.footer-base {
  margin-top: 2.75rem; border-top: 1px solid rgba(255,255,255,0.12);
  padding: 1.15rem 0; font-size: 0.82rem;
  display: flex; justify-content: space-between; gap: 1rem; flex-wrap: wrap;
}
.wa-float {
  position: fixed; right: 20px; bottom: 20px; z-index: 70;
  width: 58px; height: 58px; border-radius: 50%;
  background: var(--wa); color: #fff;
  display: flex; align-items: center; justify-content: center;
  box-shadow: 0 6px 22px rgba(0,0,0,0.22);
  text-decoration: none;
  transition: transform 0.2s ease;
}
.wa-float:hover { transform: scale(1.07); }
.wa-float svg { width: 30px; height: 30px; fill: #fff; }
@media (max-width: 980px) {
.hero-grid, .grid-2, .footer-grid { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: repeat(2, 1fr); }
.footer-grid { gap: 1.75rem; }
.nav {
    display: none; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--hair);
    padding: 0.5rem var(--gut) 1rem;
  }
.nav.open { display: flex; }
.nav a { padding: 0.85rem 0; border-bottom: 1px solid var(--hair); }
.nav a::after { display: none; }
.masthead .shell { position: relative; }
}
@media (max-width: 640px) {
body { font-size: 16px; }
.grid-3 { grid-template-columns: 1fr; }
.topbar .shell { justify-content: center; text-align: center; }
}
@media (prefers-reduced-motion: reduce) {
*, *::before, *::after { transition: none !important; scroll-behavior: auto !important; }
}

/* ================================================================== */
/* V1 additions                                                       */
/* ================================================================== */

/* A warm hairline for dividers, so a rule inside a white panel does not read as
   cool grey against a gold-and-indigo palette. This is the brand gold #8A7524
   laid over white at roughly 12% - light enough to be a whisper, warm enough to
   belong. --hair #E3E3E7 and --hair-strong #C9C9D0 are both cool and both read
   heavier than a menu divider should. */
:root { --hair-warm: #EFEAD9; }

/* Nav stays visible at every width - no JS toggle, so it wraps. */
.masthead .nav { flex-wrap: wrap; }
@media (max-width: 880px) {
  .masthead .shell { flex-wrap: wrap; row-gap: 0.75rem; min-height: 0; padding-block: 0.9rem; }
  .masthead .nav { width: 100%; margin-left: 0; gap: 0.75rem 1.35rem; }
  .masthead .nav a { font-size: 0.78rem; letter-spacing: 0.06em; }
  .brand img { width: 168px; }
}

/* No .pending or .awaiting rules: V1 carries no placeholders. Where a value is
   not held the copy omits it rather than announcing the gap. */

/* Numbered process steps. */
.steps { display: grid; gap: clamp(1.25rem, 2.5vw, 2rem); grid-template-columns: repeat(3, 1fr); }
.step { border-top: 2px solid var(--indigo); padding-top: 1.25rem; }
.step:nth-child(2) { border-top-color: #5B4A8E; }
.step:nth-child(3) { border-top-color: var(--gold); }
.step h3 { margin-bottom: 0.5rem; font-size: 1.15rem; }
.step p { color: var(--ink-soft); font-size: 0.97rem; margin: 0; }

/* Question-and-answer blocks. */
.qa { border-top: 1px solid var(--hair); padding: 0; }
.qa > summary {
  list-style: none;                 /* Firefox */
  cursor: pointer;
  padding: 1.25rem 2.5rem 1.25rem 0;
  position: relative;
}
.qa > summary::-webkit-details-marker { display: none; }   /* Safari, older Chrome */
.qa > summary::after {               /* chevron, drawn in CSS - no icon file */
  content: "";
  position: absolute;
  right: 0.4rem; top: 1.65rem;
  width: 0.55rem; height: 0.55rem;
  border-right: 2px solid var(--gold, #8C7F55);
  border-bottom: 2px solid var(--gold, #8C7F55);
  transform: rotate(45deg);
  transition: transform .18s ease;
}
.qa[open] > summary::after { transform: rotate(-135deg); top: 1.9rem; }
.qa > summary:hover h3 { color: var(--indigo); }
.qa > summary:focus-visible { outline: 2px solid var(--indigo); outline-offset: 3px; }
.qa > p { padding: 0 2.5rem 1.4rem 0; }
.qa:last-of-type { border-bottom: 1px solid var(--hair); }
.qa summary h3 { font-size: 1.12rem; margin-bottom: 0.4rem; }
.qa > p { color: var(--ink-soft); font-size: 0.98rem; margin: 0; }

/* Checklists. */
.ticks { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.55rem; }
.ticks li { position: relative; padding-left: 1.75em; color: var(--ink-soft); }
.ticks li::before {
  content: ""; position: absolute; left: 0; top: 0.52em;
  width: 0.7em; height: 0.36em;
  border-left: 2px solid var(--gold); border-bottom: 2px solid var(--gold);
  transform: rotate(-45deg);
}

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

/* A panel beside the hero needs h2 for a valid heading tree, but should read
   at h3 scale. Structure is the heading level; size is CSS. */
.panel h2, .contact-card h2 { font-size: clamp(1.2rem, 1.9vw, 1.5rem); }

/* ---- Dropdown: Services > COE & Financing --------------------------
   No JavaScript, so the panel opens on :hover and on :focus-within, which
   covers pointer and keyboard. The parent is also a real link, because touch
   devices have no hover - tapping Services goes to the hub page instead.
   Below 880px the child simply sits inline; a hover-only menu on a phone
   would hide it entirely. */
.has-sub { position: relative; display: inline-flex; align-items: center; }
.has-sub > a { display: inline-flex; align-items: center; gap: 0.4rem; }
.caret {
  width: 0; height: 0;
  border-left: 3.5px solid transparent;
  border-right: 3.5px solid transparent;
  border-top: 4px solid currentColor;
  opacity: 0.65;
  transition: transform 0.18s ease;
}
.has-sub:hover .caret, .has-sub:focus-within .caret { transform: rotate(180deg); }

.sub {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(6px);
  min-width: 16.5rem; margin: 0; padding: 0.4rem 0; list-style: none;
  background: var(--paper);
  border: 1px solid var(--hair);
  border-top: 2px solid var(--gold);
  box-shadow: 0 10px 28px rgba(11, 11, 12, 0.13);
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease;
  z-index: 70;
}
.has-sub:hover .sub, .has-sub:focus-within .sub {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
/* keeps the pointer from falling through the gap between parent and panel */
.sub::before { content: ""; position: absolute; top: -8px; left: 0; right: 0; height: 8px; }
.sub li { margin: 0; }
.sub a {
  display: block; padding: 0.6rem 1.1rem;
  font-size: 0.8rem; letter-spacing: 0.06em; text-transform: uppercase;
  font-weight: 600; text-decoration: none; color: var(--ink);
  line-height: 1.4;
}

/* Group companies sit on their own domains. A divider and an arrow carry that
   signal on their own - these items otherwise match the rest of the menu exactly.
   An earlier version set them in sentence case at weight 500, which read as
   smaller and looked like a mistake rather than a distinction.
   They open in the SAME tab, so there is nothing to warn about and no arrow. */
/* The FIRST group-company item, i.e. the one that follows an in-house item.
   NOT li.is-ext:first-of-type - :first-of-type means "first <li> among siblings",
   and the first <li> is COE & Financing, so that compound matched nothing at all.
   Items already sit 1.2rem apart, so the gap here is set wider than that or the
   rule reads as noise rather than a break. */
.sub li:not(.is-ext) + li.is-ext {
  border-top: 1px solid var(--hair-warm);
  margin-top: 0.7rem;
  padding-top: 0.7rem;
}
.sub li.is-ext:last-child { padding-bottom: 0.25rem; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
.sub a::after { display: none; }
.sub a:hover, .sub a:focus-visible { background: var(--indigo-soft); color: var(--indigo); }
.sub a[aria-current="page"] { color: var(--indigo); background: var(--indigo-soft); }

/* Parent of the current page: show the same underline the nav gives a current
   item, without claiming aria-current - that belongs to the page itself. */
.has-sub.is-ancestor > a { color: var(--indigo); }
.has-sub.is-ancestor > a::after { right: 0; }

@media (max-width: 880px) {
  .has-sub { display: contents; }
  .caret { display: none; }
  .sub {
    position: static; transform: none; opacity: 1; visibility: visible;
    pointer-events: auto; min-width: 0; margin: 0; padding: 0;
    background: none; border: 0; box-shadow: none;
    display: inline-flex; gap: 0.75rem 1.35rem;
  }
  .sub::before { display: none; }
  .sub a { padding: 0; font-size: 0.78rem; letter-spacing: 0.06em; }
}

/* ---- Group brand panels on /about --------------------------------
   The live homepage runs these as two full-bleed Slider Revolution panels with
   background photography. We hold neither the photographs nor a colour Sprayboxx
   logo - only a 140x65 greyscale mark - so these are set in type instead of
   pairing one crisp asset with one poor one. Drop in the photography and this
   becomes a background-image swap. */
.brandpanels { display: grid; gap: 1.25rem; grid-template-columns: 1fr; }
@media (min-width: 46rem) { .brandpanels { grid-template-columns: 1fr 1fr; } }

.brandpanel {
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--hair);
  border-top: 3px solid var(--gold);
  padding: clamp(2rem, 4vw, 3.25rem) clamp(1.5rem, 3vw, 2.5rem);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.brandpanel > * { position: relative; z-index: 1; }
.brandpanel h3 {
  color: var(--ink);
  font-family: var(--sans);
  font-size: clamp(1.9rem, 4vw, 2.9rem);
  font-weight: 800;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin: 0 0 0.45rem;
}
.brandpanel .sub {
  font-size: 0.76rem; letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--gold-bright); margin: 0 0 1.1rem; font-weight: 600;
}
.brandpanel .tag {
  font-family: var(--serif);
  font-size: clamp(1rem, 1.35vw, 1.15rem);
  line-height: 1.3; color: var(--ink);
  margin: 0 auto 1.6rem; max-width: 24ch;
}

/* A panel standing alone in a section rather than beside the hero. Gets more
   room to breathe, and its heading reads at section scale since nothing else on
   the row competes with it. */
.panel-wide { padding: clamp(1.75rem, 3.5vw, 2.75rem) clamp(1.5rem, 3vw, 2.5rem); }
.panel-wide h2 { font-size: clamp(1.5rem, 2.6vw, 2.1rem) !important; }
.panel-wide p { max-width: 66ch; font-size: 1rem; }

/* Trust numbers. The live site animates these on scroll; here they are static -
   V1 carries no JavaScript, and a number that counts up is a number you cannot
   read until it has finished. */
.stats {
  list-style: none; margin: 0; padding: 0;
  display: grid; gap: clamp(1.5rem, 3vw, 2.5rem);
  grid-template-columns: repeat(2, 1fr);
  text-align: center;
}
@media (min-width: 54rem) { .stats { grid-template-columns: repeat(4, 1fr); } }
.stats li { position: relative; }
@media (min-width: 54rem) {
  .stats li + li::before {
    content: ""; position: absolute; left: calc(clamp(1.5rem, 3vw, 2.5rem) / -2);
    top: 12%; bottom: 12%; width: 1px; background: var(--hair-warm);
  }
}
.stats b {
  display: block;
  font-family: var(--serif); font-weight: 500;
  font-size: clamp(2.1rem, 4.4vw, 3.1rem);
  line-height: 1; letter-spacing: -0.02em;
  color: var(--indigo);
}
.stats span {
  display: block; margin-top: 0.55rem;
  font-size: 0.76rem; letter-spacing: 0.15em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint);
}

/* Wider intros, site-wide. Krishna's sheet caps .lede at 62ch and .section-head
   at 66ch, which is a sound measure for long prose but leaves these short two-
   sentence intros wrapping to three lines across a third of the page. 84ch is
   still inside the comfortable range for lines this short.
   Body paragraphs inside grid columns are unaffected - their column is narrower
   than 84ch, so the column keeps doing the constraining. */
.lede { max-width: 104ch; }
.section-head { max-width: 104ch; }

/* Cards on the warm section background. The pillars they replace were bare
   columns with a top rule; these sit on white so they read as objects against
   --paper-warm rather than as text that happens to be in a column. */
.cards { display: grid; gap: clamp(1rem, 2vw, 1.5rem); grid-template-columns: 1fr; }
@media (min-width: 52rem) { .cards { grid-template-columns: repeat(3, 1fr); } }
.card {
  background: var(--paper);
  border: 1px solid var(--hair);
  border-top: 3px solid var(--indigo);
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
  display: flex; flex-direction: column;
}
.card:nth-child(2) { border-top-color: #5B4A8E; }
.card:nth-child(3) { border-top-color: var(--gold); }
.card:nth-child(4) { border-top-color: var(--gold-bright); }
.card h3 { margin-bottom: 0.6rem; font-size: clamp(1.15rem, 1.7vw, 1.35rem); }
.card p { color: var(--ink-soft); font-size: 0.97rem; margin: 0 0 1.4rem; }
/* buttons sit on the baseline whatever the copy length, so a row of cards
   keeps a straight line across the bottom */
.card .btn-row { margin-top: auto; gap: 0.6rem; }

/* ---- Stock carousel -------------------------------------------------
   Four cards. A grid on wide screens, a scroll-snap rail on narrow ones -
   swipe and keyboard scroll both work with no JavaScript. Arrow buttons
   would need a script to drive them, so the rail is scrollable instead and
   focusable, which keeps it reachable by keyboard. */
.cars-rail {
  display: grid; gap: clamp(1rem, 2vw, 1.5rem);
  grid-template-columns: repeat(4, 1fr);
  margin-bottom: clamp(2rem, 3.5vw, 3rem);
}
@media (max-width: 68rem) { .cars-rail { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 40rem) {
  .cars-rail {
    grid-auto-flow: column; grid-auto-columns: 78%; grid-template-columns: none;
    overflow-x: auto; scroll-snap-type: x mandatory;
    padding-bottom: 0.75rem; margin-inline: calc(var(--gut) * -1);
    padding-inline: var(--gut); scrollbar-width: thin;
  }
  .car { scroll-snap-align: start; }
}
.cars-rail:focus-visible { outline: 3px solid var(--gold-bright); outline-offset: 4px; }

.car { background: var(--paper); border: 1px solid var(--hair); display: flex; flex-direction: column; }
.car-shot { display: block; aspect-ratio: 16 / 10; overflow: hidden; background: var(--indigo-soft); }
.car-shot img { width: 100%; height: 100%; object-fit: cover; }
.car-body { padding: 1rem 1.1rem 1.15rem; display: flex; flex-direction: column; flex: 1; }
.car-body h3 { font-size: 1.05rem; margin: 0 0 0.3rem; line-height: 1.25; }
.car-body h3 a { text-decoration: none; color: var(--ink); }
.car-body h3 a:hover { color: var(--indigo); }
.car-price { font-family: var(--serif); font-size: 1.3rem; color: var(--indigo); margin: 0 0 0.9rem; }
.car-specs { display: grid; grid-template-columns: auto 1fr; gap: 0.2rem 0.75rem; margin: 0; font-size: 0.83rem; }
.car-specs dt { color: var(--ink-faint); text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.7rem; align-self: center; }
.car-specs dd { margin: 0; color: var(--ink-soft); font-weight: 600; }

/* Shown whether or not there is stock - it is the fallback when the carousel is
   empty, and still the right prompt when it is not. */
.ask-instead {
  border-top: 1px solid var(--hair-warm); padding-top: clamp(1.5rem, 2.5vw, 2rem);
  display: flex; flex-wrap: wrap; gap: 1rem 2rem; align-items: center;
  justify-content: space-between;
}
.ask-instead p { margin: 0; font-size: 1.02rem; color: var(--ink-soft); max-width: 52ch; }
.ask-instead strong { color: var(--ink); }

/* The ported sheet has no visible focus ring. */
:focus-visible { outline: 3px solid var(--gold-bright); outline-offset: 2px; }
.skip-link { position: absolute; left: -9999px; background: var(--indigo); color: #fff; padding: 0.6rem 1.2rem; z-index: 200; }
.skip-link:focus { left: 1rem; top: 0.5rem; }

/* ---- Latest news: minimised, one card per post -------------------------
   Titles only. The excerpts were dropped to shrink the block - it sits
   between the car rail and the contact panel and should not compete with
   either. Dates are deliberately NOT shown: the newest post is 2023-09-05
   and a visible date would read as neglect. If the blog is ever written
   again, put the dates back - that is the honest version. */
.section-tight { padding-block: 3.25rem; }
.section-head-sm { margin-bottom: 1.5rem; }
.section-head-sm h2 { font-size: clamp(1.35rem, 2.2vw, 1.75rem); }

.posts {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1rem;
}
.postcard {
  background: #fff;
  border: 1px solid var(--hair-warm);
  border-radius: 10px;
  overflow: hidden;
  transition: border-color .15s ease, transform .15s ease;
}
.postcard:hover { border-color: #D8C99A; transform: translateY(-2px); }
.postcard-link { display: block; text-decoration: none; color: inherit; height: 100%; }
.postcard-shot {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  background: var(--hair-warm);
}
.postcard-body { padding: 0.95rem 1.05rem 1.1rem; }
.postcard-title {
  margin: 0;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.975rem;
  line-height: 1.45;
  font-weight: 600;
}
.postcard-more {
  display: block;
  margin-top: 0.6rem;
  font-size: 0.8rem;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #8C7F55;
}
.postcard-link:hover .postcard-more { text-decoration: underline; }

@media (max-width: 60rem) { .posts { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 34rem) { .posts { grid-template-columns: 1fr; } }

/* ---- Homepage map ------------------------------------------------------
   Replaces the plain contact card. The address is kept beneath the map: a
   pin is not machine-readable, and it is all a visitor has if the embed is
   blocked or fails to load. Note this is the site's only third-party embed. */
.map-card {
  border: 1px solid var(--hair-warm);
  border-radius: 12px;
  overflow: hidden;
  background: #fff;
  /* Match the column beside it: the card fills the grid row, and the map takes
     whatever height is left once the address strip has had its share. A fixed
     ratio drifted out of step with the text column as it rewrapped. */
  display: flex;
  flex-direction: column;
  height: 100%;
}
.map-embed {
  display: block;
  width: 100%;
  flex: 1 1 auto;
  min-height: 260px;   /* so a short text column cannot squash it to a sliver */
  border: 0;
  background: var(--hair-warm);
}
.map-nap {
  display: block;
  padding: 1rem 1.15rem 1.15rem;
  font-style: normal;
  font-size: 0.925rem;
  line-height: 1.65;
  border-top: 1px solid var(--hair-warm);
}
.map-nap strong { font-family: Georgia, "Times New Roman", serif; font-size: 1.05rem; }

@media (max-width: 980px) {
  .map-card { height: auto; }
  .map-embed { flex: 0 0 auto; aspect-ratio: 3 / 2; min-height: 0; }
}

/* ---- "Ready to sell?" pointers ----------------------------------------
   A list, not cards: these are the six things to send, and boxing each one
   would give them more weight than the section above them. Icons are inline
   SVG so they inherit colour and cost no extra request. */
.pointers {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2.25rem 3rem;
}
.pointer {
  display: flex;
  align-items: flex-start;
  gap: 0.75rem;
  font-size: 0.975rem;
  line-height: 1.5;
}
.pt-icon {
  flex: 0 0 auto;
  width: 26px;
  height: 26px;
  color: var(--gold, #8C7F55);
  margin-top: 0.05rem;
}

@media (max-width: 62rem) { .pointers { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 38rem) { .pointers { grid-template-columns: 1fr; } }

/* /buy shows the whole list, so it keeps a wrapping grid at every width. The
   homepage rail is a teaser and may scroll sideways; a listing must not. */
/* Three across, so six cards read as a tidy 3x2 block. */
.cars-grid { margin-bottom: 0; grid-template-columns: repeat(3, 1fr); }
@media (max-width: 40rem) {
  .cars-grid {
    grid-auto-flow: row; grid-template-columns: 1fr; grid-auto-columns: auto;
    overflow-x: visible; scroll-snap-type: none;
    margin-inline: 0; padding-inline: 0;
  }
}

/* ---- Car card actions + CSS-only "Load more" --------------------------
   No JavaScript anywhere: the ninth card onwards is hidden by CSS, and a
   checkbox the visitor never sees flips it. All cars are present in the HTML
   from the first byte, so a crawler reads the full list regardless. */
.car-actions {
  display: flex;
  gap: 0.5rem;
  margin-top: 1rem;
  padding-top: 0.9rem;
  border-top: 1px solid var(--hair-warm);
}
.car-actions .btn { flex: 1 1 0; justify-content: center; text-align: center; }
.btn-sm { padding: 0.55rem 0.8rem; font-size: 0.78rem; }

.more-toggle {
  position: absolute; width: 1px; height: 1px;
  clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
.cars-grid.is-capped > .car:nth-child(n+7) { display: none; }
.more-toggle:checked ~ .cars-grid.is-capped > .car:nth-child(n+7) { display: flex; }
.more-btn { display: flex; width: max-content; margin: 2.25rem auto 0;
            cursor: pointer; justify-content: center; }
.more-toggle:checked ~ .more-btn { display: none; }
.more-toggle:focus-visible ~ .more-btn { outline: 2px solid var(--indigo); outline-offset: 3px; }

/* ---- Numbered option cards -------------------------------------------
   The numeral is part of the <h3>, displayed above the word. It is a numbering
   device, not a label line: an eyebrow above a heading is banned framework-wide. */
.cards-3 { grid-template-columns: repeat(3, 1fr); }
.card-num .num {
  display: block;
  font-family: Georgia, "Times New Roman", serif;
  font-size: 0.95rem;
  letter-spacing: 0.06em;
  color: var(--gold, #8C7F55);
  margin-bottom: 0.35rem;
}
.card-lead { font-weight: 600; margin-bottom: 0.5rem; }
.card-num p { color: var(--ink-soft); font-size: 0.97rem; margin: 0; }
.card-num .card-lead { color: var(--ink); }
.btn-row-center { display: flex; justify-content: center; margin-top: 2.5rem; }

@media (max-width: 62rem) { .cards-3 { grid-template-columns: 1fr; } }

/* Whole-card click target. The button's own <a> is stretched across the card by
   ::after, so there is exactly one link per card and no nested anchors. */
.card-num { position: relative; transition: border-top-color .15s ease, transform .15s ease; }
.card-num:hover { border-top-color: var(--gold-bright, #C9A227); transform: translateY(-2px); }
.card-num:focus-within { outline: 2px solid var(--indigo); outline-offset: 3px; }
.card-cta { margin-top: auto; padding-top: 1.25rem; }
.card-cta .btn { width: 100%; justify-content: center; text-align: center; }
.stretch::after { content: ""; position: absolute; inset: 0; z-index: 1; }

/* ---- Shared service-page template ------------------------------------
   Every Services child page renders through service_page() in build-site.py,
   so these rules are the single definition of how a service page looks. Change
   one here and every service page changes with it - that is the point. */
.svc-intro { max-width: 84ch; }
.svc-intro p + p { margin-top: 1rem; }
.svc-text { max-width: 84ch; }
.svc-text p + p { margin-top: 1rem; }
.svc-hero-shot img { width: 100%; height: auto; display: block; border-radius: 12px; }

.cards-4 { grid-template-columns: repeat(4, 1fr); }
.steps-4 { grid-template-columns: repeat(4, 1fr); }

.svc-gallery {
  display: grid; gap: clamp(1rem, 2vw, 1.5rem);
  grid-template-columns: repeat(3, 1fr);
}
.svc-gallery img, .svc-slide img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block;
  background: var(--hair-warm);
}
.svc-gallery figcaption, .svc-slide figcaption {
  font-size: 0.87rem; color: var(--ink-soft); margin-top: 0.5rem;
}
.svc-ba { display: grid; gap: 1.5rem; grid-template-columns: repeat(2, 1fr); }
.svc-ba-pair { display: grid; grid-template-columns: 1fr 1fr; gap: 0.5rem; }
.svc-ba-pair img { width: 100%; aspect-ratio: 1; object-fit: cover; }
/* The caption belongs to the pair, so it spans both columns. Without this it
   lands in the next grid cell - one column wide, under the left-hand picture
   only - and at 1440 that is 250px against the pair's 508, which wrapped
   "Wheels and details - before and after" onto a second line for no reason.
   The mobile block already spanned it; this is the same rule at every width,
   and the mobile one still centres the text on top. */
.svc-ba-pair figcaption { grid-column: 1 / -1; }

.svc-table-wrap { overflow-x: auto; }
.svc-table { width: 100%; border-collapse: collapse; font-size: 0.95rem; }
.svc-table th, .svc-table td {
  text-align: left; padding: 0.75rem 0.9rem; border-bottom: 1px solid var(--hair);
}
.svc-table th { font-weight: 600; border-bottom: 2px solid var(--indigo); }

.svc-quotes { display: grid; gap: 1.25rem; grid-template-columns: repeat(2, 1fr); }
.svc-quotes blockquote {
  margin: 0; padding: 1.4rem 1.6rem; background: var(--paper);
  border-left: 3px solid var(--gold, #8C7F55);
}
.svc-quotes cite { display: block; margin-top: 0.75rem; font-style: normal;
                   font-size: 0.87rem; color: var(--ink-soft); }
/* Every sourced module prints where its claim comes from. Clause 7.8(c). */
.svc-source { margin-top: 0.9rem; font-size: 0.82rem; color: var(--ink-soft); }

.svc-cta { text-align: center; max-width: 84ch; }
.svc-cta .lede { max-width: 76ch; margin: 1.1rem auto 0; }

@media (max-width: 62rem) {
  .cards-4, .steps-4 { grid-template-columns: repeat(2, 1fr); }
  .svc-gallery { grid-template-columns: repeat(2, 1fr); }
  .svc-quotes, .svc-ba { grid-template-columns: 1fr; }
}
@media (max-width: 38rem) {
  .cards-4, .steps-4, .svc-gallery { grid-template-columns: 1fr; }
}

/* Two or three labelled lists side by side - the factors in a decision, not
   figures. Nothing here states a number; see rail 3 on COE. */
.svc-columns { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
.svc-columns-2 { grid-template-columns: repeat(2, 1fr); }
.svc-columns-3 { grid-template-columns: repeat(3, 1fr); }
.svc-column {
  background: #fff;
  border: 1px solid var(--hair-warm);
  border-top: 3px solid var(--gold, #8C7F55);
  padding: clamp(1.4rem, 2.4vw, 1.9rem);
}
.svc-column h3 { margin-bottom: 0.9rem; font-size: clamp(1.1rem, 1.6vw, 1.28rem); }
.svc-column .ticks { margin: 0; }

@media (max-width: 52rem) { .svc-columns-2, .svc-columns-3 { grid-template-columns: 1fr; } }

/* Sister-brand logos. Inside the <h3> so the alt text is the heading: the page
   outline is unchanged and the brand name is still announced. No chip needed now
   the panel is light - both files are dark-on-light artwork. */
.brandpanel .brand-logo {
  margin: 0 auto 2rem;
  height: 54px;
  display: flex;
  align-items: center;
  justify-content: center;
}
.brandpanel .brand-logo img { max-height: 100%; max-width: 210px; width: auto; height: auto; }
@media (max-width: 38rem) {
  .brandpanel .brand-logo { height: 44px; }
  .brandpanel .brand-logo img { max-width: 170px; }
}


/* Buttons centred inside their grid column. Scoped rather than added to
   .btn-row, which is used site-wide and should stay left-aligned by default. */
.btn-row-mid { justify-content: center; }

/* The actual number / address on each contact card, set apart from the
   description above it so it can be read at a glance. */
.contact-value {
  font-family: var(--serif);
  font-size: 1.1rem;
  margin: auto 0 0;
  padding-top: 1rem;
  word-break: break-word;
}
.contact-value a { display: inline-flex; align-items: baseline; gap: 0.4rem; }
.card-num:hover .contact-value a { text-decoration: underline; }
.contact-value a { color: var(--indigo); text-decoration: none; }
.contact-value a:hover { text-decoration: underline; }

/* Label / value pairs on the contact page. A <dl> rather than a table: these are
   name-value pairs, not tabular data, and it reads correctly to a screen reader. */
.visit-details {
  display: grid;
  grid-template-columns: max-content 1fr;
  gap: 0.9rem 1.75rem;
  margin: 1.75rem 0 0;
  font-size: 0.97rem;
}
.visit-details dt {
  font-size: 0.76rem; letter-spacing: 0.14em; text-transform: uppercase;
  font-weight: 600; color: var(--ink-faint); padding-top: 0.22rem;
}
.visit-details dd { margin: 0; color: var(--ink-soft); line-height: 1.6; }
.visit-details dd a { color: var(--indigo); }
@media (max-width: 34rem) {
  .visit-details { grid-template-columns: 1fr; gap: 0.3rem; }
  .visit-details dt { padding-top: 0.9rem; }
}

/* Design credit, opposite the copyright. The footer is dark, so the link takes
   the footer's own link colour rather than the page default. */
.footer-credit { color: rgba(255,255,255,0.42); font-size: 0.74rem; }
.footer-credit a { color: rgba(255,255,255,0.58); text-decoration: none; }
.footer-credit a:hover { color: rgba(255,255,255,0.9); text-decoration: underline;
                         text-underline-offset: 2px; }

/* ==========================================================================
   v2 STYLE LAYER — after joinsparq.com
   --------------------------------------------------------------------------
   What was taken from the reference, measured from its own page source:

     radii      24px / 16px / 12px, and 999px pills on buttons
     surfaces   a flat neutral ramp - #fafafa, #f5f5f5, #e5e5e5 - with cards
                sitting on tinted bands rather than being outlined
     type       Inter and Inter Tight: a geometric sans, tight tracking,
                headings not much larger than the body copy
     rhythm     centred section headings, wide gutters, big gaps between
                sections, everything on one measure

   What was NOT taken:
     their accent is #fe522e. PRM keeps indigo and gold. The page stays light.
     No pill or badge is placed above a heading - that is an eyebrow, and
     eyebrows are banned framework-wide. Pills are used on buttons only.

   All components are unchanged - the cards, accordion, tiles, tables, map,
   bands and mobile menu are the same markup as before.
   ========================================================================== */

:root {
  --shell: 1180px;
  --gut: clamp(1.25rem, 4vw, 3rem);

  /* the neutral ramp, in PRM's warm cast rather than the reference's grey */
  --n-50:  #FBFAF8;
  --n-100: #F5F4F1;
  --n-200: #E8E6E1;
  --n-400: #9A968E;
  --n-600: #5D5A54;

  --r-lg: 20px;
  --r-md: 16px;
  --r-sm: 12px;
}

/* ---- type: sans-led, tight, modest in scale ---------------------------- */
h1, h2, h3, .car-price, .stats b {
  font-family: var(--sans);
  letter-spacing: -0.028em;
  font-weight: 650;
}
h1 { font-size: clamp(2.1rem, 4.4vw, 3.4rem); line-height: 1.06; }
h2 { font-size: clamp(1.55rem, 2.6vw, 2.2rem);  line-height: 1.12; }
h3 { font-size: clamp(1.05rem, 1.5vw, 1.2rem);  line-height: 1.25; letter-spacing: -0.015em; }
/* the italic second line of a hero keeps the serif - it is the one place PRM's
   own voice shows through, and losing it would make this someone else's site */
h1 em { font-family: var(--serif); font-weight: 500; letter-spacing: -0.01em; }
.lede { font-size: clamp(1rem, 1.25vw, 1.12rem); color: var(--n-600); max-width: 68ch; }

/* ---- rhythm ------------------------------------------------------------- */
.section { padding-block: clamp(3.5rem, 8vh, 6.5rem); }
.section-warm { background: var(--n-100); }
.hero { padding-block: clamp(3rem, 7vh, 5.5rem) clamp(2.5rem, 5vh, 4rem); }

/* Centred section headings, as the reference does throughout. The copy block
   is centred with it so the two do not disagree. */
.section-head { text-align: center; margin-inline: auto; max-width: 82ch; }
.section-head .lede { margin-inline: auto; }
/* except where a section is a two-column row - centring there looks accidental */
.grid-2 .section-head, .hero .section-head { text-align: left; margin-inline: 0; }

/* ---- surfaces: soft, rounded, unoutlined ------------------------------- */
.card, .postcard, .car, .svc-column, .panel, .map-card, .brandpanel {
  background: var(--paper);
  border: 1px solid var(--n-200);
  border-radius: var(--r-lg);
  box-shadow: none;
  transition: border-color .18s ease, box-shadow .18s ease, transform .18s ease;
}
.card:hover, .postcard:hover, .car:hover, .svc-column:hover {
  border-color: var(--n-400);
  box-shadow: 0 18px 40px -30px rgba(11,11,12,0.45);
  transform: translateY(-2px);
}
/* the coloured top rule goes - the reference separates by surface, not by line */
.card, .card:nth-child(2), .card:nth-child(3), .card:nth-child(4),
.svc-column, .brandpanel { border-top-width: 1px; border-top-color: var(--n-200); }
.pillar, .step { border-top: 2px solid var(--n-200); }

.car, .postcard { overflow: hidden; padding: 0; }
.card, .svc-column { padding: clamp(1.35rem, 2.2vw, 1.85rem); }
.car-shot img, .postcard-shot { border-radius: 0; }

/* ---- buttons become pills ---------------------------------------------- */
.btn {
  border-radius: 999px;
  padding: 0.78rem 1.5rem;
  font-weight: 600;
  letter-spacing: 0.01em;
  text-transform: none;
  font-size: 0.92rem;
}
.btn-sm { padding: 0.6rem 1.1rem; font-size: 0.82rem; }
.btn-primary { background: var(--indigo); border-color: var(--indigo); }
.btn-primary:hover { background: var(--indigo-deep); border-color: var(--indigo-deep); }
.btn-ghost { border-color: var(--n-200); color: var(--ink); background: var(--paper); }
.btn-ghost:hover { border-color: var(--ink); background: var(--paper); color: var(--ink); }
.more-btn { border-radius: 999px; }

/* ---- equal tiles, on one grid ------------------------------------------ */
.cards { gap: clamp(0.9rem, 1.6vw, 1.35rem); }
@media (min-width: 62rem) {
  .cards-4 { grid-template-columns: repeat(4, 1fr); }
  .cars-grid { grid-template-columns: repeat(3, 1fr); }
  .posts { grid-template-columns: repeat(4, 1fr); }
}

/* ---- accordion, table, small print ------------------------------------- */
.qa { border-color: var(--n-200); }
.qa > summary { padding-block: 1.15rem; }
.svc-table th, .svc-table td { border-bottom-color: var(--n-200); }
.svc-table th { border-bottom: 2px solid var(--n-200); }
.visit-details dt, .car-specs dt, .stats span { color: var(--n-400); }

/* ---- the full-bleed photo band ----------------------------------------- */
.band {
  position: relative;
  width: 100vw;
  margin-inline: calc(50% - 50vw);
  overflow: hidden;
  line-height: 0;
  background: var(--n-100);
}
/* No fixed height, so nothing is cropped. The band is full-bleed, so the
   picture already spans the viewport width - at a fixed height the only thing
   a crop can do is cut the top and bottom off, which on the frontage shot
   meant losing the workshop under the sign. Letting the height follow the
   image shows the whole frame at every width, and the aspect ratio does the
   work that a media query used to.

   The cap is in vw, not rem, so the same share of the picture shows at every
   width. A fixed cap does not: 44rem is 81% of the image at 1440px wide but
   only 46% at 2560, which puts an ultrawide screen back to sign-and-ceiling
   with the workshop cut off. The rem term is an absolute ceiling so the band
   cannot take over a very large monitor. The cap crops rather than letterboxes,
   which is why object-position still matters above it. */
.band { height: auto; max-height: min(54vw, 46rem); }
.band img {
  width: 100%;
  height: auto;
  object-fit: cover;
  /* Framed on the signboard, which is what the picture is for. 15% down keeps
     the whole board on a wide screen, where the band is about 3.5:1 and crops
     top and bottom. 40% across matters on a phone, where it crops the SIDES
     instead: centred at 50% the board's left edge falls off and the page leads
     with PORSCHIFY rather than PRM GROUP. The board's own centre is at 40%. */
  object-position: 40% 12%;
  display: block;
}
/* full-bleed blocks use 100vw, which counts the scrollbar */
html, body { overflow-x: clip; }

/* ---- masthead ----------------------------------------------------------- */
.masthead { background: rgba(251,250,248,0.92); border-bottom: 1px solid var(--n-200); }
.nav a { font-weight: 550; letter-spacing: 0; text-transform: none; font-size: 0.95rem; }
.sub { border-radius: var(--r-md); border-color: var(--n-200); }

/* ==========================================================================
   MOBILE MENU — photo tiles, kept from the previous build
   ========================================================================== */
.menu-toggle {
  position: absolute; width: 1px; height: 1px;
  clip: rect(0 0 0 0); clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}
/* .menu-close was in here too; it is shown by the mobile panel rules and
   hiding it at base meant fighting this declaration from three layers away */
.menu-btn { display: none; }
.menu-close { display: none; }

/* .masthead carries a backdrop-filter, and a filtered element becomes the
   containing block for its fixed descendants - the overlay would be only as
   tall as the header. */
html:has(.menu-toggle:checked) .masthead {
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
html:has(.menu-toggle:checked) { overflow: hidden; }

@media (max-width: 980px) {
  .topbar { display: none; }

  .menu-btn {
    display: flex; align-items: center; justify-content: center;
    margin-left: auto; width: 44px; height: 44px; cursor: pointer;
  }
  .menu-bars, .menu-bars::before, .menu-bars::after {
    content: ""; display: block; width: 24px; height: 2px;
    background: var(--ink); transition: transform .25s ease;
  }
  .menu-bars { position: relative; }
  .menu-bars::before { position: absolute; top: -7px; }
  .menu-bars::after  { position: absolute; top: 7px; }
  .menu-toggle:checked ~ .menu-btn { position: relative; z-index: 80; }
  .menu-toggle:checked ~ .menu-btn .menu-bars { background: transparent; }
  .menu-toggle:checked ~ .menu-btn .menu-bars::before { transform: translateY(7px) rotate(45deg); }
  .menu-toggle:checked ~ .menu-btn .menu-bars::after  { transform: translateY(-7px) rotate(-45deg); }
  .menu-toggle:focus-visible ~ .menu-btn { outline: 3px solid var(--gold-bright); outline-offset: 2px; }
















}

/* ==========================================================================
   v2 STYLE LAYER, PASS 2 — the composition, not the trim
   --------------------------------------------------------------------------
   Pass 1 changed radii, type and colour and the page still read as the old
   one, because none of that is what makes the reference look the way it does.
   This pass changes the composition:

     1. the hero is centred, and it is the only thing on the screen
     2. the navigation becomes a pill, with the last item as a filled button
     3. the indigo utility strip goes - nothing in that genre has one
     4. sections get roughly double the air
     5. cards are image-led, heavily rounded, and sit on a tinted ground
     6. the footer is a dark rounded slab, not a full-width band

   PRM's colours are untouched. The page stays light.
   ========================================================================== */

/* ---- 1. the hero, centred ---------------------------------------------- */
.hero .shell { text-align: center; }
.hero .shell.hero-grid { text-align: left; }        /* the two-column heroes keep their shape */
.hero h1 {
  font-size: clamp(2.6rem, 5.6vw, 4.6rem);
  line-height: 1.04;
  letter-spacing: -0.035em;
  max-width: 30ch;
  margin-inline: auto;
}
.hero .shell:not(.hero-grid) .lede {
  margin-inline: auto;
  text-align: center;
  font-size: clamp(1.05rem, 1.35vw, 1.22rem);
  max-width: 82ch;
}
.hero .shell:not(.hero-grid) .btn-row { justify-content: center; }
.hero { padding-block: clamp(4rem, 11vh, 8rem) clamp(3.5rem, 9vh, 6.5rem); }

/* ---- 2. the navigation as a pill --------------------------------------- */
@media (min-width: 981px) {
  .masthead {
    background: transparent;
    border-bottom: 0;
    backdrop-filter: none;
    padding-block: 0.9rem;
  }
  .masthead .shell {
    min-height: 0;
    background: var(--paper);
    border: 1px solid var(--n-200);
    border-radius: 999px;
    padding: 0.45rem 0.55rem 0.45rem 1.5rem;
    gap: 1.25rem;
    box-shadow: 0 14px 38px -28px rgba(11,11,12,0.55);
  }
  .brand img { height: 34px; width: auto; }
  .nav {
    background: transparent;
    border: 0;
    border-radius: 0;
    padding: 0;
    gap: 1.6rem;
    box-shadow: none;
  }
  .nav > a { padding: 0.55rem 0; font-size: 0.92rem; }
  .nav a::after { display: none; }          /* the underline marker goes with the pill */
  /* the last item becomes the button, as the reference does with "Buy now" */
  .nav > a:last-of-type {
    background: var(--indigo);
    color: #fff;
    border-radius: 999px;
    padding: 0.62rem 1.35rem;
    margin-left: 0.55rem;
  }
  .nav > a:last-of-type:hover { background: var(--indigo-deep); color: #fff; }
  .nav a[aria-current="page"] { color: var(--indigo); }
}

/* ---- 3. the utility strip goes ----------------------------------------- */
/* An indigo bar of address and phone above the logo is the single strongest
   signal that this is a 2016 template. The address and number are on /contact,
   in the footer and in the schema, so nothing is lost. */
.topbar { display: none; }

/* ---- 4. air ------------------------------------------------------------ */
.section { padding-block: clamp(4.5rem, 11vh, 8.5rem); }
.section-head { margin-bottom: clamp(2.25rem, 4.5vh, 3.5rem); }
.section-head h2 { max-width: 30ch; margin-inline: auto; margin-bottom: 1.1rem; }
.section-head .lede { margin-top: 0; }
/* the same gap in the hero, where the lede carries an inline margin-top */
.hero .lede { margin-top: 1.25rem !important; }

/* ---- 5. cards: image-led, round, on a tinted ground --------------------- */
.card, .postcard, .car, .svc-column, .panel {
  border-radius: var(--r-lg);
  border: 0;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(11,11,12,0.04), 0 12px 32px -28px rgba(11,11,12,0.5);
}
.card:hover, .postcard:hover, .car:hover, .svc-column:hover {
  box-shadow: 0 1px 2px rgba(11,11,12,0.05), 0 26px 50px -30px rgba(11,11,12,0.55);
  transform: translateY(-3px);
  border: 0;
}
.card, .svc-column { padding: clamp(1.6rem, 2.6vw, 2.2rem); }
/* every card group now sits on the tinted ground, which is what makes the
   cards read as objects rather than as boxes drawn on the page */
.section:has(.cards), .section:has(.cars-grid), .section:has(.posts) {
  background: var(--n-100);
}
.section-warm:has(.cards) { background: var(--n-100); }

/* pictures fill the top of their card, corners and all */
.car-shot, .postcard-shot { border-radius: var(--r-lg) var(--r-lg) 0 0; overflow: hidden; }
.car-shot img { border-radius: 0; }

/* ---- 6. the footer as a dark slab -------------------------------------- */
.footer {
  background: var(--ink);
  border-radius: 0;
  margin-top: 0;
  padding-block: clamp(3.5rem, 8vh, 6rem) 2rem;
}
.footer h4 { color: var(--gold-bright); }
.footer-base { border-top-color: rgba(255,255,255,0.14); }

/* ---- small print ------------------------------------------------------- */
.rule-gradient { display: none; }     /* the gradient rule belonged to the old masthead */
.wa-float { border-radius: 999px; }

/* ---- One rule for every heading + supporting line ----------------------
   Three patterns carry an <h2> with a .lede under it: .section-head (38 of
   them), the final CTA blocks on the service pages (5), and the two-column
   rows (6). They had three different gaps and three different measures. The
   !important is needed because those ledes carry an inline margin-top in the
   markup, which would otherwise win. */
.section-head h2,
.svc-cta h2,
.grid-2 h2 { margin-bottom: 1.1rem; }

.section-head .lede,
.svc-cta .lede,
.grid-2 .lede { margin-top: 0 !important; }

/* the same measure, wherever the pair appears */
.svc-cta { max-width: 82ch; }
.svc-cta h2 { max-width: 30ch; margin-inline: auto; }
.svc-cta .lede { max-width: 72ch; margin-inline: auto; }

/* hero sub-headlines share one measure, centred or two-column */
.hero .lede { max-width: 82ch; }
@media (min-width: 62rem) { .hero-grid .lede { max-width: 58ch; } }

/* "Ready to sell?" - the heading is centred, so the six pointers and the
   buttons under them were the only left-aligned things in the section. The
   grid is narrowed and centred, each pointer centres its icon and label, and
   the button row follows. Scoped to the section that has pointers. */
.pointers {
  max-width: 62rem;
  margin-inline: auto;
  justify-items: center;
}
.pointer { justify-content: center; text-align: left; }
.section:has(.pointers) .btn-row { justify-content: center; }

/* A two-column row whose second column is just buttons: centre them in that
   column, horizontally and vertically. Left-aligned they sit against the gap
   between the columns and read as unplaced. This replaces the one-off
   .btn-row-mid added earlier for a single row on /about-us. */
.grid-2 > .btn-row {
  justify-content: center;
  align-self: center;
}

/* The brand panels were running the full shell with heavy interior padding,
   so two short cards spread across 1180px. Narrowed and tightened. */
.brandpanels { max-width: 56rem; margin-inline: auto; gap: 1.1rem; }
.brandpanel { padding: clamp(1.5rem, 2.6vw, 2.1rem) clamp(1.25rem, 2.2vw, 1.75rem); }
.brandpanel .tag { margin-bottom: 1rem; }
.brandpanel p { margin-bottom: 1.25rem; }

/* Hero width back on the page measure. The long headlines are handled by
   setting the type down rather than by widening the container. */
.hero h1 {
  font-size: clamp(2.2rem, 4.4vw, 3.5rem);
  max-width: 34ch;
}
.hero .shell:not(.hero-grid) .lede {
  font-size: clamp(0.98rem, 1.15vw, 1.08rem);
  max-width: 78ch;
}

/* ==========================================================================
   MOBILE CAROUSELS
   Card groups become a swipeable rail below 62rem, with arrows at each side.
   The arrows are anchors to the neighbouring slide - the visible slide's own
   pair is the pair you see, so two links behave like carousel controls with
   no script. scroll-behavior: smooth on the rail makes the jump a glide.
   ========================================================================== */

@media (max-width: 62rem) {
  .cards, .cars-grid, .posts, .brandpanels, .cars-rail, .stats, .steps,
  .svc-ba, .svc-gallery {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: 100%;
    grid-template-columns: none;
    gap: 0.75rem;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    overscroll-behavior-x: contain;
    margin-inline: 0;
    padding-inline: 0;
    padding-block: 0.25rem 0.75rem;
    scrollbar-width: none;
  }
  .cards::-webkit-scrollbar, .cars-grid::-webkit-scrollbar,
  .posts::-webkit-scrollbar, .brandpanels::-webkit-scrollbar,
  .cars-rail::-webkit-scrollbar, .stats::-webkit-scrollbar,
  .steps::-webkit-scrollbar { display: none; }

  /* the earlier mobile rule forced every tile to span the full row */
  .cards > *, .cars-grid > *, .posts > *, .brandpanels > *, .cars-rail > *,
  .stats > *, .steps > *, .svc-ba > *, .svc-gallery > * {
    grid-column: auto !important;
    scroll-snap-align: center;
    position: relative;
  }




}

/* The stats carousel: one figure at a time, centred, with room for the arrows
   so a long number never runs under them. */
@media (max-width: 62rem) {
  .stats { text-align: center; }
  .stats > li { padding-inline: 3.25rem; }
  .stats li + li::before { display: none; }   /* the divider belonged to the row */
  .stats b { font-size: clamp(2.6rem, 14vw, 3.6rem); }
}

/* More room between a section's buttons and the map beneath them on mobile. */
@media (max-width: 62rem) {
  .grid-2 > .btn-row { margin-bottom: 0.75rem; }
  .map-card { margin-top: 1.5rem; }
}

/* With the menu open the header capsule floats above the overlay, so the logo
   stays on the left and the cross on the right - one bar, as on the reference. */
html:has(.menu-toggle:checked) .masthead { z-index: 90; }

/* The Services submenu inside the open mobile menu: a plain stacked list.
   Pinned explicitly rather than left to inherit - it was rendering as a row
   with its own sideways scroll, and nothing in the sheet should have made it
   one. Written at full strength so no later rule can turn it back. */
@media (max-width: 980px) {





}

/* The parent too: a flex item that stays block and full width, so its list
   cannot be laid out across the row. */
@media (max-width: 980px) {



}

/* The nowrap I added to stop the submenu going sideways made every item in the
   column shrinkable, so they compressed into each other. Items keep their own
   height and the list gets its spacing back. */
@media (max-width: 980px) {







}

/* Tighter under the close cross, and Contact pinned to the foot of the menu.
   The nav is the scrolling element, so position: sticky on the last link keeps
   the button in view while the list scrolls behind it - no script. */
@media (max-width: 980px) {



}

/* The main menu links set smaller - they were at display size and crowding the
   list. The Contact button keeps its own size, being a button. */
@media (max-width: 980px) {



}

/* No rules in the submenu. The lines came from the ported sheet's mobile rule
   `.nav a { border-bottom: 1px solid var(--hair) }`, which catches every anchor
   in the nav including these, plus the divider I had added before the two
   sister-company links. All of it off, and the list tightened. */
@media (max-width: 980px) {




}

/* Mobile footer: the Cars and Company link columns come out, leaving the brand
   block and Contact. Both columns only repeat the main navigation, which is a
   tap away in the menu; the contact details are the one thing the footer holds
   that the nav does not.
   Targeted by position because the columns carry no classes of their own:
   1 = brand block, 2 = Cars, 3 = Company, 4 = Contact. */
@media (max-width: 62rem) {
  .footer-grid > div:nth-child(2),
  .footer-grid > div:nth-child(3) { display: none; }
  .footer-grid { gap: 1.5rem; }
}

/* Step cards in the carousel need room for the arrows, same as the stats. */
@media (max-width: 62rem) {
  .steps > .step { padding-inline: 2.75rem; }
}

/* The arrows were sitting on the copy. They move out to the very edge of the
   rail, get a little smaller, and every slide type gets enough side padding to
   clear them - cards included, which had only their own 1.35rem. */
@media (max-width: 62rem) {

  .steps > .step { padding-inline: 2.9rem !important; }
  .stats > li { padding-inline: 2.9rem !important; }
  .cards > .card, .svc-columns > .svc-column { padding-inline: 2.9rem !important; }
  .brandpanels > .brandpanel { padding-inline: 2.9rem !important; }
  /* the picture tiles keep their image full-bleed; only the text under it moves in */
  .cars-grid > .car .car-body,
  .cars-rail > .car .car-body,
  .posts > .postcard .postcard-body { padding-inline: 2.9rem !important; }
}

/* Nothing peeks in from the sides: the gap only applies between slides while
   scrolling, never at rest. */
@media (max-width: 62rem) {
  .cards, .cars-grid, .posts, .brandpanels, .cars-rail, .stats, .steps,
  .svc-ba, .svc-gallery { gap: 0 !important; }
}

/* ---- Carousel arrows (fixed, script-driven) ----------------------------
   The buttons sit on the shell, outside the scrolling rail, so they hold
   their place while the slides move. Hidden until carousel.js marks the
   shell ready - an arrow that does nothing is worse than no arrow. */
.cx { position: relative; }
.cx-btn { display: none; }

@media (max-width: 62rem) {
  .cx-ready .cx-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 4;
    width: 34px;
    height: 34px;
    padding: 0 0 2px;
    border-radius: 999px;
    border: 1px solid var(--n-200);
    background: rgba(255,255,255,0.96);
    box-shadow: 0 6px 18px -10px rgba(11,11,12,0.5);
    color: var(--ink);
    font: 1.4rem/1 var(--sans);
    cursor: pointer;
  }
  .cx-ready .cx-prev { left: -0.35rem; }
  .cx-ready .cx-next { right: -0.35rem; }
  .cx-btn:active { background: #fff; }
  .cx-btn:focus-visible { outline: 3px solid var(--gold-bright); outline-offset: 2px; }
}

/* "Ready to sell?" on mobile: the six pointers align left on their icons, so
   the icon column makes a straight edge down the list. Centred, every row
   started at a different x depending on how long its label was. Desktop keeps
   the centred arrangement, where the columns do the aligning. */
@media (max-width: 62rem) {
  .pointers { justify-items: start; max-width: none; }
  .pointer { justify-content: flex-start; text-align: left; width: 100%; }
  .section:has(.pointers) .btn-row { justify-content: center; }
}

/* /buy on mobile: the whole listing is in the carousel, so the six-card cap
   and the Load more button both come off. They exist to stop a long grid
   filling the page on desktop; in a carousel there is nothing to cap - you
   swipe past what you are not interested in. */
@media (max-width: 62rem) {
  .cars-grid.is-capped > .car:nth-child(n+7) { display: flex !important; }
  .more-btn { display: none !important; }
}

/* One before/after pair per slide: the two pictures stay side by side inside
   the slide, with room at the edges for the arrows. */
@media (max-width: 62rem) {
  .svc-ba > .svc-ba-pair {
    display: grid !important;
    grid-template-columns: 1fr 1fr !important;
    gap: 0.4rem;
    padding-inline: 2.6rem;
  }
  .svc-ba-pair figcaption { grid-column: 1 / -1; text-align: center; }
}

/* The pair was collapsing to the images' intrinsic size instead of filling the
   slide - the mockup is an SVG, and an SVG with no width/height attributes
   reports a small intrinsic size, so `width: 100%` had nothing to resolve
   against. The slide and its columns are pinned explicitly. */
@media (max-width: 62rem) {
  .svc-ba > .svc-ba-pair {
    width: 100% !important;
    padding-inline: 2.4rem !important;
    align-content: start;
  }
  .svc-ba-pair img {
    width: 100% !important;
    height: auto !important;
    min-width: 0;
    aspect-ratio: 4 / 3 !important;
    object-fit: cover;
    display: block;
  }
  .svc-ba-pair figcaption { margin-top: 0.6rem; }
}

/* ---- Tap to enlarge: before/after ------------------------------------
   The overlay is shown by :target - the thumbnail links to its id - so
   opening and closing needs no script. The carousel inside is a .cx shell
   and gets its arrows from carousel.js like every other rail. */
.lb {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(8,8,10,0.94);
  padding: 3.5rem 1rem 2rem;
  flex-direction: column;
  justify-content: center;
}
.lb:target { display: flex; }
.lb-close {
  position: absolute;
  top: 0.75rem;
  right: 1rem;
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 1.9rem;
  line-height: 1;
  color: #fff;
  text-decoration: none;
  border-radius: 999px;
}
.lb-close:hover { background: rgba(255,255,255,0.12); }
.lb-rail {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  gap: 0;
  scrollbar-width: none;
}
.lb-rail::-webkit-scrollbar { display: none; }
.lb-slide {
  scroll-snap-align: center;
  margin: 0;
  padding-inline: 2.6rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
}
.lb-slide img {
  width: 100%;
  height: auto;
  max-height: 68svh;
  object-fit: contain;
  border-radius: var(--r-sm);
}
.lb-slide figcaption,
.lb-cap {
  color: rgba(255,255,255,0.78);
  font-size: 0.85rem;
  text-align: center;
  margin-top: 0.75rem;
}
.lb-cap { color: #fff; font-size: 0.95rem; margin-top: 1.25rem; }
/* the arrows inside the overlay are visible at every width, unlike the page
   rails which only carousel on mobile */
.lb-cx.cx-ready .cx-btn { display: flex; }
.lb .cx-btn { background: rgba(255,255,255,0.92); border-color: transparent; }
.lb-open { display: block; cursor: zoom-in; }

/* More of the screen given to the picture: less padding around the overlay,
   less inside the slide, and a taller cap. The arrows sit over the edges of
   the image rather than beside it, which is normal for a lightbox. */
.lb { padding: 3.25rem 0.5rem 1.25rem; }
.lb-slide { padding-inline: 0.25rem; }
.lb-slide img { max-height: 76svh; }
@media (min-width: 62rem) {
  .lb-slide img { max-height: 80svh; max-width: 1100px; margin-inline: auto; }
}

/* ---- Lightbox, full screen -------------------------------------------
   The picture fills the viewport and the words sit over the bottom of it on
   a gradient, so nothing competes with the image for space. */
.lb { padding: 0; }
.lb-rail { height: 100svh; }
.lb-slide {
  position: relative;
  height: 100svh;
  padding: 0;
  justify-content: flex-start;
}
.lb-slide img {
  width: 100%;
  height: 100%;
  max-height: none;
  max-width: none;
  object-fit: cover;          /* fills the frame - see the note on cropping */
  border-radius: 0;
  margin: 0;
}
/* the scrim only exists so the caption stays readable over a light picture */
.lb-slide::after {
  content: "";
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 42%;
  pointer-events: none;
  background: linear-gradient(to top, rgba(0,0,0,0.78) 8%, rgba(0,0,0,0.35) 45%, transparent);
}
.lb-slide figcaption {
  position: absolute;
  left: 1.25rem; right: 1.25rem; bottom: 3.5rem;
  z-index: 2;
  margin: 0;
  color: rgba(255,255,255,0.85);
  font-size: 0.85rem;
  text-align: center;
}
.lb-cap {
  position: absolute;
  left: 1.25rem; right: 1.25rem; bottom: 1.5rem;
  z-index: 2;
  margin: 0;
  color: #fff;
  font-size: 1rem;
  font-weight: 600;
  text-align: center;
}
.lb-close { top: 1rem; right: 1rem; background: rgba(0,0,0,0.45); }
@media (min-width: 62rem) {
  .lb-slide img { max-height: none; max-width: none; margin-inline: 0; }
}

/* Close and arrows were painting underneath the picture. Both are positioned
   with z-index auto, and the .cx shell that holds the image comes after the
   close link in the DOM - so it won over it. Explicit layers fix the order. */
/* ---- Lightbox on a desktop: a panel, not the whole window ---------------
   The full-screen treatment above is right on a phone, where the picture is
   the screen and the words sit over it. On a desktop it meant height:100svh
   and object-fit:cover, which both fills the entire window and crops the
   photograph to do it - the overlay read as too big, and you saw less of the
   picture than before it opened.

   Above 62rem the picture is contained instead: whole frame, centred, capped,
   with the caption under it on the dark ground rather than printed over the
   image. The scrim goes with it - it exists to keep white text readable over
   a light photograph, and there is no text on the image any more. */
@media (min-width: 62rem) {
  .lb { padding: 4rem 1.5rem 2rem; justify-content: center; }
  .lb-rail { height: auto; }
  .lb-slide {
    height: auto;
    padding: 0 0.5rem;
    justify-content: center;
    align-items: center;
  }
  .lb-slide img {
    width: auto;
    height: auto;
    max-height: 74svh;
    max-width: min(1000px, 86vw);
    object-fit: contain;        /* the whole picture, not a crop of it */
    margin-inline: auto;
    border-radius: 10px;
  }
  .lb-slide::after { display: none; }
  .lb-slide figcaption {
    position: static;
    margin: 0.9rem auto 0;
    color: rgba(255,255,255,0.62);
    font-size: 0.82rem;
  }
  .lb-cap {
    position: static;
    margin: 1.1rem auto 0;
    max-width: 60ch;
  }
}

.lb-close { z-index: 260 !important; }
.lb .cx-btn,
.lb-cx.cx-ready .cx-btn {
  z-index: 250 !important;
  background: rgba(255,255,255,0.95) !important;
  border: 0 !important;
  width: 42px !important;
  height: 42px !important;
  font-size: 1.6rem !important;
  color: #0B0B0C !important;
  box-shadow: 0 6px 20px -8px rgba(0,0,0,0.6) !important;
}
/* The arrows need positioning as well as painting. .cx-btn is only made
   absolute inside @media (max-width: 62rem), because the page rails carousel
   on mobile alone - so above that the lightbox's arrows were position:static,
   every left/right/top below did nothing, and both buttons stacked under the
   picture at the left edge. The car popup hit this and got its own
   width-independent block; the lightbox never did. Same fix, same reason. */
.lb-cx.cx-ready .cx-btn {
  position: absolute !important;
  top: 50% !important;
  transform: translateY(-50%) !important;
  align-items: center;
  justify-content: center;
  border-radius: 999px !important;
  padding: 0 0 2px !important;
  line-height: 1 !important;
  cursor: pointer;
}
.lb-cx.cx-ready .cx-prev { left: 0.75rem !important; right: auto !important; }
.lb-cx.cx-ready .cx-next { right: 0.75rem !important; left: auto !important; }
/* the shell must not create a layer above them */
.lb .cx { position: static; }
.lb-cx { position: relative !important; z-index: 1; }

/* ---- FAQ: heading on the left, questions on the right -----------------
   Desktop only. The section head and the <details> are siblings inside the
   shell, so the shell becomes a two-column grid and each one is placed by
   column - no markup change. The head sticks while the list scrolls past it,
   which is the point of putting it there. */
@media (min-width: 62rem) {
  .section:has(.qa) > .shell {
    display: grid;
    grid-template-columns: 4fr 7fr;
    column-gap: clamp(2.5rem, 6vw, 6rem);
    align-items: start;
  }
  .section:has(.qa) .section-head {
    grid-column: 1;
    grid-row: 1 / span 99;
    text-align: left;
    margin: 0;
    max-width: none;
    position: sticky;
    top: 7rem;
  }
  .section:has(.qa) .section-head h2 { margin-inline: 0; max-width: 16ch; }
  .section:has(.qa) .section-head .lede { margin-inline: 0; }
  .section:has(.qa) .qa { grid-column: 2; }
  /* the first question sits level with the heading */
  .section:has(.qa) .qa:first-of-type { border-top: 0; padding-top: 0; }
  .section:has(.qa) .qa:first-of-type > summary { padding-top: 0; }
}

/* A plus that becomes a minus, rather than a rotating chevron. */
.qa > summary::after {
  content: "+";
  border: 0;
  transform: none;
  width: auto;
  height: auto;
  top: 50%;
  margin-top: -0.72em;
  right: 0;
  font: 300 1.6rem/1 var(--sans);
  color: var(--n-400);
  transition: color .15s ease;
}
.qa[open] > summary::after { content: "\2212"; transform: none; top: 50%; }
.qa > summary:hover::after { color: var(--ink); }
.qa > summary { padding-right: 2.25rem; }

/* The header bar is transparent so the pill floats, which means the page
   scrolls through the gutters either side of it. A band behind the pill fades
   the page out before it reaches the header - the pill still reads as floating,
   but nothing passes behind it.
   It sits at z-index -1 inside the masthead's own stacking context, so it is
   behind the pill and in front of the page. No backdrop-filter: that would make
   the masthead a containing block for the fixed mobile menu again. */
@media (min-width: 981px) {
  .masthead::before {
    content: "";
    position: absolute;
    left: 0; right: 0; top: 0;
    height: calc(100% + 4.5rem);
    z-index: -1;
    pointer-events: none;
    background: linear-gradient(to bottom,
                rgba(251,250,248,1) 0%,
                rgba(251,250,248,1) 34%,
                rgba(251,250,248,0.92) 52%,
                rgba(251,250,248,0.68) 66%,
                rgba(251,250,248,0.34) 80%,
                rgba(251,250,248,0.12) 90%,
                rgba(251,250,248,0) 100%);
  }
}

/* ---- Marque row -------------------------------------------------------
   Logos, greyscale and evenly sized, with the brand name under each. The name
   is always present - hover and focus only lift it - because a touch screen
   has no hover and a screen reader needs it regardless. */
.marques {
  list-style: none;
  margin: 0;
  padding: 0 0 1.25rem;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 1.75rem 2.75rem;
}
.marque {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.5rem;
}
.marque img {
  height: 34px;
  width: auto;
  max-width: 140px;
  object-fit: contain;
  filter: grayscale(1);
  opacity: 0.62;
  transition: opacity .2s ease, filter .2s ease;
}
.marque-name {
  font-family: var(--sans);
  font-size: 0.68rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  font-weight: 600;
  color: var(--n-400);
  /* present for assistive tech, revealed on hover and focus */
  position: absolute;
  bottom: -1.25rem;
  left: 50%;
  transform: translateX(-50%) translateY(3px);
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: opacity .18s ease, transform .18s ease, color .18s ease;
}
.marque { position: relative; }
.marque:hover .marque-name,
.marque:focus-within .marque-name {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
  color: var(--ink);
}
/* On a touch screen the name is not shown at all.
   This block used to do the opposite - no hover to reveal it, so make it
   permanently visible - which put a row of words under every logo on the one
   page that carries the grid, /buy. The logos read perfectly well without
   them, and the marque is in each image's alt text, which is what a screen
   reader and a crawler use regardless. The label was an affordance for a
   pointer; a touch screen has none, so it goes rather than becoming permanent
   furniture. */
@media (hover: none) {
  .marque-name { opacity: 0; }
}
.marque:hover img, .marque:focus-within img { filter: grayscale(0); opacity: 1; }
.marque:hover .marque-name, .marque:focus-within .marque-name { color: var(--ink); }

.marque-more {
  margin: 1.4rem 0 0;
  text-align: center;
  font-family: var(--sans);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--n-400);
}
.marque-note {
  margin: 0.9rem auto 0;
  max-width: 62ch;
  text-align: center;
  font-size: 0.78rem;
  line-height: 1.5;
  color: var(--n-400);
}
@media (max-width: 40rem) {
  .marques { gap: 1.35rem 1.75rem; }
  .marque img { height: 28px; max-width: 110px; }
  .marque-name { font-size: 0.64rem; letter-spacing: 0.12em; }
}

/* The real logos vary wildly in proportion - the BMW roundel is square, the
   Porsche and Lamborghini wordmarks are 9:1. Sizing by height alone would make
   the wordmarks enormous, so each is fitted into a box capped on both axes. */
.marque img { height: auto; max-height: 30px; max-width: 132px; }
.marque { min-width: 132px; }
@media (max-width: 40rem) {
  .marque img { max-height: 24px; max-width: 104px; }
  .marque { min-width: 104px; }
}

/* ---- Marque marquee ----------------------------------------------------
   The row as a section of its own, scrolling slowly across the full width.

   The spacing is a margin on each logo rather than a flex gap, deliberately:
   the track holds the six marques twice and is animated exactly half its own
   width, so the second copy has to land precisely where the first started. A
   gap between items leaves eleven gaps in a twelve-item track, and half of
   that is half a gap out - visible as a jump once a loop. As a margin every
   item measures the same, and half the track is six whole items. */
.section-marquee {
  padding-block: clamp(2rem, 4.5vh, 3.25rem);
  overflow: hidden;
}
.marquee {
  overflow: hidden;
  /* the strip fades out rather than ending at a hard edge */
  -webkit-mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 8%, #000 92%, transparent);
}
.marquee-track {
  display: flex;
  flex-wrap: nowrap;
  justify-content: flex-start;
  gap: 0;
  padding: 0;
  width: max-content;
  animation: marquee-scroll 44s linear infinite;
}
.marquee-track .marque {
  margin-right: 3.5rem;
  flex: 0 0 auto;
}
/* the name is revealed on hover here too, so it stays out of the flow on every
   screen - an inline label would make the items different widths and break the
   seam. The marque is in the image's alt text regardless. */
.marquee-track .marque-name {
  position: absolute;
  transform: translateX(-50%) translateY(3px);
  white-space: nowrap;
  opacity: 0;
}
.marquee-track .marque:hover .marque-name,
.marquee-track .marque:focus-within .marque-name {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
/* stop the strip while someone is reading a name off it */
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }

@keyframes marquee-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@media (prefers-reduced-motion: reduce) {
  .marquee-track { animation: none; }
  .marquee { -webkit-mask-image: none; mask-image: none; }
}
.section-marquee .marque-more { margin-top: 1.1rem; }
@media (max-width: 40rem) {
  .marquee-track .marque { margin-right: 2.25rem; }
  .marquee-track { animation-duration: 30s; }
}

/* No name reveal on a touch screen or a narrow window.
   .marque-name is absolutely positioned and translateX(-50%) from the logo's
   left edge, inside a strip that is overflow:hidden and masked to transparent
   at both ends - so a name revealed anywhere near either edge is clipped. On a
   desktop that barely shows, because the pointer is in the middle of the strip
   and the row is wide. On a phone the strip is narrow, a tap leaves :hover
   stuck on the item it landed on, and the name sits there half cut off with no
   way to dismiss it.
   Nothing is lost by removing it: every logo carries its marque in alt text,
   which is what a screen reader and a search engine read anyway - the visible
   label was only ever a pointer affordance.
   Two queries, because they catch different things: (hover: none) is the real
   test and covers a phone and devtools device emulation, while the width also
   catches a desktop browser dragged narrow, which is how this gets checked. */
@media (hover: none), (max-width: 40rem) {
  .marquee-track .marque:hover .marque-name,
  .marquee-track .marque:focus-within .marque-name {
    opacity: 0;
  }
}

/* ---- Marque row: more air between every part ---------------------------
   The lede, the logos, the "and more" line and the independence note were
   stacked tight enough to read as one block. Scoped away from .marquee-track,
   which shares the .marques class but is a single moving strip with nothing
   above or below it to breathe against. */
.marques:not(.marquee-track) {
  margin-top: clamp(2.25rem, 4.5vh, 3.5rem);
  padding-bottom: 1.5rem;
  row-gap: clamp(2rem, 4vh, 3rem);
}
.marques:not(.marquee-track) + .marque-more { margin-top: clamp(2rem, 4vh, 3rem); }
.marque-more + .marque-note { margin-top: clamp(1.4rem, 2.6vh, 2.1rem); }
.section:has(.marques:not(.marquee-track)) { padding-block: clamp(5rem, 12vh, 9rem); }
@media (max-width: 40rem) {
  .marques:not(.marquee-track) { margin-top: 2rem; row-gap: 1.75rem; }
  .marques:not(.marquee-track) + .marque-more { margin-top: 1.9rem; }
}

/* ---- Marque name: drop it further clear of the logo ---------------------
   The label was sitting hard against the mark it names. The row's own bottom
   padding grows with it, so the caption still has room to appear in and does
   not overlap whatever follows. */
.marque-name { bottom: -1.9rem; }
.marques:not(.marquee-track) { padding-bottom: 2.4rem; }
.marquee-track { padding-bottom: 2rem; }
@media (hover: none) {
  /* static in the flow on touch screens - a gap, not an offset */
  .marque-name { margin-top: 0.25rem; }
}

/* ---- Photographic hero -------------------------------------------------
   Full-bleed picture, scrim, headline over it.

   An <img> rather than a background: it is the largest thing on the page, so
   it carries dimensions and fetchpriority and the browser starts it at once.
   Empty alt - the headline says what the page is, the photograph is mood. */
.hero-photo {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  min-height: clamp(27rem, 74svh, 42rem);
  display: grid;
  align-content: center;
  background: var(--ink);
  color: #fff;
  padding-block: clamp(3.5rem, 9vh, 6rem);
}
.hero-photo .hero-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% 54%;
  z-index: -2;
}
/* darkest at the foot, where the copy and the button sit */
.hero-photo::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg,
              rgba(11,11,12,0.56) 0%,
              rgba(11,11,12,0.30) 38%,
              rgba(11,11,12,0.70) 78%,
              rgba(11,11,12,0.88) 100%);
}
.hero-photo h1 { color: #fff; text-shadow: 0 1px 30px rgba(0,0,0,0.45); }
.hero-photo h1 em { color: var(--gold-bright); }
.hero-photo .lede { color: rgba(255,255,255,0.87); text-shadow: 0 1px 20px rgba(0,0,0,0.5); }

/* The header veil is a cream gradient that fades the page out behind the nav
   pill. Over a dark photograph it washes the top of the frame, so a page with
   a photographic hero gives the header a plain solid ground instead. */
/* This used to force a solid paper ground on photo-hero pages. It beat the
   .at-hero rules on specificity - body:has(.hero-photo) .masthead is (0,2,1)
   against .at-hero .masthead at (0,2,0) - so the header kept its white band
   over the picture no matter what the observer did. The header now simply
   behaves as it does everywhere else, and .at-hero is what changes it. */

/* ---- Parallax band -----------------------------------------------------
   background-attachment: fixed paints the picture against the viewport rather
   than the section, so the page slides over a photograph that stays put. */
.band-parallax {
  height: var(--band-h, 62svh);
  background-image: var(--band-img);
  background-size: cover;
  background-position: center 40%;
  background-repeat: no-repeat;
  background-attachment: fixed;
  background-color: var(--ink);
}
/* iOS Safari ignores fixed attachment and several Android browsers stutter on
   it. Touch screens get an ordinary cover background - the picture without the
   drift, which is better than a picture that judders. */
@media (hover: none) {
  .band-parallax { background-attachment: scroll; height: 42svh; }
}
@media (prefers-reduced-motion: reduce) {
  .band-parallax { background-attachment: scroll; }
}
@media (max-width: 40rem) {
  .hero-photo { min-height: clamp(24rem, 66svh, 32rem); }
  .hero-photo .hero-img { object-position: 50% 58%; }
}

/* ---- Marque row directly under the hero --------------------------------
   A compact band, not a section with a section's air: it sits between a
   full-height photograph and the stats, and both of those already carry their
   own space. The generous spacing tuned for /buy is undone here. */
.section-marquerow { padding-block: clamp(2rem, 4.5vh, 3rem); }
.section-marquerow .marques { margin-top: 0; padding-bottom: 1.6rem; row-gap: 1.5rem; }
@media (max-width: 40rem) {
  .section-marquerow { padding-block: 1.75rem; }
  .section-marquerow .marques { padding-bottom: 1.2rem; }
}

/* ---- The homepage row: still on a wide screen, moving on a phone --------
   The markup is the marquee's - six logos twice, on an animated track. On a
   wide screen the second set is hidden and the animation stopped, which gives
   a plain centred row; below 61rem the track behaves as a marquee, because six
   logos on a phone wrap into a cramped block. */
@media (min-width: 61rem) {
  .section-marquerow .marquee { -webkit-mask-image: none; mask-image: none; }
  .section-marquerow .marquee-track {
    animation: none;
    width: auto;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1.75rem 2.75rem;
  }
  .section-marquerow .marquee-track .marque { margin-right: 0; }
  .section-marquerow .marque-clone { display: none; }
}
@media (max-width: 60.9375rem) {
  /* the marquee's own spacing, which the seam depends on */
  .section-marquerow .marquee-track .marque { margin-right: 3rem; }
  .section-marquerow .marques { padding-bottom: 1.4rem; }
}

/* ---- Hero legibility ---------------------------------------------------
   Two separate problems, both from putting cream-background colours over a
   dark photograph.

   1. --gold-bright (#A8912F) is a deep gold chosen to sit on paper. The
      photograph is lit in that same warm range, so the italic line had almost
      nothing to stand against. --gold-on-dark is the same hue, lifted: it
      measures about 10:1 against the scrimmed picture, against roughly 3:1
      before. It is used ONLY on dark photographic grounds; the brand gold on
      paper is untouched.
   2. The scrim was a vertical gradient, so the middle of the frame - which is
      exactly where the headline sits - was its lightest point. A soft dark
      ellipse now sits behind the copy, leaving the car's edges bright. */
:root { --gold-on-dark: #E3C56B; }

.hero-photo h1 em { color: var(--gold-on-dark); }

.hero-photo::after {
  background:
    radial-gradient(ellipse 70% 58% at 50% 46%,
                    rgba(11,11,12,0.62) 0%,
                    rgba(11,11,12,0.44) 55%,
                    rgba(11,11,12,0) 100%),
    linear-gradient(180deg,
                    rgba(11,11,12,0.52) 0%,
                    rgba(11,11,12,0.26) 38%,
                    rgba(11,11,12,0.66) 78%,
                    rgba(11,11,12,0.86) 100%);
}

/* the supporting line was thin white over a busy frame */
.hero-photo .lede {
  color: #fff;
  font-weight: 500;
  text-shadow: 0 1px 3px rgba(0,0,0,0.55), 0 1px 24px rgba(0,0,0,0.6);
}
.hero-photo h1 { text-shadow: 0 2px 4px rgba(0,0,0,0.4), 0 1px 34px rgba(0,0,0,0.5); }

/* The band was positioned at 40% down, which pushed the car towards the foot
   of the window and cropped its wheels. Centred instead.

   With background-attachment: fixed the picture is painted against the
   viewport, so the band is a moving window onto it - the framing shifts as you
   scroll, and centring sets where it sits on average rather than exactly. */
.band-parallax { background-position: center center; }

/* ---- Two warm sections in a row ----------------------------------------
   Where one warm section follows another there is no colour change to mark
   the join, so the two paddings stack into a gap roughly twice the size of
   any other - a hole in the middle of what reads as a single block.

   The second section drops its top padding; the first one's bottom padding
   still separates them, once instead of twice. This is the pattern, not one
   page: the homepage (stats into the cards), /about-us, /sell,
   /services/car-grooming and the template demo all do it. */
.section-warm + .section-warm { padding-top: clamp(2rem, 4vh, 3.25rem); }

/* ---- The header while the hero is on screen ----------------------------
   No ground of its own: the nav pill and the logo float over the photograph,
   and the normal header returns as soon as the hero scrolls away. Driven by
   .at-hero on <html>, set by an IntersectionObserver.

   A cream gradient was the other option and it is the wrong one - fading
   paper over a dark picture reads as haze across the top of the frame.

   Every rule here is additive, so with the script blocked the header keeps the
   solid ground it has without them. */
.at-hero .masthead {
  background: transparent;
  border-bottom-color: transparent;
  transition: background .25s ease, border-color .25s ease;
}
@media (min-width: 981px) {
  .at-hero .masthead::before { display: none; }
  /* No capsule for the wordmark here. On a wide screen .masthead .shell is
     itself a paper capsule holding the logo and the nav, so the mark already
     has a light ground - a capsule round the logo was a capsule inside a
     capsule. */
}
@media (max-width: 980px) {
  /* no pill on a phone: the burger is dark ink, which vanishes on a dark
     photograph, and the logo needs the same capsule */
  .at-hero:has(.hero-photo) .menu-bars,
  .at-hero:has(.hero-photo) .menu-bars::before,
  .at-hero:has(.hero-photo) .menu-bars::after { background: #fff; }

}

/* The marquee shell clips, because a scrolling strip must not spill into the
   page. On the wide-screen layout nothing scrolls - the only thing reaching
   past the box is the hovered name hanging below its logo, and it was being
   cut in half. Clipping off, and enough room under the row for the label. */
@media (min-width: 61rem) {
  .section-marquerow .marquee { overflow: visible; }
  .section-marquerow .marques { padding-bottom: 2.3rem; }
}

/* ---- The picture runs behind the header --------------------------------
   The header is sticky, which means it is in the flow: the hero began below
   it, so making it transparent revealed the page's own paper rather than the
   photograph. Nothing to see through.

   The hero is pulled up by the header's height and given that height back as
   padding, so the picture starts at the top of the window while the copy sits
   where it did. The header paints above it - z-index 60 against the hero's
   own stacking context.

   --head-h is published by the script; the fallback matches the desktop
   header, so a blocked script leaves the layout sane rather than overlapped. */
body:has(.hero-photo) .hero-photo {
  margin-top: calc(-1 * var(--head-h, 92px));
  padding-top: calc(var(--head-h, 92px) + clamp(3.5rem, 9vh, 6rem));
}

/* A taller hero: 74svh -> 80svh, with the floor and ceiling moved to match.
   Deliberately short of 100svh - a hero that exactly fills the window gives no
   sign there is a page under it, and the marque row peeking in is what invites
   the scroll. */
.hero-photo { min-height: clamp(30rem, 80svh, 45rem); }
@media (max-width: 40rem) {
  .hero-photo { min-height: clamp(26rem, 72svh, 35rem); }
}

/* Taller again: 80svh -> 88svh. Still short of the full window, so the marque
   row shows at the bottom edge and the page reads as having more below it. */
.hero-photo { min-height: clamp(31rem, 83svh, 46rem); }
@media (max-width: 40rem) {
  .hero-photo { min-height: clamp(28rem, 78svh, 38rem); }
}

/* ---- Centring the marque row -------------------------------------------
   Horizontally: the track is centred explicitly rather than relying on the
   flex default, and the trailing item's margin is removed - a margin on the
   last logo pushes the whole row left by half of it, which is exactly the
   kind of small offset that looks like a mistake without looking like
   anything in particular.

   Vertically: the row reserves space beneath it for the hover label, and
   nothing above, so it sat high in its own band. The same space above puts it
   back in the middle. */
@media (min-width: 61rem) {
  .section-marquerow .marquee-track {
    justify-content: center;
    margin-inline: auto;
  }
  .section-marquerow .marquee-track .marque:last-child { margin-right: 0; }
  .section-marquerow .marques { padding-top: 2.3rem; }
}

/* ---- The wordmark over a photograph -------------------------------------
   The capsule is gone. It only ever existed because the mark is indigo and
   gold, which vanishes on a dark picture - so over a photographic hero the
   header shows a white version of the same mark instead, and the coloured one
   everywhere else.

   Two <img> elements rather than a filter: invert() would turn the gold
   olive-green and the indigo pale yellow. The white file keeps the original
   alpha and replaces only the ink, so every letterform and the emblem are
   exactly as drawn.

   The white copy is aria-hidden with empty alt - the coloured one carries the
   name, and a screen reader should hear it once. */
.brand { background: none; border: 0; box-shadow: none; padding: 0; position: relative;
         display: inline-flex; }
.brand-mark-white { display: none; }

/* On a wide screen the header is a paper capsule, so the coloured mark is
   right in both states and the white one is never used.

   Below 981px there is no capsule: the header is a plain bar, and .at-hero
   makes it transparent, so over the homepage photograph the wordmark really is
   sitting on the picture. That is the one place the white mark belongs. */
@media (max-width: 980px) {
  .brand-mark-white {
    display: block;
    position: absolute;
    inset: 0;
    opacity: 0;
    transition: opacity .2s ease;
  }
  .brand-mark { transition: opacity .2s ease; }
  .at-hero:has(.hero-photo) .brand-mark { opacity: 0; }
  .at-hero:has(.hero-photo) .brand-mark-white { opacity: 1; }
}

/* The address strip under the map sat tight against the frame edge and the
   map above it. It carries the NAP - the one thing on the card a person
   copies or a crawler reads - so it gets room rather than being squeezed in
   under the embed. */
.map-nap { padding: 1.1rem 1.25rem 1.2rem; line-height: 1.65; }
.map-nap strong { display: inline-block; margin-bottom: 0.35rem; }


/* ==========================================================================
   DARK MODE
   --------------------------------------------------------------------------
   A repaint of the tokens, not a second stylesheet. Every surface, rule and
   text colour on the site already comes from a custom property, so the theme
   redefines those properties and the whole page follows. What is left below
   the token block is the handful of places that hard-code a colour or depend
   on the ground being light.

   The ramp is warm, as the light one is: PRM's neutrals have a warm cast, and
   a cold grey dark mode would read as a different brand. Nothing is pure
   black - #0B0B0C is the page, surfaces sit above it, and text is off-white
   rather than #FFF, which is what stops the type vibrating on a dark ground.
   ========================================================================== */
:root[data-theme="dark"] {
  --ink:          #F2F1EE;   /* text, not black: the roles invert with the theme */
  --ink-soft:     #C6C4BE;
  --ink-faint:    #9C998F;
  --hair:         #32323A;
  --hair-strong:  #45454F;
  --hair-warm:    #37362F;
  --paper:        #1D1D22;   /* cards, the header capsule, anything raised */
  --paper-warm:   #26262B;

  --indigo:       #6C56C9;   /* lifted: #2E1D6B on a dark ground is unreadable */
  --indigo-deep:  #8371DA;   /* hover goes lighter in the dark, not darker */
  --indigo-soft:  #241C3D;

  --gold:         #C7A84E;
  --gold-bright:  #E3C56B;
  --gold-soft:    #2A2517;

  --n-50:   #17171B;
  --n-100:  #1D1D22;         /* the warm band behind card groups */
  --n-200:  #32323A;
  --n-400:  #8F8C85;
  --n-600:  #BFBCB5;
}
:root[data-theme="dark"] body { background: #141418; }

/* ---- the places tokens cannot reach ------------------------------------ */
:root[data-theme="dark"] .map-card { background: var(--paper); }
:root[data-theme="dark"] .map-embed { background: var(--n-200); }

/* The footer is a dark slab in both themes. On a dark page it would merge
   with the ground, so it lifts instead of darkening. */
:root[data-theme="dark"] .footer { background: var(--paper-warm); }

/* The marque logos are single-colour dark artwork. Inverting a greyscale
   image is the whole job - it gives white marks with the shapes untouched -
   and it is why the row was greyscaled in the first place. */
:root[data-theme="dark"] .marque img { filter: grayscale(1) invert(1) brightness(1.35); opacity: 0.72; }
:root[data-theme="dark"] .marque:hover img,
:root[data-theme="dark"] .marque:focus-within img { filter: grayscale(1) invert(1) brightness(1.6); opacity: 1; }

/* The wordmark is indigo and gold, which disappears on a dark header. The
   white rendering already exists for phones over a photograph; the dark theme
   is its second home. */
:root[data-theme="dark"] .brand-mark { opacity: 0; }
:root[data-theme="dark"] .brand-mark-white { display: block; position: absolute; inset: 0; opacity: 1; }

/* Placeholder artwork is drawn on white. Knocking it back stops a sample car
   burning a hole in the page. */
:root[data-theme="dark"] .car-shot img[src$=".svg"],
:root[data-theme="dark"] .svc-ba img[src$=".svg"] { filter: invert(0.92) hue-rotate(180deg); }

/* Photographs are not themed - they are the same picture either way - but the
   scrim over a hero can afford to be heavier on a dark page. */
:root[data-theme="dark"] .hero-photo::after { opacity: 1.06; }

/* ---- the switch --------------------------------------------------------- */
.theme-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  margin-left: 0.15rem;
  padding: 0;
  border: 1px solid var(--n-200);
  border-radius: 999px;
  background: transparent;
  color: var(--ink);
  cursor: pointer;
  transition: background .18s ease, border-color .18s ease, color .18s ease;
}
.theme-btn:hover { border-color: var(--n-400); background: var(--n-100); }
.theme-btn:focus-visible { outline: 3px solid var(--gold-bright); outline-offset: 2px; }
.theme-btn svg { width: 17px; height: 17px; fill: none; stroke: currentColor; stroke-width: 1.7;
                 stroke-linecap: round; stroke-linejoin: round; }
.theme-moon { fill: currentColor; stroke: none; }
/* one icon at a time: the moon offers dark, the sun offers the way back */
.theme-moon { display: none; }
:root[data-theme="dark"] .theme-sun { display: none; }
:root[data-theme="dark"] .theme-moon { display: block; }

@media (max-width: 980px) {
  /* in the full-screen menu it sits with the links rather than in the bar */
  .theme-btn { width: 44px; height: 44px; }

}

/* ---- indigo has two jobs, and they pull opposite ways in the dark -------
   As a button ground it must stay dark enough for white text to sit on it;
   as text it must be light enough to read against the page. One value cannot
   do both: #6C56C9 carries white at 5.5:1 but reads at only 3.6:1 as type,
   which is below the 4.5:1 body-text line.

   So the ground keeps --indigo and the type gets --indigo-text, measured at
   7.4:1 on the page and 6.7:1 on a card. The light theme has no such problem
   and is untouched. */
:root[data-theme="dark"] { --indigo-text: #A897F0; }
:root[data-theme="dark"] .nav a[aria-current="page"],
:root[data-theme="dark"] .hero h1 em,
:root[data-theme="dark"] .contact-card a,
:root[data-theme="dark"] .contact-value a,
:root[data-theme="dark"] .visit-details dd a,
:root[data-theme="dark"] .car-price,
:root[data-theme="dark"] .car-body h3 a:hover,
:root[data-theme="dark"] .qa > summary:hover h3,
:root[data-theme="dark"] .sub a:hover,
:root[data-theme="dark"] .sub a:focus-visible,
:root[data-theme="dark"] .sub a[aria-current="page"],
:root[data-theme="dark"] .has-sub.is-ancestor > a { color: var(--indigo-text); }

/* ==========================================================================
   CINEMATIC LAYER  (v3)
   --------------------------------------------------------------------------
   The brief was the layout, not the palette - so this changes composition,
   scale and rhythm, and it changes them in BOTH themes.

     1. display type, roughly half again as large, set tight
     2. a hero that fills the window, with the copy anchored low
     3. dark islands: every warm section becomes a deep block, so the page
        alternates light and dark instead of running on one ground
     4. bands that bleed into the page rather than butting against it
     5. one measure for headings, left-aligned, with a rule to open on
     6. sections that rise into place as they enter the window

   The eyebrow rule still holds: no kicker, label or pill above any heading.
   The rules below are lines, not text.
   ========================================================================== */

/* ---- 1. display type ---------------------------------------------------- */
h1 { font-size: clamp(2.7rem, 6.4vw, 5.2rem); line-height: 0.98; letter-spacing: -0.04em; }
h2 { font-size: clamp(1.9rem, 3.6vw, 3rem);   line-height: 1.05; letter-spacing: -0.035em; }
h3 { font-size: clamp(1.1rem, 1.7vw, 1.35rem); letter-spacing: -0.02em; }
.lede { font-size: clamp(1.05rem, 1.35vw, 1.2rem); line-height: 1.62; }

/* ---- 2. the hero fills the window --------------------------------------- */
.hero-photo {
  min-height: 100svh;
  align-content: end;                 /* copy sits low, as a title card does */
  padding-bottom: clamp(5rem, 13vh, 9rem);
}
.hero-photo .shell { text-align: left; }
.hero-photo h1 { max-width: 15ch; margin-inline: 0; }
.hero-photo .lede { max-width: 46ch; margin-inline: 0; text-align: left; }
.hero-photo .btn-row { justify-content: flex-start; }
/* weight the scrim towards the foot, where the copy now lives */
.hero-photo::after {
  background:
    radial-gradient(ellipse 88% 62% at 28% 82%,
                    rgba(11,11,12,0.72) 0%, rgba(11,11,12,0.34) 60%, rgba(11,11,12,0) 100%),
    linear-gradient(180deg,
                    rgba(11,11,12,0.46) 0%, rgba(11,11,12,0.16) 34%,
                    rgba(11,11,12,0.74) 82%, rgba(11,11,12,0.92) 100%);
}
/* a line that breathes at the foot of the hero - a cue to scroll, not a label */
@media (min-width: 981px) {
  .hero-photo::before {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 1.6rem;
    width: 1px;
    height: 3.2rem;
    background: linear-gradient(to bottom, transparent, rgba(255,255,255,0.75));
    transform-origin: bottom;
    animation: cue 2.6s ease-in-out infinite;
  }
}
@keyframes cue {
  0%, 100% { transform: scaleY(0.35); opacity: 0.35; }
  50%      { transform: scaleY(1);    opacity: 0.9; }
}
@media (prefers-reduced-motion: reduce) { .hero-photo::before { animation: none; } }

/* plain heroes grow too, but nothing like as far - there is no picture behind
   them, and an empty screen is not atmosphere */
.hero:not(.hero-photo) { padding-block: clamp(5rem, 13vh, 9rem) clamp(3.5rem, 9vh, 6rem); }
.hero:not(.hero-photo) .shell { text-align: left; }
.hero:not(.hero-photo) h1 { max-width: 17ch; margin-inline: 0; }
.hero:not(.hero-photo) .lede { margin-inline: 0; text-align: left; max-width: 52ch; }
.hero:not(.hero-photo) .btn-row { justify-content: flex-start; }

/* ---- 3. dark islands ---------------------------------------------------- */
/* A warm section becomes a deep block. The tokens are repainted inside it, so
   every card, rule and caption within follows without being named - the same
   mechanism the dark theme uses, applied to one section instead of the page.
   The page then alternates instead of running on a single ground, which is
   most of what makes a layout feel cinematic rather than tidy. */
/* In light mode the alternate section is the warm neutral, not a dark block.
   The token repaint that was here turned every warm section into a deep
   island - the page alternated, but it read as a dark site with light gaps
   rather than a light site with rhythm. */
:root[data-theme="light"] .section-warm { background: #F5F4F1; }

:root[data-theme="dark"] .section-warm { background: #0F0F13; }
:root[data-theme="dark"] .section:not(.section-warm) { background: #141418; }

/* ---- 4. bands that bleed ------------------------------------------------ */
.band, .band-parallax { position: relative; }
.band-parallax { height: clamp(28rem, 78svh, 46rem); }
.band::after, .band-parallax::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
              rgba(11,11,12,0.55) 0%, rgba(11,11,12,0) 22%,
              rgba(11,11,12,0) 74%, rgba(11,11,12,0.62) 100%);
}

/* ---- 5. headings: one measure, left, opened by a rule ------------------- */
.section-head { text-align: left; margin-inline: 0; max-width: 34ch; }
.section-head h2 { max-width: 20ch; margin-inline: 0; }
.section-head .lede { margin-inline: 0; max-width: 52ch; }
.section-head::before {
  content: "";
  display: block;
  width: 3.5rem;
  height: 2px;
  margin-bottom: clamp(1.4rem, 3vh, 2.2rem);
  background: var(--gold-bright);
  opacity: 0.85;
}
.section { padding-block: clamp(5.5rem, 14vh, 10rem); }

/* ---- 6. sections rise into place ---------------------------------------- */
/* Scroll-driven, in CSS - no observer, no script. Browsers without view()
   simply show everything, which is the correct fallback rather than a
   degraded one. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) and (min-width: 700px) {
    .section > .shell, .band img {
      animation: rise linear both;
      animation-timeline: view();
      animation-range: entry 8% cover 26%;
    }
  }
}
@keyframes rise {
  from { opacity: 0; transform: translateY(26px); }
  to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   CINEMATIC, PASS 2 — after hbbody.com
   --------------------------------------------------------------------------
   What the reference actually does, read from its own page: a full-screen
   hero with the copy CENTRED over the picture and an intro sequence before
   it settles; uppercase headings; dark grounds throughout; and cards that are
   photographs with text on them rather than text in boxes.

   Taken: the centred hero, the opening move, the uppercase headings, the
   image-led cards.
   Not taken: their category labels above product names. That is an eyebrow,
   and eyebrows are banned here whatever the reference does.
   ========================================================================== */

/* ---- the hero centres again, as the reference has it -------------------- */
.hero-photo { align-content: center; padding-bottom: clamp(4rem, 10vh, 7rem); }
.hero-photo .shell { text-align: center; }
/* 26ch rather than 20: at the hero size that is about 640px, enough for
   "With people you can trust." to sit on one line instead of breaking
   after "can". Still a cap - an uncapped headline would run the full
   1200 and read as a paragraph rather than a title. */
.hero-photo h1 { max-width: 26ch; margin-inline: auto; }
.hero-photo .lede { max-width: 54ch; margin-inline: auto; text-align: center; }
.hero-photo .btn-row { justify-content: center; }
.hero-photo::after {
  background:
    radial-gradient(ellipse 76% 60% at 50% 50%,
                    rgba(11,11,12,0.68) 0%, rgba(11,11,12,0.40) 58%, rgba(11,11,12,0.12) 100%),
    linear-gradient(180deg,
                    rgba(11,11,12,0.52) 0%, rgba(11,11,12,0.22) 36%,
                    rgba(11,11,12,0.68) 84%, rgba(11,11,12,0.9) 100%);
}

/* ---- the opening move --------------------------------------------------- */
/* The picture settles out of a slow push-in while the copy rises through it.
   One and a half seconds, once, on load - the difference between a page that
   appears and a page that opens. It is decoration, so it is behind a
   reduced-motion guard and nothing depends on it having run. */
@media (prefers-reduced-motion: no-preference) {
  .hero-photo .hero-img { animation: push-in 1.6s cubic-bezier(.16,.84,.34,1) both; }
  .hero-photo h1        { animation: lift 1s ease-out .25s both; }
  .hero-photo .lede     { animation: lift 1s ease-out .42s both; }
  .hero-photo .btn-row  { animation: lift 1s ease-out .58s both; }
}
@keyframes push-in {
  from { transform: scale(1.085); }
  to   { transform: scale(1); }
}
@keyframes lift {
  from { opacity: 0; transform: translateY(18px); }
  to   { opacity: 1; transform: none; }
}

/* ---- uppercase section headings ----------------------------------------- */
/* The reference sets its headings in caps, and on an automotive page it reads
   as signage rather than as prose. Section headings only: the hero keeps
   sentence case and its serif italic line, which is where PRM's own voice is
   and the one thing worth not borrowing. */
.section-head h2, .svc-cta h2 {
  text-transform: uppercase;
  letter-spacing: 0.01em;
  font-weight: 700;
  font-size: clamp(1.6rem, 3vw, 2.5rem);
  line-height: 1.08;
  max-width: 24ch;
}
.section-head h2 em, .svc-cta h2 em { text-transform: none; }

/* ---- cards become photographs ------------------------------------------- */
/* News tiles already carry a picture; it was a strip above the text. Now it
   fills the tile and the copy sits on it, which is the reference's card.

   Written against the real markup: .postcard-shot IS the <img>, and the whole
   tile is one <a class="postcard-link">. */
.postcard { position: relative; isolation: isolate; border-radius: var(--r-lg); overflow: hidden; }
.postcard-link { display: flex; flex-direction: column; justify-content: flex-end;
                 min-height: 21rem; padding: 0; text-decoration: none; }
.postcard-shot {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
  transition: transform .7s cubic-bezier(.16,.84,.34,1);
}
.postcard::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgba(11,11,12,0.10) 16%, rgba(11,11,12,0.86) 94%);
}
.postcard-body { padding: 1.3rem 1.35rem 1.4rem; }
.postcard-title, .postcard-more, .postcard-body p, .postcard-body time { color: #fff; }
.postcard-more { opacity: 0.85; }
.postcard:hover .postcard-shot,
.postcard:focus-within .postcard-shot { transform: scale(1.07); }

/* the same push on any other picture that sits in a tile */
.car-shot { overflow: hidden; }
.car-shot img { transition: transform .7s cubic-bezier(.16,.84,.34,1); }
.car:hover .car-shot img { transform: scale(1.05); }

/* ==========================================================================
   SPLIT SECTIONS: text column 30%, card rail 70%
   --------------------------------------------------------------------------
   The heading and its lede sit in a narrow column on the left; the cards
   become a horizontal rail on the right with the same arrows the phone
   carousel uses. Below 62rem nothing changes - the rail is already a
   swipeable carousel there, and the heading already sits above it.

   Scoped with :has() to sections that hold BOTH a heading block and a card
   rail, so a section with cards and no heading is left alone.
   ========================================================================== */
@media (min-width: 62.01rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell {
    display: grid;
    grid-template-columns: minmax(0, 30%) minmax(0, 70%);
    gap: clamp(1.4rem, 2.6vw, 2.4rem);
    align-items: start;
  }
  /* the column is the measure now, so the character cap comes off */
  .section:not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail)) > .shell > .section-head {
    max-width: none;
    margin-bottom: 0;
  }
  .section:not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail)) > .shell > .section-head h2,
  .section:not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail)) > .shell > .section-head .lede { max-width: none; }

  /* the rail */
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx { min-width: 0; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx > :is(.cards, .cars-rail, .cars-grid) {
    display: flex;
    flex-wrap: nowrap;
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    scroll-behavior: smooth;
    gap: clamp(0.9rem, 1.6vw, 1.35rem);
    /* room for the card shadow, and for the arrows to sit over the edges */
    padding: 0.4rem 0.2rem 1rem;
    scrollbar-width: none;
  }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx > :is(.cards, .cars-rail, .cars-grid)::-webkit-scrollbar { display: none; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx > :is(.cards, .cars-rail, .cars-grid) > * {
    flex: 0 0 min(330px, 78%);
    scroll-snap-align: start;
  }

  /* the arrows exist on every width now, so they need showing here too -
     still only once carousel.js has marked the shell ready */
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 50%;
    transform: translateY(-50%);
    z-index: 4;
    width: 38px;
    height: 38px;
    padding: 0 0 2px;
    border-radius: 999px;
    border: 1px solid var(--n-200);
    background: var(--paper);
    box-shadow: 0 8px 22px -12px rgba(11,11,12,0.55);
    color: var(--ink);
    font: 1.4rem/1 var(--sans);
    cursor: pointer;
  }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-prev { left: -0.9rem; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-next { right: -0.9rem; }
}

/* A scroll container clips on both axes - overflow-x: auto computes overflow-y
   to auto as well, so there is no way to let a shadow spill out of it. The
   room has to be inside: padding deep enough for the shadow to finish, with
   scroll-padding matching the inline side so the snap still lands on the card
   edge rather than on the padding. */
@media (min-width: 62.01rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx > :is(.cards, .cars-rail, .cars-grid) {
    padding: 0.9rem 0.75rem 2.4rem;
    scroll-padding-left: 0.75rem;
  }
  /* and the arrows clear the cards instead of sitting on their corners */
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-prev { left: -1.35rem; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-next { right: -1.35rem; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx.cx-ready > .cx-btn {
    top: calc(50% - 0.75rem);   /* centred on the cards, not on the padding */
  }
}

/* ---- elevation in the dark ---------------------------------------------
   Every shadow on the site is black at low opacity, which does nothing on a
   near-black page - black on black is black. A dark interface raises a
   surface three other ways, and this uses all three:

     the surface is lighter than the page (--paper #17171A on #0B0B0C)
     a hairline at the rim, light rather than dark
     a lit top edge - one inset pixel of white at 6%, which is what a real
     raised edge catches, and what reads as "above" when a shadow cannot

   A deeper black shadow is kept underneath as well. It is nearly invisible on
   its own, but it stops the card sitting flat against a band of similar tone.
   ========================================================================== */
:root[data-theme="dark"] .card,
:root[data-theme="dark"] .postcard,
:root[data-theme="dark"] .car,
:root[data-theme="dark"] .svc-column,
:root[data-theme="dark"] .panel,
:root[data-theme="dark"] .map-card,
:root[data-theme="dark"] .brandpanel {
  border: 1px solid rgba(255,255,255,0.10);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.06),
    0 20px 44px -26px rgba(0,0,0,0.95);
}
:root[data-theme="dark"] .card:hover,
:root[data-theme="dark"] .postcard:hover,
:root[data-theme="dark"] .car:hover,
:root[data-theme="dark"] .svc-column:hover {
  border-color: rgba(255,255,255,0.20);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.10),
    0 30px 60px -28px rgba(0,0,0,1);
  transform: translateY(-3px);
}
/* the header capsule and the carousel arrows are raised too */
:root[data-theme="dark"] .masthead .shell,
:root[data-theme="dark"] .cx-ready .cx-btn {
  border-color: rgba(255,255,255,0.12);
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.06), 0 16px 36px -24px rgba(0,0,0,0.95);
}

/* ---- the ask sits under the heading, not under the rail ----------------
   A third child of the split shell lands in the left column on a second row,
   and that row starts below the rail - which is tall - so the block drifted
   far down the page with a hole above it.

   Pinning the rail across both rows fixes it: the left column then reads
   heading, lede, ask, in one run, and the cards sit beside all three.

   Below 62rem the grid is off and the DOM order stands, which is already
   what was asked for: text, then cards, then the ask. */
@media (min-width: 62.01rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .section-head { grid-column: 1; grid-row: 1; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid))  .cx { grid-column: 2; grid-row: 1 / span 2; }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .ask-instead,
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .btn-row {
    grid-column: 1;
    grid-row: 2;
    align-self: start;
    margin-top: clamp(1.4rem, 3vh, 2.1rem);
  }
  /* the heading row takes only the height it needs; the rail spans the rest */
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell { grid-template-rows: auto 1fr; }
}

/* Two gaps were stacking above the ask: the margin that puts it on its own
   grid row, and its own padding under the rule. In one column they read as
   one large hole between the lede and the rule. Both come down. */
@media (min-width: 62.01rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .ask-instead {
    margin-top: 0.15rem;
    padding-top: 0.9rem;
  }
}

/* The buttons keep their full size. The room comes from the layout instead:
   the column gap is tighter and the text column takes 33% rather than 30%,
   which is about 35px more - enough for both buttons on one line without
   shrinking either. */

/* Side by side, at full size. Two things were needed: the row must not wrap,
   and the column must be wide enough that it does not have to - so above
   75rem the text column takes 36% and the row is nowrap.

   Between 62rem and 75rem the column is genuinely too narrow for both buttons
   at full size, so wrapping stays allowed there. Forcing nowrap at every
   width would push them out of the column and under the cars. */
@media (min-width: 75rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell {
    grid-template-columns: minmax(0, 30%) minmax(0, 70%);
  }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .ask-instead .btn-row {
    flex-wrap: nowrap;
    gap: 0.6rem;
  }
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards), :has(.cx > .cars-rail), :has(.cars-grid)) > .shell > .ask-instead .btn {
    white-space: nowrap;
  }
}

/* The container goes to 1200. Set here rather than edited in one of the three
   earlier :root blocks, so there is a single current answer at the end of the
   sheet instead of three competing ones further up. */
/* 1200px of CONTENT, not a 1200px box.

   .shell is border-box with padding-inline: var(--gut), so its max-width has
   to carry the gutters on top of the measure or the content comes out two
   gutters short. The gutter is a clamp, so the arithmetic is done in calc
   rather than baked into a number - at any width the content is 1200. */
:root { --content: 1200px; }
.shell { max-width: calc(var(--content) + var(--gut) * 2); }


/* ==========================================================================
   THE NAV BAR, AFTER FERRARI
   --------------------------------------------------------------------------
   Theirs is a thin black bar running the full width of the window: a small
   mark hard left, uppercase links tracked out beside it, one item pushed to
   the far right, and no pill anywhere. It is solid over the hero rather than
   transparent - the picture starts beneath it.

   That replaces the floating capsule. The capsule was the Sparq idea; this is
   the opposite instinct, and the two cannot both be on the page.
   ========================================================================== */
.masthead {
  background: #121212;
  border-bottom: 0;
  padding-block: 0;
  backdrop-filter: none;
}
.masthead::before { display: none; }          /* the cream veil goes with it */
.masthead .shell {
  max-width: none;
  width: 100%;
  padding-inline: clamp(1rem, 2.4vw, 2rem);
  min-height: 58px;
  background: transparent;
  border: 0;
  border-radius: 0;
  box-shadow: none;
  gap: clamp(1.4rem, 3.4vw, 3rem);
}

/* the mark: small, hard left, and white - the coloured wordmark disappears
   on a black bar, and the white rendering already exists */
.brand { padding: 0; background: none; border: 0; box-shadow: none; }
/* The bar grows with the mark: a 38px wordmark in a 58px bar leaves 10px of
   air above and below, which is too tight for a lockup that has a second line
   under it. */
.brand img { width: auto; height: 38px; }
.masthead .shell { min-height: 72px; }
.brand-mark { opacity: 0; }
.brand-mark-white { display: block; position: absolute; inset: 0; opacity: 1; }

/* links sit beside the mark, not pushed to the right as a group */
@media (min-width: 981px) {
  .nav {
    margin-left: clamp(1.5rem, 4vw, 3.5rem);
    flex: 1 1 auto;
    gap: clamp(1.3rem, 2.8vw, 2.6rem);
    background: transparent;
    border: 0;
    padding: 0;
    box-shadow: none;
  }
  /* "Services" is a .has-sub > a, not a direct .nav > a, so it kept its own
     casing and size and sat out of line with the rest */
  .nav > a,
  .nav .has-sub > a {
    color: #fff;
    text-transform: uppercase;
    letter-spacing: 0.09em;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0;
  }
  .nav .has-sub > a:hover { color: var(--gold-bright); }
  .nav > a:hover { color: var(--gold-bright); }
  .nav a[aria-current="page"] { color: var(--gold-bright); }
  /* the last item goes to the far right, as plain as the others - no pill */
  .nav > a:last-of-type {
    margin-left: auto;
    background: none;
    color: #fff;
    border-radius: 0;
    padding: 0;
  }
  .nav > a:last-of-type:hover { background: none; color: var(--gold-bright); }
  .has-sub > a, .caret { color: #fff; }
}

/* the switch sits at the end of the bar, outlined rather than filled */
.theme-btn { border-color: rgba(255,255,255,0.3); color: #fff; }
.theme-btn:hover { background: rgba(255,255,255,0.1); border-color: rgba(255,255,255,0.5); }

/* solid over the hero too: .at-hero no longer strips the ground, it only
   stops the veil, which is already gone */
.at-hero .masthead { background: #121212; border-bottom-color: transparent; }

@media (max-width: 980px) {
  /* the burger is on black at every scroll position now, not only over a photo */
  .menu-bars, .menu-bars::before, .menu-bars::after { background: #fff; }
}

/* ---- the dropdown belongs to the black bar -----------------------------
   It was still the capsule-era panel: white, rounded, sentence case, with an
   indigo hover. Against a square black bar it read as a different component
   borrowed from a different site.

   It was also centred under its trigger (left: 50% and a translate), which is
   why its left corner hung out past the word above it. Anchored to the
   trigger's left edge instead, so the panel and the word line up. */
@media (min-width: 981px) {
  .sub {
    left: 0;
    transform: translateX(0) translateY(6px);
    min-width: 17rem;
    padding: 0.25rem 0;
    background: #121212;
    border: 0;
    border-top: 2px solid var(--gold-bright);
    border-radius: 0;
    box-shadow: 0 20px 44px -22px rgba(0,0,0,0.8);
  }
  .has-sub:hover .sub,
  .has-sub:focus-within .sub { transform: translateX(0) translateY(0); }

  .sub a {
    color: #fff;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.72rem;
    font-weight: 600;
    padding: 0.8rem 1.25rem;
  }
  /* written for both themes: the dark theme has its own .sub hover rule at a
     higher specificity, and without naming it here that rule would win */
  .sub a:hover, .sub a:focus-visible,
  :root[data-theme="dark"] .sub a:hover,
  :root[data-theme="dark"] .sub a:focus-visible,
  .sub a[aria-current="page"],
  :root[data-theme="dark"] .sub a[aria-current="page"] {
    background: rgba(255,255,255,0.09);
    color: var(--gold-bright);
  }
  .sub li:not(.is-ext) + li.is-ext { border-top-color: rgba(255,255,255,0.16); }
  .caret { color: #fff; opacity: 0.8; }
}


/* ==========================================================================
   MOBILE NAV, AFTER FERRARI
   --------------------------------------------------------------------------
   Closed: a black bar reading MENU at the left, the mark centred, the switch
   at the right. No hamburger - they use the word.

   Open: a black full-screen panel, the mark at the top, a round close at the
   right, and each section a large row with a chevron. Services opens as an
   accordion in place.

   Written with flex rows rather than absolutely-positioned chevrons: the
   first attempt relied on a positioning context that the older mobile-menu
   rules were also claiming, and the chevrons landed on the wrong side of the
   row. A flex row cannot go wrong that way.

   The accordion is a checkbox and a label, as the menu itself is. No script.
   ========================================================================== */
.sub-toggle { position: absolute; opacity: 0; pointer-events: none; width: 0; height: 0; }
.sub-btn { display: none; }

@media (max-width: 980px) {
  /* ---------- the closed bar ---------- */
  .masthead .shell { min-height: 60px; }
  /* The hamburger, not the word. Ferrari spells MENU out; on a bar this
     narrow the icon is quicker to find and costs no width, and the button
     keeps its aria-label either way. */
  .menu-btn { order: -1; width: 44px; height: 44px; margin: 0; }
  .menu-btn::after { content: none; }
  .brand { margin-inline: auto; }
  .brand img { height: 30px; }
  .theme-btn { margin-left: 0; border-color: rgba(255,255,255,0.3); color: #fff; }

  /* ---------- the open panel ---------- */
  .menu-toggle:checked ~ .nav {
    position: fixed;
    inset: 0;
    z-index: 95;
    display: flex;
    flex-direction: column;
    /* the base nav is flex-wrap: wrap. In a column inside a fixed-height
       panel that makes the list wrap into a SECOND COLUMN once it is taller
       than the screen - which is why Contact was sitting top right and the
       close had gone off the side entirely. */
    flex-wrap: nowrap;
    align-items: stretch;
    gap: 0;
    background: #121212;
    padding: 1.25rem 1.5rem 2.5rem;
    overflow-y: auto;
  }
  /* the mark, at the top of the panel itself rather than borrowed from the
     bar underneath it */
  .menu-toggle:checked ~ .nav::before {
    content: "";
    display: block;
    /* the mark in the open panel is the only branding on screen there, so it
       carries more weight than the 30px version it had in the bar */
    height: 52px;
    margin: 0.75rem 0 2.1rem;
    background: url("/assets/img/prm-logo-white.png") center/contain no-repeat;
  }

  /* every row: text left, chevron right, rule under */
  .menu-toggle:checked ~ .nav > a,
  .menu-toggle:checked ~ .nav .has-sub > a {
    width: 100%;
    flex: 0 0 auto;
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    min-height: 0;
    padding: 1.05rem 0;
    border: 0;
    border-bottom: 1px solid rgba(255,255,255,0.12);
    border-radius: 0;
    background: none !important;
    background-image: none !important;
    color: #fff;
    font-family: var(--sans);
    font-size: 1.4rem;
    font-weight: 650;
    letter-spacing: -0.01em;
    text-transform: none;
  }
  .menu-toggle:checked ~ .nav > a::before,
  .menu-toggle:checked ~ .nav .has-sub::before { content: none !important; }
  .menu-toggle:checked ~ .nav > a::after {
    content: "\203A";                     /* a single chevron, as the row's last child */
    /* .nav a::after is the old underline marker - display:none on mobile and
       absolutely positioned at the row's foot. Reviving it means undoing that
       geometry too, or the chevron lands bottom-left. */
    display: block !important;
    position: static;
    width: auto;
    height: auto;
    background: none;
    margin-left: auto;
    font-size: 1.5rem;
    font-weight: 400;
    line-height: 1;
    opacity: 0.75;
    transform: none;
  }
  .menu-toggle:checked ~ .nav .has-sub {
    display: block;
    position: relative;
    min-height: 0;
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none !important;
  }
  .menu-toggle:checked ~ .nav .has-sub > a { border-bottom: 0; }
  .menu-toggle:checked ~ .nav .caret { display: none; }

  /* the chevron on a section with children is a LABEL, so tapping it opens
     the accordion while the word still links to the section's own page */
  .menu-toggle:checked ~ .nav .sub-btn {
    display: block;
    position: absolute;
    top: 0;
    right: 0;
    width: 3.4rem;
    height: 3.9rem;
    cursor: pointer;
  }
  .menu-toggle:checked ~ .nav .sub-btn::after {
    content: "\203A";
    display: block !important;
    position: absolute;
    top: 50%;
    right: 0;
    transform: translateY(-50%) rotate(90deg);
    font-size: 1.5rem;
    line-height: 1;
    color: #fff;
    opacity: 0.75;
    transition: transform .22s ease;
  }
  .menu-toggle:checked ~ .nav .sub-toggle:checked ~ .sub-btn::after {
    transform: translateY(-50%) rotate(-90deg);
  }

  /* ---------- the accordion ---------- */
  /* max-height, not grid-template-rows: 0fr. That trick collapses only the
     FIRST row, and this submenu is a <ul> of five <li> - the other four rows
     stayed auto-sized, so the panel was never closed and its items sat on top
     of the links below. A max-height large enough for the longest submenu
     closes all of it. */
  .menu-toggle:checked ~ .nav .sub {
    display: block !important;
    max-height: 0;
    transition: max-height .28s ease;
    overflow: hidden;
    position: static;
    transform: none;
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
    margin: 0;
    padding: 0;
    background: none;
    border: 0;
    border-bottom: 1px solid rgba(255,255,255,0.12);
    box-shadow: none;
    min-width: 0;
  }
  .menu-toggle:checked ~ .nav .sub-toggle:checked ~ .sub { max-height: 32rem; }
  .menu-toggle:checked ~ .nav .sub > * { min-height: 0; overflow: hidden; }
  .menu-toggle:checked ~ .nav .sub a {
    display: block;
    padding: 0.6rem 0;
    font-size: 0.95rem;
    font-weight: 500;
    letter-spacing: 0.01em;
    text-transform: none;
    color: rgba(255,255,255,0.78);
    background: none;
  }
  .menu-toggle:checked ~ .nav .sub li:first-child a { padding-top: 0.85rem; }
  .menu-toggle:checked ~ .nav .sub li:last-child a { padding-bottom: 1rem; }
  .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext {
    border-top-color: rgba(255,255,255,0.14);
  }

  /* the Contact pill is a desktop treatment - in this list it is a row */
  .menu-toggle:checked ~ .nav > a:last-of-type {
    background: none !important;
    color: #fff;
    border-radius: 0;
    padding: 1.05rem 0;
    margin: 0;
  }

  /* ---------- the close ---------- */
  .menu-toggle:checked ~ .nav .menu-close {
    position: fixed;
    top: 0.85rem;
    right: 1.1rem;
    left: auto;
    bottom: auto;
    z-index: 100;
    display: flex !important;
    align-items: center;
    justify-content: center;
    width: 42px;
    height: 42px;
    padding: 0;
    border-radius: 999px;
    background: rgba(255,255,255,0.14);
    color: #fff;
    font-size: 0;
  }
  .menu-toggle:checked ~ .nav .menu-close span { font-size: 1.45rem; line-height: 1; }
}

/* ==========================================================================
   THE BAR FOLLOWS THE THEME
   --------------------------------------------------------------------------
   The Ferrari bar was written black in both themes, because theirs is. On a
   light page that leaves a black band sitting on cream with nothing else on
   the page to answer it. The shape stays - full width, square, uppercase,
   links left, one item far right - and only the colours change.
   ========================================================================== */
:root[data-theme="light"] .masthead,
:root[data-theme="light"] .at-hero .masthead {
  background: var(--paper);
  border-bottom: 1px solid var(--n-200);
}

/* the coloured wordmark comes back: it was swapped for the white rendering
   only because the bar was black */
:root[data-theme="light"] .brand-mark { opacity: 1; }
:root[data-theme="light"] .brand-mark-white { display: none; }

@media (min-width: 981px) {
  :root[data-theme="light"] .nav > a,
  :root[data-theme="light"] .nav .has-sub > a,
  :root[data-theme="light"] .nav > a:last-of-type,
  :root[data-theme="light"] .caret { color: var(--ink); }
  :root[data-theme="light"] .nav > a:hover,
  :root[data-theme="light"] .nav .has-sub > a:hover,
  :root[data-theme="light"] .nav > a:last-of-type:hover,
  :root[data-theme="light"] .nav a[aria-current="page"] { color: var(--indigo); }

  /* the dropdown is a light panel on a light bar */
  :root[data-theme="light"] .sub {
    background: var(--paper);
    border-top-color: var(--gold);
    box-shadow: 0 20px 44px -22px rgba(11,11,12,0.28);
  }
  :root[data-theme="light"] .sub a { color: var(--ink); }
  :root[data-theme="light"] .sub a:hover,
  :root[data-theme="light"] .sub a:focus-visible,
  :root[data-theme="light"] .sub a[aria-current="page"] {
    background: var(--indigo-soft);
    color: var(--indigo);
  }
  :root[data-theme="light"] .sub li:not(.is-ext) + li.is-ext {
    border-top-color: var(--hair-warm);
  }
}

:root[data-theme="light"] .theme-btn { border-color: var(--n-200); color: var(--ink); }
:root[data-theme="light"] .theme-btn:hover { background: var(--n-100); border-color: var(--n-400); }

@media (max-width: 980px) {
  :root[data-theme="light"] .menu-btn::after { color: var(--ink); }
  :root[data-theme="light"] .theme-btn { border-color: var(--n-200); color: var(--ink); }

  /* the open panel too - a black overlay on a light site reads as a different
     site, and the close and the rules have to come with it */
  :root[data-theme="light"] .menu-toggle:checked ~ .nav { background: var(--paper); }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav::before {
    background-image: url("/assets/img/prm-logo.png");
  }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav > a,
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .has-sub > a {
    color: var(--ink);
    border-bottom-color: var(--n-200);
  }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub { border-bottom-color: var(--n-200); }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub a { color: var(--ink-soft); }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub-btn::after { color: var(--ink); }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .menu-close {
    background: var(--n-100);
    color: var(--ink);
  }
}

/* ---- bigger hero type, every page --------------------------------------
   Headline and supporting line together: raising the headline alone widens
   the gap between them until the lede reads as a caption rather than the
   second half of the statement.

   Scoped to .hero so it cannot reach a heading anywhere else on the page. */
.hero h1 {
  font-size: clamp(3rem, 6.6vw, 5.3rem);
  line-height: 0.98;
}
.hero .lede {
  font-size: clamp(1.15rem, 1.7vw, 1.4rem);
  line-height: 1.5;
}
/* the measure is in characters, so it holds the same number of words at the
   new size - widened a little so the headline does not gain a line */
.hero-photo h1 { max-width: 25ch; }
/* 24ch, was 19. Every hero headline sets its own line breaks with <br>, and at
   19ch (927px at the full type size) the cap was narrower than the shell's
   1200px and broke three of them mid-phrase. /services/car-grooming was the
   worst: "Look after the car you drive." needs 1126px, so "drive." dropped to
   a line of its own.

   24ch is 1171px - it clears that line and /blogs and /services/financing with
   it, and still stops short of the shell, so the headline keeps a measure
   rather than running the full page width. Cap and text both scale with the
   font, so what fits at one width fits at all of them until the font-size
   clamp bottoms out on a phone. /about-us is unchanged: its second line wants
   1397px and wraps either way.

   Measured, not guessed - the three rules above this one all set .hero h1
   max-width, and this is the one that wins. */
.hero:not(.hero-photo) h1 { max-width: 24ch; }

@media (max-width: 40rem) {
  /* 50px put the homepage headline on four lines. There is no width to give back -
     the h1 box is 441px against a 684px cap, so the viewport is the
     constraint, not the measure - which leaves the type size.
     Measured at 390: the two authored lines of the homepage headline want 532
     and 612px at 50px type, so neither fits and both wrap. Three lines means
     one of the two may wrap, which needs 41px. 8.2vw lands there and keeps
     scaling with the screen; the 2.6rem ceiling holds it at the top of this
     range and the 2.1rem floor stops it collapsing on a 320px handset. */
  .hero h1 { font-size: clamp(2.1rem, 8.2vw, 2.6rem); }
  .hero .lede { font-size: 1.05rem; }
}

/* The marque band is a .section, so the cinematic pass's generous section
   padding applied to it - written later in the sheet than the compact rule
   this band was given, and at the same specificity, so it won. It is a strip
   of logos between a hero and the stats; it does not need a section's air. */
.section-marquerow { padding-block: clamp(1.4rem, 3vh, 2.1rem); }
.section-marquerow .marques { padding-top: 1.2rem; padding-bottom: 1.6rem; }
@media (max-width: 40rem) {
  .section-marquerow { padding-block: 1.2rem; }
  .section-marquerow .marques { padding-top: 0.8rem; padding-bottom: 1rem; }
}

/* The band is pinned to 150px and its contents centred in it, rather than
   built up from paddings that each have to be guessed at. The row keeps a
   little space beneath for the hover label; the band absorbs it. */
.section-marquerow {
  min-height: 150px;
  padding-block: 0;
  display: grid;
  align-content: center;
}
.section-marquerow .marques { padding-top: 0.6rem; padding-bottom: 1.5rem; }
@media (max-width: 40rem) {
  .section-marquerow { min-height: 120px; padding-block: 0; }
}

/* No hairline on warm sections. The ported sheet put one top and bottom; with
   adjacent warm sections sharing a ground it read as a seam through the middle
   of one block. The change of background is the divider where there is one. */
.section-warm { border-block: 0; }

/* ---- article pages ------------------------------------------------------
   One column at a reading measure. 68ch is the point where a line is long
   enough not to feel choppy and short enough that the eye finds the next one
   without hunting. */
.hero-post { padding-block: clamp(3rem, 8vh, 5rem) clamp(1.5rem, 4vh, 2.5rem); }
.hero-post h1 {
  max-width: 24ch;
  margin-inline: 0;
  font-size: clamp(2.1rem, 4.4vw, 3.4rem);
  text-transform: none;
}
.post-date {
  margin: 0 0 0.9rem;
  font-family: var(--sans);
  font-size: 0.76rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-faint);
}
.article { max-width: 68ch; }
.article p { margin: 0 0 1.35rem; font-size: 1.06rem; line-height: 1.75; }
.article h2 {
  margin: 2.4rem 0 0.85rem;
  font-size: clamp(1.25rem, 2vw, 1.55rem);
  text-transform: none;
  letter-spacing: -0.01em;
}
.article h2:first-child { margin-top: 0; }
.article p:last-child { margin-bottom: 0; }

/* ---- the footer mark is the logo, not the words ------------------------
   The white rendering in both themes: the footer is a dark slab either way,
   so the coloured wordmark would disappear on it. The alt text carries the
   name, so nothing is lost to a screen reader by dropping the text node. */
.footer .mark {
  margin-bottom: 0.9rem;
  line-height: 0;
}
.footer .mark img {
  width: auto;
  height: 38px;
  max-width: 200px;
}
@media (max-width: 40rem) {
  .footer .mark img { height: 34px; }
}

/* Four columns again, the last one the address on its own. */
.footer-grid { grid-template-columns: 1.5fr 1fr 1fr 1.2fr; }
@media (max-width: 62rem) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 40rem) { .footer-grid { grid-template-columns: 1fr; } }

/* ---- contact cards: the whole card is the link -------------------------
   The number used to be the visible link text and the accessible name at the
   same time. With the numbers gone the arrow carries the affordance and a
   visually-hidden label carries the name - a link whose only content is an
   arrow announces as "link, arrow", which tells a screen-reader user nothing.

   .stretch already covers the card with a click target, so nothing else needs
   to move. */
.card-go {
  display: inline-flex;
  align-items: center;
  margin-top: 1.1rem;
  font-size: 1.35rem;
  line-height: 1;
  color: var(--indigo);
  text-decoration: none;
  transition: transform .2s ease, color .2s ease;
}
:root[data-theme="dark"] .card-go { color: var(--indigo-text, #A897F0); }
.card:hover .card-go { transform: translateX(4px); }
.card:hover { cursor: pointer; }

/* 30 / 70 exactly, at every desktop width. The gap sits on top of the two
   tracks, so it is taken out of the rail rather than allowed to push the pair
   past 100% - with two percentage tracks and a gap the row would otherwise
   overflow its own container. */
@media (min-width: 62.01rem) {
  .section:has(> .shell > .section-head):not(:has(.cars-grid)):is(:has(.cx > .cards),
  :has(.cx > .cars-rail), :has(.cars-grid)) > .shell {
    grid-template-columns: 30% calc(70% - var(--split-gap));
    --split-gap: clamp(1.4rem, 2.6vw, 2.4rem);
    gap: var(--split-gap);
  }
}

/* ---- every hero centres --------------------------------------------------
   Three variants had drifted apart: the photographic heroes were centred, the
   plain ones left-aligned by the first cinematic pass, and the article heroes
   left by their own rule. One statement for all three.

   .hero-grid is the two-column hero - only the template demo still uses one -
   and it keeps its left alignment, because centring one half of a two-column
   row reads as an accident. */
.hero .shell:not(.hero-grid) { text-align: center; }
.hero .shell:not(.hero-grid) h1,
.hero .shell:not(.hero-grid) .lede { margin-inline: auto; text-align: center; }
.hero .shell:not(.hero-grid) .btn-row { justify-content: center; }
.hero-post .post-date { text-align: center; }

/* ---- "Across the PRM Group." -------------------------------------------
   Centred and wider than the standard heading block. Targeted by :has() on
   the brand panels rather than by adding a class, so the markup stays as the
   build writes it - this is the only section on the site with them.

   The 34ch measure and the left alignment come off together: a centred block
   at 34ch reads as a narrow column adrift in the middle of the page. */
.section:has(.brandpanels) > .shell > .section-head {
  text-align: center;
  margin-inline: auto;
  max-width: 96ch;
}
.section:has(.brandpanels) > .shell > .section-head h2 {
  max-width: none;
  margin-inline: auto;
}
.section:has(.brandpanels) > .shell > .section-head .lede {
  max-width: 88ch;
  margin-inline: auto;
  text-align: center;
}
/* the rule that opens a section heading centres with it */
.section:has(.brandpanels) > .shell > .section-head::before { margin-inline: auto; }

/* The two group panels are the same height already - it is the buttons that
   sat at different points, because one card's copy runs to three lines and
   the other's to two. Making the panel a column and giving the button
   margin-top: auto pins both to the foot of their card, so they line up
   whatever the copy does. */
.brandpanel {
  display: flex;
  flex-direction: column;
}
.brandpanel .btn {
  margin-top: auto;
  align-self: center;
}

/* The homepage version of the group section carries a single short sentence,
   meant to sit on one line. The shared 88ch measure broke it in two, so this
   variant drops the cap and lets the container decide - about 1200px, which
   the sentence clears at this size. /about-us keeps the cap: its sentence is
   twice as long and would run the full width unreadably. */
/* Two caps were in the way, not one. The lede's own 88ch rule outranked this
   variant - .section:has(.brandpanels) ... .lede scores (0,5,0) against
   (0,4,0) - and above it .section-head itself is capped at 96ch, about 880px,
   while the sentence needs about 886 at its own size. It was wrapping by six
   pixels. Both caps come off here, and the selector is written to outrank the
   shared one. */
.section.group-oneline:has(.brandpanels) > .shell > .section-head,
.section.group-oneline:has(.brandpanels) > .shell > .section-head .lede {
  max-width: none;
}
@media (max-width: 62rem) {
  .section.group-oneline:has(.brandpanels) > .shell > .section-head .lede { max-width: 62ch; }
}


/* ---- the listings heading: centred, full width -------------------------
   Now that this section is not split, its heading has the whole row. The 34ch
   cap and the left alignment were written for a narrow column beside a rail,
   and a 34ch block centred in a 1200px row reads as adrift. */
.section:has(.cars-grid) > .shell > .section-head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}
.section:has(.cars-grid) > .shell > .section-head h2,
.section:has(.cars-grid) > .shell > .section-head .lede {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}
.section:has(.cars-grid) > .shell > .section-head::before {
  margin-inline: auto;   /* the gold rule centres with the words above it */
}

/* ---- the marque block's heading: centred, full width -------------------
   The logos below it are centred, so a left-aligned 34ch heading above them
   sat off to one side of its own section. Matched by :has() on the static
   marque row - the homepage strip is .marquee-track and has no heading, so it
   is not touched. */
.section:has(> .shell > .marques) > .shell > .section-head {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}
.section:has(> .shell > .marques) > .shell > .section-head h2,
.section:has(> .shell > .marques) > .shell > .section-head .lede {
  max-width: none;
  margin-inline: auto;
  text-align: center;
}
.section:has(> .shell > .marques) > .shell > .section-head::before { margin-inline: auto; }

/* ---- Load more, through the carousel shell ------------------------------
   The toggle works by sibling: .more-toggle:checked ~ .cars-grid. The carousel
   pass wraps every group in a .cx, so the grid stopped being a sibling of the
   checkbox and the "show" rule stopped matching - while the "hide" rule, which
   needs no sibling, kept working. Cards 7-9 were hidden with no way to reveal
   them, and the button appeared to do nothing.

   Both shapes are matched now, so it works whether or not a group is wrapped. */
.more-toggle:checked ~ .cx > .cars-grid.is-capped > .car:nth-child(n+7),
.more-toggle:checked ~ .cars-grid.is-capped > .car:nth-child(n+7) {
  display: flex;
}
.more-toggle:checked ~ .more-btn { display: none; }

/* ==========================================================================
   CAR DETAILS POPUP
   --------------------------------------------------------------------------
   :target, as the before/after lightbox is: the card is a link to #id, the
   panel is hidden until it is the target, and both the backdrop and the cross
   are links to #_. No script - and because the panel is a real place in the
   page, the back button closes it and a link to one car can be shared.
   ========================================================================== */
.carlb {
  position: fixed;
  inset: 0;
  z-index: 120;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(1rem, 4vh, 3rem) var(--gut);
}
.carlb:target { display: flex; }
.carlb-back {
  position: absolute;
  inset: 0;
  background: rgba(11,11,12,0.72);
  backdrop-filter: blur(2px);
}
.carlb-panel {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr;
  width: min(1120px, 100%);
  max-height: 88svh;
  overflow: hidden;              /* the two columns scroll, not the panel */
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--n-200);
  border-radius: var(--r-lg);
  box-shadow: 0 40px 90px -40px rgba(0,0,0,0.6);
}
/* half pictures, half specification - the shape a listing is read in */
@media (min-width: 52rem) {
  .carlb-panel { grid-template-columns: 1fr 1fr; }
}
.carlb-close {
  position: absolute;
  top: 0.6rem;
  right: 0.75rem;
  z-index: 3;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  background: rgba(11,11,12,0.55);
  color: #fff;
  font-size: 1.5rem;
  line-height: 1;
  text-decoration: none;
}

/* ---- left: the pictures ---- */
.carlb-media { position: relative; background: var(--n-100); min-width: 0; }
.carlb-media .cx { height: 100%; }
.carlb-rail {
  display: flex;
  height: 100%;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
}
.carlb-rail::-webkit-scrollbar { display: none; }
.carlb-slide {
  flex: 0 0 100%;
  scroll-snap-align: start;
  margin: 0;
  min-width: 0;
}
.carlb-slide img {
  width: 100%;
  height: 100%;
  min-height: 15rem;
  object-fit: cover;
  display: block;
}
@media (max-width: 51.99rem) {
  .carlb-slide img { aspect-ratio: 16 / 10; height: auto; }
}

/* ---- right: the specification ---- */
.carlb-body {
  display: flex;
  flex-direction: column;
  min-width: 0;
  min-height: 0;
}
.carlb-scroll {
  overflow-y: auto;
  padding: clamp(1.25rem, 2.4vw, 2rem);
}
.carlb-body h3 { margin: 0 0 0.35rem; font-size: clamp(1.15rem, 1.9vw, 1.45rem); }
.carlb-body .car-price { margin: 0 0 1.1rem; }
.carlb-specs { display: grid; gap: 0; margin: 0 0 1.1rem; }
.carlb-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.6rem 0;
  border-bottom: 1px solid var(--n-200);
}
.carlb-row dt { margin: 0; color: var(--ink-faint); font-size: 0.78rem;
                letter-spacing: 0.06em; text-transform: uppercase; }
.carlb-row dd { margin: 0; font-weight: 600; }
.carlb-note { margin: 0; font-size: 0.85rem; color: var(--ink-faint); }
/* the buttons sit below the scrolling specs, always reachable */
.carlb-actions {
  padding: 1rem clamp(1.25rem, 2.4vw, 2rem) clamp(1.25rem, 2.4vw, 2rem);
  border-top: 1px solid var(--n-200);
  background: var(--paper);
}

/* arrows only when there is more than one picture, and carousel.js has wired
   them - .cx-ready is added by the script */
.carlb-media .cx-ready .cx-btn { display: flex; }
.carlb-media .cx-btn { left: auto; }
.carlb-media .cx-ready .cx-prev { left: 0.5rem; }
.carlb-media .cx-ready .cx-next { right: 0.5rem; }

/* the page behind does not scroll while a panel is open. The lightbox is the
   same kind of overlay and was left out of this - with it open the wheel
   scrolled the page underneath, which is disorienting when the overlay does
   not move with it. */
html:has(.carlb:target), html:has(.lb:target) { overflow: hidden; }

/* The entrance animates TRANSFORM ONLY. With opacity in the keyframes and
   fill-mode both, a panel opened straight from a URL - someone following a
   link to one car - could sit at the animation's start state and render
   invisible over its own backdrop. Nothing about whether the panel can be
   seen depends on an animation having run. */
@media (prefers-reduced-motion: no-preference) {
  .carlb:target .carlb-panel { animation: carlb-in .22s ease-out; }
}
@keyframes carlb-in {
  from { transform: translateY(12px) scale(0.99); }
  to   { transform: none; }
}

/* ==========================================================================
   THE STOCK VEIL
   --------------------------------------------------------------------------
   Nine placeholder cars with prices and COE dates read as real stock, which
   is the one thing they must not do. The cards stay - they show what the
   listing will look like - but they sit behind a blur with a card over them
   saying what they are and where the real cars are.

   Pointer events come off the cards: a blurred card that still opens a popup
   of a car that does not exist is worse than no card at all.
   ========================================================================== */
.section-stock > .shell { position: relative; }
/* Blurred only while the veil is actually in the page. The build drops the veil
   as soon as every car is a real record (STOCK_IS_REAL in build-site.py), and
   this makes that one change enough - without it, lifting the veil would leave
   the real stock blurred and unclickable. */
.shell:has(> .stock-veil) .stock-wrap {
  filter: blur(5px) saturate(0.75);
  opacity: 0.55;
  pointer-events: none;
  user-select: none;
}
.stock-veil {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--gut);
  /* above the blurred cards, and the only thing clickable here */
  z-index: 2;
}
.stock-veil-card {
  max-width: 34rem;
  padding: clamp(1.5rem, 3vw, 2.4rem);
  background: var(--paper);
  border: 1px solid var(--n-200);
  border-radius: var(--r-lg);
  box-shadow: 0 30px 70px -40px rgba(11,11,12,0.55);
  text-align: center;
}
.stock-veil-card h3 {
  margin: 0 0 0.6rem;
  font-size: clamp(1.2rem, 2.2vw, 1.6rem);
  text-transform: none;
}
.stock-veil-card p {
  margin: 0 0 1.4rem;
  color: var(--ink-soft);
  font-size: 0.98rem;
  line-height: 1.6;
}
/* the Load more button belongs to stock nobody can reach yet */
.section-stock:has(.stock-veil) .more-btn { display: none !important; }
@media (max-width: 40rem) {
  .shell:has(> .stock-veil) .stock-wrap { filter: blur(4px) saturate(0.8); }
}

/* A spec with no value yet: present, so the card keeps its shape and the
   label says what is coming, but visibly empty rather than a figure a reader
   could take at face value. */
.car-specs dd.is-pending { color: var(--ink-faint); font-weight: 400; }

/* With the paragraph gone the heading sat straight on top of the button. The
   gap is on the heading rather than the button, so it holds whether or not a
   line of copy comes back between them. */
.stock-veil-card h3 { margin-bottom: clamp(1.4rem, 3vh, 2.1rem); }
.stock-veil-card p + .btn { margin-top: 0; }

/* On the homepage the stock section is split, so a veil at inset:0 covers the
   whole row - the heading, and the "Cannot find what you are looking for?"
   block with its WhatsApp button, which it would also make unclickable. Pinned
   to the rail's own grid cell instead, so only the cars are behind it.

   /buy is excluded: its section is not split, and there the veil should cover
   the whole listing. */
@media (min-width: 62.01rem) {
  .section-stock:has(.cx > .cars-rail):not(:has(.cars-grid)) > .shell > .stock-veil {
    grid-column: 2;
    grid-row: 1 / span 2;
  }
}

/* The veil and the rail share one grid cell rather than the veil being
   absolutely positioned over the row. An absolutely positioned grid child is
   laid against the grid AREA, which is wider than the rail itself, so the
   panel sat about 25px right of the cars it belongs to. As a grid item in the
   same cell it is exactly as wide as the rail, and centring is centring on the
   carousel. */
@media (min-width: 62.01rem) {
  .section-stock:has(.cx > .cars-rail):not(:has(.cars-grid)) > .shell > .stock-wrap {
    grid-column: 2;
    grid-row: 1 / span 2;
  }
  .section-stock:has(.cx > .cars-rail):not(:has(.cars-grid)) > .shell > .stock-veil {
    position: relative;
    inset: auto;
    grid-column: 2;
    grid-row: 1 / span 2;
    align-self: center;
    justify-self: center;
    width: 100%;
    padding: 0;
  }
}

/* The veil's button in dark mode. --indigo is lifted to #6C56C9 so white text
   can sit on it, and at that saturation it reads as a stray UI colour on a
   near-black panel - the one bright thing in the frame, and not a brand one.
   The dark theme's own accent is the gold, which is what the section rules and
   the hero's second line already use. Dark text on gold measures far past AA. */
:root[data-theme="dark"] .stock-veil-card .btn-primary {
  background: var(--gold-bright);
  border-color: var(--gold-bright);
  color: #141418;
}
:root[data-theme="dark"] .stock-veil-card .btn-primary:hover {
  background: #EFD489;
  border-color: #EFD489;
  color: #141418;
}

/* The veil panel, raised in dark mode. Its shadow is black at low opacity,
   which does nothing on a near-black page - the panel was sitting flat on the
   blur. Same three-part treatment the cards use: a lighter rim, a one-pixel
   lit top edge, and a deeper black shadow underneath that separates it from
   the blurred cars without being visible in itself.

   Not a light-coloured shadow: a white glow around a panel reads as something
   emitting light, not something above the surface. */
:root[data-theme="dark"] .stock-veil-card {
  border-color: rgba(255,255,255,0.12);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.07),
    0 28px 60px -30px rgba(0,0,0,0.95);
}


/* The burger follows the bar: white on the black dark-mode bar, ink on the
   light one. The at-hero rule above only covered a photographic hero, which
   is no longer the only time the bar is dark. */
@media (max-width: 980px) {
  :root[data-theme="dark"] .menu-bars,
  :root[data-theme="dark"] .menu-bars::before,
  :root[data-theme="dark"] .menu-bars::after { background: #fff; }
  :root[data-theme="light"] .menu-bars,
  :root[data-theme="light"] .menu-bars::before,
  :root[data-theme="light"] .menu-bars::after { background: var(--ink); }
}

/* The open menu is a flex column at a fixed height, and flex items shrink by
   default. Once the list is taller than the screen every row is squeezed - and
   a row holding an open submenu is squeezed below its own contents, so the
   submenu spills over the link beneath it.
   Items keep their natural height; the panel scrolls instead. */
@media (max-width: 980px) {
  .menu-toggle:checked ~ .nav > *,
  .menu-toggle:checked ~ .nav .has-sub { flex: 0 0 auto; }
}

/* ---- no rules in the mobile menu ---------------------------------------
   Every row, the submenu, and the divider before the two outside links all
   carried a hairline. Written out for both themes because the light-mode
   colour overrides score higher than a plain rule and would otherwise put the
   lines back. Spacing alone separates the rows now. */
@media (max-width: 980px) {
  .menu-toggle:checked ~ .nav > a,
  .menu-toggle:checked ~ .nav .has-sub,
  .menu-toggle:checked ~ .nav .has-sub > a,
  .menu-toggle:checked ~ .nav .sub,
  .menu-toggle:checked ~ .nav .sub li,
  .menu-toggle:checked ~ .nav .sub li.is-ext,
  .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext,
  .menu-toggle:checked ~ .nav .sub a,
  :root[data-theme="light"] .menu-toggle:checked ~ .nav > a,
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .has-sub > a,
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub,
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext,
  :root[data-theme="dark"] .menu-toggle:checked ~ .nav > a,
  :root[data-theme="dark"] .menu-toggle:checked ~ .nav .has-sub > a,
  :root[data-theme="dark"] .menu-toggle:checked ~ .nav .sub {
    border: 0;
  }
  /* the two outside links keep their gap, which the divider used to mark */
  .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext { margin-top: 0.75rem; }
}

/* One line kept: the divider before Porschify. Everything above it is a PRM
   page; the last two go to other companies' sites, and that is worth marking
   with more than a gap. Both themes written out, for the same reason the
   removal was - the light-mode colour rules outrank a plain selector. */
@media (max-width: 980px) {
  :root[data-theme="dark"] .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext {
    border-top: 1px solid rgba(255,255,255,0.16);
  }
  :root[data-theme="light"] .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext {
    border-top: 1px solid var(--n-200);
  }
  .menu-toggle:checked ~ .nav .sub li:not(.is-ext) + li.is-ext {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
  }
}

/* ---- headings centre on a phone ----------------------------------------
   The left-aligned heading block is a desktop arrangement: there it sits in a
   column beside a rail, and the alignment ties the two together. Stacked on a
   phone there is nothing to tie it to, so every section heading, its lede and
   the rule above it centre. The gold rule centres with them, or it hangs off
   the left of centred words.

   62rem, the width at which the split sections stack. */
@media (max-width: 62rem) {
  .section-head,
  .svc-cta {
    text-align: center;
    margin-inline: auto;
    max-width: none;
  }
  .section-head h2,
  .section-head .lede,
  .svc-cta h2,
  .svc-cta .lede {
    margin-inline: auto;
    text-align: center;
    max-width: 42ch;
  }
  .section-head::before { margin-inline: auto; }
}

/* ---- the rest of the text centres on a phone ---------------------------
   The earlier rule only reached .section-head and .svc-cta. These are the
   blocks it missed, found by walking every paragraph and heading in <main> at
   430px rather than by eye:

     two-column rows   their h2 and lede sit in a plain <div>, not a
                       .section-head - "Everything premium", "You speak to
                       someone", "Visit PRM Group"
     cards             heading and body
     car tiles         model and price, but NOT the spec rows
     news tiles        title and Read more
     the ask block     its paragraph; the buttons were already centred
     the address       under the map

   Deliberately left alone:
     .pointer          the /sell list aligns on its icons, by request
     .car-specs rows   label left, value right - a spec sheet, not prose
     .qa               a question with a chevron at the end of its own line
     .article          blog prose: centred body text is unreadable
   ========================================================================== */
@media (max-width: 62rem) {
  .grid-2 > div > h2,
  .grid-2 > div > .lede,
  .card h3,
  .card > p,
  .car-body h3,
  .car-body .car-price,
  .postcard-title,
  .postcard-more,
  .ask-instead p,
  .map-nap {
    text-align: center;
  }
  .card .btn-row,
  .card-cta { justify-content: center; }
  .ask-instead { justify-content: center; }
}

/* Naming each block one at a time kept missing ones - the steps on /sell, the
   "What to include" panel on /buy. Headings and paragraphs inside a section
   centre by type instead, with the four places that must not:

     .article   blog prose; centred body text is genuinely hard to read
     .carlb     the popup has its own layout
     .qa        a question with a chevron at the end of its line
     lists      pointers align on their icons by request, and dt/dd rows are
                label-left value-right, which is a spec sheet not prose
   ========================================================================== */
@media (max-width: 62rem) {
  main section :is(h2, h3, p):not(.article *):not(.carlb *):not(.qa *):not(li *) {
    text-align: center;
  }
}

/* The text centred but the buttons under it did not, which read as a mistake
   rather than a choice. Centring .card .btn-row and .card-cta above only
   covered the ones inside cards; the CTA block at the foot of a page, the
   hero rows and the two-column rows kept their left edge.

   Every button row inside main centres below 62rem. The car popup is left
   out for the same reason as before - it has its own layout. */
@media (max-width: 62rem) {
  main :is(.btn-row, .card-cta, .car-actions, .ask-instead, .btn-row-mid):not(.carlb *):not(.carlb-actions) {
    justify-content: center;
  }
}

/* The panel sat flush against the word above it, so its gold top border read
   as a second underline under SERVICES rather than the top of a panel.

   Ten pixels of air. The invisible bridge that stops the pointer falling
   through on the way down has to grow with it, or the panel closes as the
   cursor crosses the gap - it covers twelve, slightly overlapping the
   trigger. Desktop only; the mobile menu stacks and has no gap to bridge. */
@media (min-width: 981px) {
  .sub { margin-top: 10px; }
  .sub::before { top: -12px; height: 12px; }
}

/* The popup's picture rail is only wrapped in a .cx shell when the car has
   more than one photograph, so the height has to be set on the rail itself
   as well - otherwise a single-photo popup leaves its left column short. */
.carlb-media > .carlb-rail { height: 100%; }

/* The block that gives an arrow its shape - absolute, round, 34px - sits
   inside @media (max-width: 62rem), and the wide-screen rails take theirs
   from the section rule further up. The popup's picture rail belongs to
   neither, so above 62rem its arrows were left as plain glyphs in the flow:
   20px wide, no circle, and sitting over the backdrop, where a click closed
   the panel instead of changing the picture. They get the same shape here,
   at every width. */
.carlb-media .cx-ready .cx-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 6;
  width: 38px;
  height: 38px;
  padding: 0 0 2px;
  border-radius: 999px;
  border: 1px solid var(--n-200);
  background: rgba(255,255,255,0.96);
  box-shadow: 0 6px 18px -10px rgba(11,11,12,0.5);
  color: var(--ink);
  font: 1.5rem/1 var(--sans);
  cursor: pointer;
}
.carlb-media .cx-ready .cx-prev { left: 0.5rem; right: auto; }
.carlb-media .cx-ready .cx-next { right: 0.5rem; left: auto; }

/* An arrow with nowhere to go. carousel.js puts this on the left arrow at the
   first card and on the right arrow at the last, and on both when a rail
   already fits. Not display:none - the arrows are positioned against the
   shell, so removing one moves nothing, and this way it fades. */
.cx-btn.cx-off {
  opacity: 0;
  visibility: hidden;
  pointer-events: none;
}
/* visibility is switched at the right end of the fade: instantly on the way
   in, after the fade on the way out. Transitioning it like opacity makes it
   flip half way through, which shows as a blink. */
.cx-btn { transition: opacity 0.18s ease, visibility 0s linear 0s; }
.cx-btn.cx-off { transition: opacity 0.18s ease, visibility 0s linear 0.18s; }

/* The sister-brand marks are the client's own artwork now, lifted off their
   backgrounds. Porschify is a single dark ink and would disappear on a dark
   panel, so it ships twice and the panel shows the one that reads - the same
   two-file approach as the header wordmark, for the same reason: a filter
   would be fighting the artwork rather than respecting it.

   Sprayboxx is red and orange and needs neither copy nor correction. */
.brandpanel .brand-ink-white { display: none; }
:root[data-theme="dark"] .brandpanel:has(.brand-ink-white) .brand-ink { display: none; }
:root[data-theme="dark"] .brandpanel .brand-ink-white { display: block; }


/* ---- Section rhythm on a phone -----------------------------------------
   Measured on a 390x667 handset: .section computed to 93.38px top AND bottom,
   so any two sections sat 187px apart - 28% of the viewport spent on nothing,
   and on a long page like /buy that is most of a scroll between one heading
   and the next. The figure comes from clamp(4.5rem, 11vh, 8.5rem), whose 4.5rem
   floor was set for a desktop and never relaxed for a small screen.

   Roughly half, and still generous: 80px between sections at this height.

   All three selectors are named because they do not share specificity -
   .section:has(.marques:not(.marquee-track)) outranks a bare .section, so a
   rule written against .section alone would leave the /buy marque row at its
   old 80px while everything around it moved. */
@media (max-width: 40rem) {
  /* .section-marquerow is excluded: it sets its own padding to 0 further down
     and pairs it with a min-height, so the logo strip sits tight against what
     is above and below it. Sweeping it into this rule gave it 40px it had
     deliberately given up. */
  .section:not(.section-marquerow),
  .section-tight,
  .section:has(.marques:not(.marquee-track)) {
    padding-block: clamp(2.5rem, 6vh, 3.5rem);
  }
}


/* The hidden attribute, defended.
   A module carrying hidden=True relies on the UA rule [hidden]{display:none}.
   Nothing sets display on .section today, so it works - but this stylesheet is
   append-only and three separate faults this week were a later rule quietly
   beating an earlier one. A future `.section { display: grid }` would put a
   hidden section back on the page with no error anywhere. */
[hidden] { display: none !important; }


/* A gallery of four is 2x2, not 3+1.
   .svc-gallery is a three-column grid, which suits three or six. Four leaves a
   single picture alone on a second row, reading as something missing rather
   than as a layout. Scoped by count so three and six are untouched, and only
   above the width where the grid is three-up at all. */
@media (min-width: 62.01rem) {
  .svc-gallery-4 { grid-template-columns: repeat(2, 1fr); }
}
