/* ============================================================
   Detroit Metro Luxury Car Rental - design system

   The palette is the network's, not this door's. Ground is pure
   black, two raised near-black surfaces sit on it, and one gold
   carries every accent. That set is byte for byte the one this
   repository was split out with, and it is shared by all five
   satellites again: a colour scheme is not what keeps five doors
   apart, the writing and the layout are, and those stay this
   site's own.

   What did not come back is --line-strong. The original drew the
   quiet button, the menu button and the filter chip with
   rgba(255, 255, 255, 0.20), which is 1.66:1 over this ground
   against a floor of 3:1 for anything a visitor operates. Those
   boundaries take --line-ui instead, which is the palette's own
   muted grey rather than a new colour. --line stays decoration.

   Layout, spacing, the serif accent voice and the almost square
   corner are unchanged. Only colour was reverted.

   Contrast is computed by tests/contrast.mjs, not eyeballed.
   Every colour below is measured there against the surface it is
   actually painted on, and the test fails the build on a miss.
   The new elements are measured with the rest: the lead form,
   the inventory grid, and the loading, empty and error rows did
   not exist when this palette was first written.

   The face is TeX Gyre Adventor, an open metric clone of ITC
   Avant Garde Gothic (GUST Font License / LPPL 1.3c). It ships
   Regular and Bold only, so display type is set Bold and body
   Regular rather than faked with a synthetic weight.
   ============================================================ */

/* -- Typeface -- */
@font-face {
  font-family: 'Adventor';
  src: url('adventor-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Adventor';
  src: url('adventor-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}

/* -- Tokens -- */
:root {
  /* Ground, and the two surfaces that sit on it. */
  --void:    #000000;
  --surface: #121212;
  --raised:  #1B1B1B;

  --fg:      #FFFFFF;
  --fg-mute: #888888;   /* 5.92 on void, 5.28 on surface, 4.86 on raised */

  /* One gold, used for every accent. 8.10 on void, 7.23 on surface, and
     7.59 the other way round for near black text on a gold fill. */
  --gold:     #C49A55;
  --gold-lit: #D9B679;
  --on-gold:  #0B0B0B;

  /* Two rules, and the difference matters. --line is decoration and may be
     quiet: it is the network's original hairline, unchanged. --line-ui
     bounds something a visitor operates, so it is held at 3:1 or better
     against all three surfaces, which rules out --line-strong at 1.66:1.
     It is the palette's muted grey rather than a colour of its own. */
  --line:    rgba(255, 255, 255, 0.10);
  --line-ui: var(--fg-mute);   /* 5.92 on void, 5.28 on surface, 4.86 on raised */

  /* State, not brand. The baseline palette has no counterpart for these
     three: the inventory grid, its per vehicle status and the lead form did
     not exist when it was written, and green, amber and red carry meaning
     that no member of a black and gold palette can carry. They are left
     exactly as they were and are measured with everything else below. */
  --ok:     #8FCF9B;
  --warn:   #E5B769;
  --danger: #F09A93;

  --sans: 'Adventor', 'Century Gothic', 'URW Gothic', -apple-system,
          BlinkMacSystemFont, 'Segoe UI', Helvetica, Arial, sans-serif;
  /* System serif only. No webfont, no third party host, no extra bytes. */
  --serif: Georgia, 'Iowan Old Style', 'Times New Roman', 'Liberation Serif',
           'DejaVu Serif', serif;

  /* Almost square. The other satellites round their cards; this one does
     not, and that single decision does most of the work of making the
     two read as different properties. */
  --r-sm: 2px;
  --r:    3px;
  --r-lg: 4px;

  --maxw:   1240px;
  --gutter: clamp(1.25rem, 5vw, 3.5rem);
  --nav-h:  76px;

  /* Deeper than the network default. Space is the whole treatment. */
  --band: clamp(4.5rem, 9vw, 8rem);

  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --z-nav: 80;

  /* ---- the wiring kit, themed ------------------------------------
     rr-network.css carries no colour of its own; these drive it. The
     ratios each one has to hold are listed in the kit README section
     4.1 and are checked by tests/contrast.mjs. */
  --rr-text:          var(--fg);
  --rr-text-muted:    var(--fg-mute);
  --rr-surface:       var(--surface);
  --rr-surface-2:     var(--raised);
  --rr-border:        var(--line);
  --rr-accent:        var(--gold);
  --rr-price:         var(--gold);
  --rr-ok:            var(--ok);
  --rr-warn:          var(--warn);
  --rr-danger:        var(--danger);
  --rr-focus:         var(--gold);
  /* The field fill is the page ground, not a colour of its own: a black well
     inside a #121212 form is the shape the original palette already had, and
     it is one fewer hex nothing else in the system refers to. */
  --rr-input-bg:      var(--void);
  --rr-input-text:    var(--fg);
  --rr-input-border:  var(--line-ui);
  --rr-placeholder:   var(--fg-mute);
  --rr-button-bg:     var(--gold);
  --rr-button-bg-hover: var(--gold-lit);
  --rr-button-text:   var(--on-gold);
  --rr-button-border: var(--gold);

  /* min(), not a flat 20rem: the kit builds the track as
     minmax(var(--rr-card-min), 1fr), and a flat minimum wider than a 320px
     phone's content box overflows the page sideways with no breakpoint to
     catch it. */
  --rr-card-min: min(20rem, 100%);
  --rr-gap: clamp(1rem, 2.2vw, 1.75rem);
  --rr-gap-tight: 0.5rem;
  --rr-card-pad: 0;
  --rr-card-aspect: 3 / 2;
  --rr-radius: var(--r);
  --rr-radius-inner: var(--r-sm);
  --rr-border-width: 1px;
  --rr-title-size: clamp(1.125rem, 1.6vw, 1.375rem);
  --rr-price-size: 1.5rem;
  --rr-small-size: 0.875rem;
  --rr-font-display: var(--sans);
  --rr-status-transform: uppercase;
  --rr-status-tracking: 0.14em;
  /* --rr-loading-opacity is gone, not set to 1. Holding the token at 1 was
     this site's local workaround for a kit defect, and a workaround that
     lives in a variable is one careless edit from being a defect again. The
     kit no longer has a rule that reads it: rr-network.css carries no
     opacity rule on a card at all, and instead neutralises any that survives
     elsewhere. Element opacity multiplies the copy and the surface under it
     by the same factor, so it can only ever lower a ratio, and 0.55 took
     --fg-mute on --surface from 5.28:1 to 2.44:1. Server rendered stock is
     real content and is never dimmed. */
  /* A disabled control is not read, and its label is not information the
     visitor is being asked to act on, so this one may dim. It is measured
     as a UI pair rather than a body pair in tests/contrast.mjs.
     This number is palette dependent and moved with the palette. The gold is
     darker than the champagne it replaces, so at the 0.5 this carried, the
     near black label over the dimmed fill fell to 2.74:1, under the 3:1
     floor for an operable control. 0.65 puts it at 3.84:1 and still reads as
     unmistakeably inactive. */
  --rr-disabled-opacity: 0.65;
  --rr-motion: 180ms;
  --rr-form-width: 100%;
  --rr-form-pad: clamp(1.5rem, 3vw, 2.25rem);
  --rr-control-height: 3rem;
  --rr-control-pad: 0.75rem 0.9rem;
  --rr-button-pad: 0.9rem 2rem;
  --rr-textarea-height: 8rem;
  --rr-focus-width: 2px;
  --rr-focus-offset: 3px;

  /* The scroll reveal, which is the kit's now rather than this site's. The
     travel is shorter and the curve longer than the network default: this
     palette is quiet and a 14px jump reads as a twitch against it. */
  --rr-reveal-shift: 0.875rem;
  --rr-reveal-motion: 600ms;
  --rr-reveal-delay: 0ms;

  /* Written for this site. Seven identical sentences would breach the
     network's structural distinctness rule.

     --rr-msg-loading paints only while <html> carries .rr-js, so a visitor
     whose script never arrived never sees it and never sees a loading state
     at all. It is a row of text on --rr-surface-2, not a dim: it adds
     content rather than subtracting contrast from the cards already on
     screen. */
  --rr-msg-loading: "Checking each entry against the office.";
  --rr-msg-stale: "The office was not reachable just now, so this is the list as it last stood.";
  --rr-msg-empty: "Nothing is published to this page at the moment.";
  --rr-mark-success: "\2713";
  --rr-mark-error: "\0021";
}

/* -- Reset -- */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--nav-h) + 1.5rem);
}
:target,
[id]:not(body):not(html) { scroll-margin-top: calc(var(--nav-h) + 1.5rem); }

body {
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  background: var(--void);
  color: var(--fg);
  font-family: var(--sans);
  font-size: 1rem;
  line-height: 1.6;
  font-weight: 400;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

main { flex: 1 0 auto; }

img, video, svg { display: block; max-width: 100%; }
img { height: auto; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }

::selection { background: var(--gold); color: var(--on-gold); }

/* -- Focus -- */
:focus { outline: none; }
:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute;
  left: 1rem;
  top: -100%;
  z-index: 200;
  padding: 0.75rem 1.5rem;
  background: var(--gold);
  color: var(--on-gold);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  font-size: 0.8125rem;
  transition: top 0.2s var(--ease);
}
.skip-link:focus-visible { top: 1rem; }

/* -- Layout -- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.band { padding-block: var(--band); }
.band-tight { padding-block: calc(var(--band) * 0.6); }

/* -- Type -- */
h1, h2, h3, h4 {
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.015em;
  text-wrap: balance;
}

.h-page {
  font-size: clamp(2.5rem, 4.8vw, 4rem);
  line-height: 1.03;
  letter-spacing: -0.03em;
}

.h-sec {
  font-size: clamp(2rem, 4.4vw, 3.25rem);
  line-height: 1.08;
  letter-spacing: -0.02em;
}

/* The two-tone heading. The quiet half is the serif, in italic: that one
   pairing is the site's signature and it replaces every eyebrow lockup. */
.h-sec .mute, .h-page .mute {
  font-family: var(--serif);
  font-style: italic;
  font-weight: 400;
  letter-spacing: -0.01em;
  color: var(--fg-mute);
}
.footer-mark .mute, .wordmark .mute { color: var(--fg-mute); }

.h-card {
  font-size: clamp(1.125rem, 1.6vw, 1.375rem);
  line-height: 1.2;
  letter-spacing: -0.01em;
}

.lede {
  font-size: clamp(1.0625rem, 1.45vw, 1.3125rem);
  line-height: 1.55;
  color: var(--fg);
  max-width: 44ch;
}

.body-copy {
  color: var(--fg-mute);
  max-width: 66ch;
}
.body-copy + .body-copy { margin-top: 1rem; }
.body-copy strong { color: var(--fg); font-weight: 400; }

/* The definition paragraph, set in the serif and a step up: it is the
   sentence a search engine or an assistant is most likely to lift whole. */
.answer-block { margin-top: clamp(1.5rem, 3vw, 2.25rem); }
.answer-block > p:first-child {
  font-family: var(--serif);
  font-size: clamp(1.0625rem, 1.35vw, 1.25rem);
  line-height: 1.65;
  color: var(--fg);
  max-width: 60ch;
}

/* Letterspaced micro label. 0.75rem = 12px, the floor the tests hold. */
.micro, .eyebrow {
  font-size: 0.75rem;
  line-height: 1.5;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-mute);
}

/* The serif eyebrow, the one place small gold type is allowed:
   8.10:1 on the ground it sits on. */
.eyebrow {
  font-family: var(--serif);
  font-style: italic;
  font-size: 0.9375rem;
  letter-spacing: 0.08em;
  text-transform: none;
  color: var(--gold);
  margin-bottom: clamp(1.25rem, 2.5vw, 2rem);
}

.sec-head {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem 2.5rem;
  padding-bottom: clamp(1.25rem, 2.5vw, 2rem);
  margin-bottom: clamp(2rem, 4vw, 3.5rem);
  border-bottom: 1px solid var(--line);
}

/* -- Links -- */
.inline-link {
  color: var(--gold);
  text-decoration: underline;
  text-underline-offset: 0.22em;
  text-decoration-thickness: 1px;
  transition: color 0.18s var(--ease);
}
.inline-link:hover { color: var(--gold-lit); }

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  color: var(--gold);
  font-size: 0.9375rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  transition: color 0.18s var(--ease);
}
.arrow-link::after {
  content: '\2192';
  font-weight: 400;
  transition: transform 0.24s var(--ease);
}
.arrow-link:hover { color: var(--gold-lit); }
.arrow-link:hover::after { transform: translateX(0.3em); }

/* -- Buttons: square, letterspaced, no pill anywhere on this site -- */
.actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
}

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.6rem;
  min-height: 54px;
  padding: 0.9rem 2.25rem;
  border-radius: var(--r-sm);
  font-weight: 700;
  font-size: 0.875rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-align: center;
  border: 1px solid transparent;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease),
              border-color 0.18s var(--ease);
}

.btn-primary { background: var(--gold); color: var(--on-gold); border-color: var(--gold); }
.btn-primary:hover { background: var(--gold-lit); border-color: var(--gold-lit); }

.btn-ghost { border-color: var(--gold); color: var(--gold); }
/* The gold at 12%, the network's own hover tint, restored. */
.btn-ghost:hover { background: rgba(196, 154, 85, 0.12); color: var(--gold-lit); border-color: var(--gold-lit); }

.btn-quiet { border-color: var(--line-ui); color: var(--fg); }
.btn-quiet:hover { border-color: var(--fg); background: rgba(255, 255, 255, 0.06); }

/* == Header ================================================== */
/* The alpha here is a contrast number, not a taste.
   A sticky bar does not sit on the page ground. It sits on whatever scrolls
   under it, and on this page that is photographs of cars, one of which has a
   white parking line down it. The ground for everything printed in this bar
   is therefore pure white, the brightest thing a photograph can be, exactly
   as --scrim-a is measured further down.
   The bar is black again with the rest of the palette, but the ALPHA is not
   reverted. At the 0.82 the network shipped, rgba(0,0,0,0.82) over white
   paints rgb(46,46,46) and the muted half of the wordmark, --fg-mute,
   reaches 3.83:1 against it: under the 4.5 floor, on the one element that is
   on screen for the whole visit. No token pair could see it, because the
   ground is not a token.
   0.94 paints rgb(15,15,15): --fg-mute 5.41:1, --gold 7.39:1, --fg 19.17:1,
   and the --line-ui border on the menu button 5.41:1 against the UI floor of
   3. tests/lib/painted.mjs recomputes all of it from this value. */
.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-nav);
  background: rgba(0, 0, 0, 0.94);
  backdrop-filter: saturate(140%) blur(14px);
  -webkit-backdrop-filter: saturate(140%) blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease), background-color 0.25s var(--ease);
}
.site-header.pinned {
  background: rgba(0, 0, 0, 0.95);
  border-bottom-color: var(--line);
}

.site-nav {
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
  height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: clamp(1rem, 3vw, 3rem);
}

.wordmark {
  font-size: 0.875rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  white-space: nowrap;
  margin-right: auto;
}
.wordmark b { font-weight: 700; }
.wordmark span { font-weight: 400; }

.nav-links {
  display: flex;
  align-items: center;
  gap: clamp(1rem, 2.4vw, 2.5rem);
}
.nav-links a {
  font-size: 0.8125rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-weight: 700;
  color: var(--fg-mute);
  transition: color 0.18s var(--ease);
}
.nav-links a:hover, .nav-links a[aria-current='page'] { color: var(--fg); }

.nav-book {
  display: inline-flex;
  align-items: center;
  min-height: 42px;
  padding: 0.5rem 1.35rem;
  border: 1px solid var(--gold);
  border-radius: var(--r-sm);
  color: var(--gold);
  font-weight: 700;
  font-size: 0.75rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  white-space: nowrap;
  transition: background-color 0.18s var(--ease), color 0.18s var(--ease);
}
.nav-book:hover { background: var(--gold); color: var(--on-gold); }

.hamburger {
  display: none;
  width: 44px;
  height: 44px;
  border: 1px solid var(--line-ui);
  border-radius: var(--r-sm);
  align-items: center;
  justify-content: center;
  flex-direction: column;
  gap: 4px;
}
.hamburger i {
  display: block;
  width: 16px;
  height: 1.5px;
  background: var(--fg);
  transition: transform 0.22s var(--ease), opacity 0.22s var(--ease);
}
.hamburger[aria-expanded='true'] i:nth-child(1) { transform: translateY(5.5px) rotate(45deg); }
.hamburger[aria-expanded='true'] i:nth-child(2) { opacity: 0; }
.hamburger[aria-expanded='true'] i:nth-child(3) { transform: translateY(-5.5px) rotate(-45deg); }

.mobile-menu {
  display: none;
  overflow: hidden;
  max-height: 0;
  /* max-height:0 clips the pixels but leaves every link focusable and in the
     accessibility tree, so a keyboard user tabs into a menu they cannot see.
     visibility:hidden is what actually makes it inert. */
  visibility: hidden;
  background: var(--surface);
  border-top: 1px solid var(--line);
  transition: max-height 0.32s var(--ease);
}
.mobile-menu.open { max-height: 26rem; visibility: visible; }
.mobile-menu a {
  display: flex;
  align-items: baseline;
  gap: 1.25rem;
  padding: 1.1rem var(--gutter);
  font-size: 1.0625rem;
  font-weight: 700;
  border-bottom: 1px solid var(--line);
}
.mobile-menu a:last-child { border-bottom: 0; color: var(--gold); }
.mobile-menu a span {
  font-family: var(--serif);
  font-size: 0.8125rem;
  color: var(--fg-mute);
  font-weight: 400;
}

@media (max-width: 900px) {
  .nav-links, .nav-book { display: none; }
  .hamburger { display: flex; }
  .mobile-menu { display: block; }
}

/* == Hero ====================================================
   No full-bleed photograph and no scrim. The copy sits on the
   ground itself, at full strength, and the photograph is framed
   beside it. That is the loudest structural difference between
   this site and its siblings, and it is why the type here never
   needs a wash behind it to stay legible.                      */
.hero {
  padding-block: clamp(3.5rem, 9vw, 8rem) clamp(3rem, 6vw, 5rem);
  border-bottom: 1px solid var(--line);
}

.hero-grid {
  display: grid;
  grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(2.5rem, 5vw, 4.5rem);
  align-items: center;
}

/* The grid column is the measure. A ch cap here would be read against the
   copy's own 1rem font size, not the headline's, and it once squeezed a 4rem
   h1 into a 280px column one word per line. */
.hero-copy { min-width: 0; }
.hero .lede { margin-top: clamp(1.25rem, 2.5vw, 1.75rem); }
/* Stacked and aligned rather than wrapped. The primary label names the site
   the visitor is about to leave for, which makes it wide enough that a row
   wraps into a ragged pair at every width this column ever has. */
.hero .actions {
  margin-top: clamp(2rem, 4vw, 2.75rem);
  flex-direction: column;
  align-items: stretch;
  max-width: 28rem;
}

.hero-claim {
  margin-top: clamp(1.5rem, 3vw, 2rem);
  padding-top: 1.25rem;
  border-top: 1px solid var(--line);
  color: var(--fg-mute);
  font-size: 0.9375rem;
  max-width: 38ch;
}
.hero-claim b {
  font-family: var(--serif);
  font-size: 1.375rem;
  font-weight: 400;
  font-style: italic;
  color: var(--gold);
}
.hero-claim [data-rr-inventory-count] {
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

.hero-plate { position: relative; }
.hero-plate img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
  border-radius: var(--r);
  background: var(--surface);
}
.hero-plate figcaption {
  margin-top: 1rem;
  padding-top: 0.85rem;
  border-top: 1px solid var(--line);
}

@media (max-width: 900px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-plate img { aspect-ratio: 4 / 3; }
}

/* -- Fact rail: hairlines, not boxes -- */
.rail {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  border-bottom: 1px solid var(--line);
}
.rail > div {
  padding: clamp(1.5rem, 3vw, 2.25rem) clamp(1rem, 2vw, 1.75rem);
  border-left: 1px solid var(--line);
}
.rail > div:first-child { border-left: 0; padding-left: 0; }
.rail dt { margin-bottom: 0.6rem; }
.rail dd {
  font-family: var(--serif);
  font-size: clamp(1.375rem, 2.6vw, 2rem);
  line-height: 1.1;
  color: var(--fg);
  font-variant-numeric: tabular-nums;
}

@media (max-width: 760px) {
  .rail { grid-template-columns: repeat(2, 1fr); }
  .rail > div:nth-child(odd) { border-left: 0; padding-left: 0; }
  .rail > div:nth-child(n + 3) { border-top: 1px solid var(--line); }
}

/* == The list ================================================
   The grid itself comes from rr-network.css and is sized by
   --rr-card-min and --rr-gap above. Only the card is ours.     */
.car {
  display: flex;
  flex-direction: column;
  background: var(--surface);
  border-radius: var(--r);
  overflow: hidden;
  transition: background-color 0.22s var(--ease);
}
.car:hover, .car:focus-within { background: var(--raised); }

.car-media {
  display: block;
  aspect-ratio: 3 / 2;
  background: var(--raised);
  overflow: hidden;
}
.car-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.car:hover .car-media img { transform: scale(1.02); }
.car-nophoto { display: block; width: 100%; height: 100%; background: var(--raised); }

.car-body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: 0.5rem;
  padding: clamp(1.25rem, 2.2vw, 1.75rem);
}

.car-tag {
  font-size: 0.6875rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--fg-mute);
}
.car-tag:empty { display: none; }

.car-body h3 a { transition: color 0.18s var(--ease); }
.car:hover .car-body h3 a { color: var(--gold); }

.car-spec {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem 1.25rem;
  color: var(--fg-mute);
  font-size: 0.875rem;
}
.car-fact b { font-weight: 400; color: var(--fg); }
/* A field the dashboard sends back empty takes its label with it, rather
   than leaving the word "seats" standing on its own after a repaint. */
.car-fact:has(b:empty) { display: none; }

.car-status {
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-mute);
}
.car-status:empty { display: none; }
.car[data-rr-status='available'] .car-status { color: var(--ok); }
.car[data-rr-status='rented'] .car-status,
.car[data-rr-status='maintenance'] .car-status { color: var(--warn); }

.car-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  margin-top: auto;
  padding-top: 1.5rem;
}
.car-price { display: flex; align-items: baseline; gap: 0.4rem; }
.car-price b {
  font-family: var(--serif);
  font-size: clamp(1.5rem, 2.6vw, 1.875rem);
  font-weight: 400;
  color: var(--gold);
  font-variant-numeric: tabular-nums;
}
.car-price span { color: var(--fg-mute); font-size: 0.875rem; }

/* No dimming rule for .car, on purpose.

   A card the build rendered is not a placeholder. It is the real snapshot,
   with a real price on it, and it is the only thing a visitor with no
   JavaScript will ever see. A dim that ships in the HTML is permanent for
   that visitor, because only a script can take the class off again, and it
   breaks the contrast floor rather than bending it: opacity scales the copy
   and the surface behind it together, so --fg-mute on --surface is 5.28:1
   here and 2.44:1 at 0.55.

   The kit now holds the same line rather than leaving it to each site. Its
   stylesheet has no opacity rule on a card and instead neutralises one,
   --rr-loading-opacity is retired and read by nothing, and every state the
   grid can enter is a row of text the kit writes with ::before and this
   file measures like any other copy. The loading row is gated a second time
   on .rr-js, so a page whose script never ran cannot show it.

   The build still ships the grid unmarked. That is belt to the kit's
   braces, not the fix. */
[data-rr-inventory] { align-items: stretch; }

.fleet-note {
  margin-top: clamp(1.5rem, 3vw, 2.25rem);
  max-width: 72ch;
  letter-spacing: 0.08em;
  line-height: 1.7;
}

/* == Bento =================================================== */
.bento {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr 1.1fr;
  gap: clamp(1rem, 2vw, 1.75rem);
  align-items: start;
}
.bento-stack {
  display: grid;
  gap: clamp(1rem, 2vw, 1.75rem);
  grid-column: span 2;
  grid-template-columns: 1fr 1fr;
}

.tile {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  padding: clamp(1.5rem, 2.8vw, 2.25rem);
  background: var(--surface);
  border-radius: var(--r);
  overflow: hidden;
  min-height: 210px;
}
.tile p { color: var(--fg-mute); }
.tile .arrow-link { margin-top: auto; padding-top: 1rem; }

/* -- copy over a photograph --

   Three things went wrong here at once and all three are fixed together.

   1. The copy did not sit where the wash was dark. .tile-copy was flex: 1,
      so it stretched to the whole tile, and .tile .arrow-link{margin-top:auto}
      then pushed every free pixel above the link, parking the heading and the
      paragraph in the top third. The wash was written for the bottom. So the
      copy is now content sized and the tile justifies it to the end: the box
      the copy occupies and the box the wash guarantees are the same box.
   2. The wash was computed against the wrong end of the histogram. A scrim
      protects text from the BRIGHTEST pixel a photo can put behind it, never
      the darkest. plate-angle.jpg has a white parking line in it, and the
      floor has to hold if that photo is swapped for a snow scene tomorrow.
      --scrim-a is therefore measured against pure white, the worst ground any
      photograph can present, by tests/contrast.mjs.
   3. Muted grey is the wrong colour to put on a photograph at all. --fg-mute
      is a quiet voice for a flat surface whose exact luminance is known. Over
      a photograph the copy takes --fg, which has 13.58:1 of room at this
      scrim against white where the muted grey has 3.83:1 and fails. */
:root {
  /* The wash behind copy on a photograph. 0.82 over pure white paints
     rgb(46,46,46): --fg 13.58:1, --gold 5.24:1, both over 4.5. */
  --scrim-a: 0.82;
  --tile-pad: clamp(1.5rem, 2.8vw, 2.25rem);
}

.tile-photo {
  grid-row: span 2;
  /* was flex-start, which is what put the copy under the lightest wash */
  justify-content: flex-end;
  padding: 0;
  min-height: 360px;
}
.tile-photo .tile-copy {
  position: relative;
  z-index: 1;
  display: flex;
  flex-direction: column;
  gap: 0.65rem;
  /* was flex: 1. Content sized, so the wash below is exactly this box. */
  flex: 0 0 auto;
  padding: var(--tile-pad);
  /* Transparent at the top of the padding, at full strength before the
     first glyph, and flat from there down. Bound to the copy box, so it
     cannot drift away from the text again the way a tile-height gradient
     did the moment the layout changed. */
  background: linear-gradient(
    to bottom,
    rgba(0, 0, 0, 0) 0,
    rgba(0, 0, 0, var(--scrim-a)) calc(var(--tile-pad) * 0.7),
    rgba(0, 0, 0, var(--scrim-a)) 100%);
}
/* margin-top: auto from .tile would eat the free space above the link and
   defeat the justification above. There is no free space to distribute in a
   content sized box, but say so rather than rely on it. */
.tile-photo .tile-copy .arrow-link { margin-top: 0; }
.tile-photo img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}
/* A second, gentler wash over the whole tile. This one is for the photograph,
   not for the type: it settles the image and keeps the gold rules
   legible against it. It sits under .tile-copy, so it only ever adds to the
   scrim above and is never counted towards the floor. */
.tile-photo::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0.32) 0%, rgba(0, 0, 0, 0.5) 60%, rgba(0, 0, 0, 0.62) 100%);
}
.tile-photo .tile-copy p { color: var(--fg); }

@media (max-width: 1040px) {
  .bento { grid-template-columns: 1fr 1fr; }
  .bento-lede, .bento-stack { grid-column: span 2; }
}
@media (max-width: 720px) {
  .bento, .bento-stack { grid-template-columns: 1fr; }
  .bento-lede, .bento-stack { grid-column: auto; }
  .tile-photo { grid-row: auto; }
}

/* == Steps =================================================== */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: clamp(1.5rem, 3vw, 3rem);
}
.step { padding-top: 1.5rem; border-top: 1px solid var(--line-ui); }
.step-n {
  display: block;
  margin-bottom: 1.5rem;
  font-family: var(--serif);
  font-size: 1.5rem;
  font-style: italic;
  color: var(--gold);
}
.step h3 { margin-bottom: 0.75rem; }
.step p { color: var(--fg-mute); }

/* == Spec list =============================================== */
.spec { display: grid; border-top: 1px solid var(--line); }
.spec > div {
  display: grid;
  grid-template-columns: 260px 1fr;
  gap: 1.5rem;
  padding: clamp(1.15rem, 2.2vw, 1.65rem) 0;
  border-bottom: 1px solid var(--line);
}
.spec dt {
  color: var(--fg-mute);
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding-top: 0.25rem;
}
.spec dd { color: var(--fg); font-size: 1.0625rem; }

@media (max-width: 760px) {
  .spec > div { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* == Ask: the lead form ====================================== */
.ask {
  display: grid;
  grid-template-columns: 0.9fr 1.1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.ask-copy .lede { margin-top: 1.25rem; }
.ask-copy .body-copy { margin-top: 1.5rem; font-size: 0.9375rem; }

/* The kit styles the form itself. These are the two joins: the label voice,
   and the state line, which has to keep its own colour rather than inherit
   the muted grey the kit gives a resting status. */
.ask-form .rr-label {
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.75rem;
  color: var(--fg-mute);
}
.ask-form .rr-button {
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  font-size: 0.875rem;
  justify-self: start;
}
.ask-state { letter-spacing: 0.04em; }

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

/* == FAQ =====================================================
   Kept open rather than collapsed behind a disclosure: an answer
   a crawler or an assistant cannot read is an answer that does
   not exist, and a test holds that line.                       */
.qa {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0 clamp(2rem, 5vw, 4.5rem);
  align-items: start;
}
.qa > div {
  padding-block: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid var(--line);
}
.qa dt {
  font-weight: 700;
  font-size: 1.0625rem;
  line-height: 1.35;
  margin-bottom: 0.85rem;
  color: var(--fg);
}
.qa dd { color: var(--fg-mute); }

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

/* == CTA ===================================================== */
.cta {
  padding-block: clamp(3.5rem, 8vw, 6.5rem);
  border-top: 1px solid var(--gold);
  border-bottom: 1px solid var(--line);
  text-align: center;
}
.cta .actions { justify-content: center; margin-top: 2.5rem; }
.cta .lede { margin-inline: auto; margin-top: 1.25rem; text-align: center; }
.cta-inner { padding-inline: clamp(1rem, 4vw, 3rem); }

/* == Footer ================================================== */
.site-footer {
  flex: none;
  background: var(--surface);
  padding-block: clamp(3.5rem, 7vw, 5.5rem) 2rem;
}
.footer-inner { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }

.footer-mark {
  font-size: 0.875rem;
  letter-spacing: 0.26em;
  text-transform: uppercase;
  margin-bottom: clamp(2rem, 4vw, 3rem);
}
.footer-mark b { font-weight: 700; }

.footer-cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 2.5rem 2rem;
}
.footer-cols h2 {
  font-size: 0.75rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-mute);
  font-weight: 400;
  margin-bottom: 1.25rem;
}
.footer-cols ul { display: grid; gap: 0.75rem; }
.footer-cols a, .footer-cols li {
  font-size: 0.9375rem;
  color: var(--fg-mute);
  /* admin@rochester.rentals is a single unbreakable token wider than this
     column between roughly 700 and 1100px, where auto-fit is still handing
     out 200px tracks. Without this it escapes the column instead of wrapping. */
  overflow-wrap: anywhere;
}
.footer-cols a { transition: color 0.18s var(--ease); }
.footer-cols a:hover { color: var(--gold); }

.footer-base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 0.75rem 2rem;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: 0.75rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--fg-mute);
}

/* == Reveals =================================================
   There is no reveal rule in this file any more, and there must
   not be one again. C5.

   What used to be here was `.rise { opacity: 0 }` plus a
   `.rise.in` that only assets/site.js ever added. That hides the
   whole page below the hero using a stylesheet that always
   loads, keyed to a script that sometimes does not: one 404, one
   parse error, one CDN hiccup and the site paints a header and
   nothing else, with a perfectly healthy CSS file and no error
   anywhere. A <noscript> block does not save it either, because
   a script that fails to LOAD is not a browser with scripting
   off.

   Reveal now belongs to rr-network.css, where the base state is
   visible and the hidden state exists only while <html> carries
   .rr-js. assets/rr-reveal-gate.js adds that class and takes it
   away again unless the kit claims it. So the worst case is a
   page that arrives without animation.

   .rise is kept as the class name because the kit treats it as
   an alias for data-rr-reveal, so the templates did not need a
   find and replace to become fail-safe.
   Tune it with --rr-reveal-shift, --rr-reveal-motion and
   --rr-reveal-delay in the token block above.               */

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  /* rr-network.css already forces the finished state here. Repeating it
     would be a reveal rule in this file, which is the thing above. */
  .car:hover .car-media img { transform: none; }
}
