/* Top Gear Car Wash — Innisfail
   Plain CSS, no build step. Tokens first, then base, then sections.

   Palette comes from the building: Innisfail is cobalt blue, warm yellow and
   grey concrete, and the wordmark is orange/amber. The "modern" is carried by
   space, scale and photography rather than by a dark theme. */

:root {
  /* ---- colour ---- */
  --blue-950: #06182b;
  --blue-900: #0b2742;
  --blue-800: #123a63;
  --blue-700: #17508c;
  --blue-500: #2b7fd4;
  --blue-300: #8fc2f0;

  --amber-300: #ffcc78;
  --amber-400: #ffb648;
  --amber-500: #f7941e;
  /* The label amber. It only ever prints small — eyebrows at 15px, spec and
     package headings at 13px — so it has to clear 4.5:1 as body text, not 3:1
     as a graphic. The old #d97406 was 3.1:1 on paper and 2.8:1 on the tinted
     sections, which is most of the small type on the page. This clears 4.5 on
     all three light surfaces (5.1 paper, 4.6 paper-2, 5.3 white). Use
     --amber-500 where the amber is a rule, a bar or a big number instead. */
  --amber-600: #a35800;

  --paper:     #fbfaf7;
  --paper-2:   #f2eee7;
  --paper-3:   #e7e1d7;
  --ink:       #141b24;
  --ink-2:     #47535f;
  /* Was #6f7b87, which is 4.1:1 on paper — under AA, and it is used for the
     price disclaimer and the "last updated" line, both 13px. */
  --ink-3:     #5f6a75;
  --line:      #ded7cb;
  /* --line is a divider and is allowed to be quiet. A form control's border is
     the only thing saying where the field is, so it owes 3:1 (this is 3.4). */
  --line-input: #828c96;

  /* ---- type ---- */
  --font: "Archivo", ui-sans-serif, system-ui, -apple-system, "Segoe UI",
          Roboto, Helvetica, Arial, sans-serif;

  --t-hero:  clamp(2.6rem, 1.3rem + 5.2vw, 5.6rem);
  --t-h2:    clamp(2rem, 1.3rem + 2.6vw, 3.4rem);
  --t-h3:    clamp(1.25rem, 1.05rem + 0.8vw, 1.6rem);
  --t-lead:  clamp(1.075rem, 0.98rem + 0.45vw, 1.35rem);
  --t-body:  1.0625rem;
  --t-small: 0.9375rem;
  --t-micro: 0.8125rem;

  /* ---- space ---- */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;

  --section-y: clamp(3.5rem, 2rem + 6vw, 7rem);

  /* ---- layout ---- */
  --wrap: 1180px;
  --wrap-narrow: 760px;
  --gutter: 1rem;
  --radius: 14px;
  --radius-lg: 22px;

  /* Measured height of the sticky header: the wordmark (44px, 52px from 40em),
     the rule and the INNISFAIL line stacked under it, and 0.75rem of padding
     top and bottom. Anything that has to sit clear of the header measures from
     here rather than guessing. Re-measure if the brandmark changes. */
  --header-h: 96px;

  --shadow: 0 1px 2px rgb(6 24 43 / 0.06), 0 8px 24px -8px rgb(6 24 43 / 0.14);
  --shadow-lg: 0 2px 4px rgb(6 24 43 / 0.06), 0 24px 56px -16px rgb(6 24 43 / 0.28);
}

@media (min-width: 40em) {
  :root { --gutter: 2rem; --header-h: 104px; }
}

/* Ultrawide. Without these the whole page sits in a 1180px ribbon down the
   middle of a 3200px monitor and reads as stranded. The container grows in two
   steps and the body text grows once; the type clamps deliberately stop, so
   headings don't become billboards. */
@media (min-width: 100em) {
  :root {
    --wrap: 1320px;
    --gutter: 3rem;
    --t-body: 1.125rem;
  }
}

@media (min-width: 140em) {
  :root { --wrap: 1460px; }
}

/* ---------- base ---------- */

*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

/* Without an offset every nav link lands the section's eyebrow underneath the
   sticky header. The extra 1rem keeps the heading off it rather than flush.
   scroll-margin on the sections rather than scroll-padding on <html> because
   the page has two scroll targets that are not sections: the menu sentinels,
   which sit at the top of the sticky header and are there precisely so that
   following them scrolls by nothing. scroll-padding applies to those too and
   would put a ~112px jump back into the menu; scoping the offset to the
   sections leaves them alone. */
main[id],
main > section[id] {
  scroll-margin-top: calc(var(--header-h) + var(--s-4));
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
  }
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font);
  font-size: var(--t-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  margin: 0;
  line-height: 1.04;
  letter-spacing: -0.022em;
  font-weight: 700;
  text-wrap: balance;
}

h1 { font-size: var(--t-hero); font-weight: 800; letter-spacing: -0.032em; }
h2 { font-size: var(--t-h2); }
h3 { font-size: var(--t-h3); line-height: 1.2; letter-spacing: -0.012em; }

p { margin: 0 0 var(--s-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--blue-700); }

img {
  display: block;
  max-width: 100%;
  height: auto;
}

ul, ol { margin: 0; padding: 0; list-style: none; }

/* The ring has to clear 3:1 against whatever it sits on, and this page runs
   light and dark surfaces against each other. --amber-500 was picked for the
   navy header and hero, where it is 7.9:1, but it is 2.2:1 on paper — which is
   most of the page, and the form, and the FAQ. So the ring is a token the dark
   surfaces re-declare for their own subtree.

   No border-radius here either: it was overriding the element's own, so every
   pill button and rounded card squared off for exactly as long as it held
   focus. The outline follows the real radius by itself. */
:root { --focus: var(--amber-600); }

.hero,
.site-header,
.site-footer,
.section--dark,
.package--top { --focus: var(--amber-400); }

:focus-visible {
  outline: 3px solid var(--focus);
  outline-offset: 3px;
}

/* ---------- skip link ---------- */

/* Every page puts the wordmark, and the home page a five-item nav, in front of
   the content. Off-screen until it takes focus. Fixed rather than absolute so
   shift-tabbing back to it from halfway down the page still shows it. */
.skip-link {
  position: fixed;
  top: 0;
  left: -9999px;
  z-index: 100;
  padding: var(--s-3) var(--s-5);
  background: var(--amber-500);
  color: var(--blue-950);
  font-size: var(--t-small);
  font-weight: 700;
  text-decoration: none;
  border-radius: 0 0 var(--radius) 0;
  box-shadow: var(--shadow-lg);
}

.skip-link:focus { left: 0; }

/* It lands on <main tabindex="-1">, which is only focusable so the skip link
   has somewhere to put focus. Clicking anywhere in the page body shouldn't
   ring the whole document — :focus-visible already handles that, but Safari
   has historically drawn a box on programmatic focus regardless. */
main:focus { outline: none; }

/* ---------- helpers ---------- */

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

.section {
  padding-block: var(--section-y);
}

.section--dark {
  background: var(--blue-950);
  color: var(--paper);
}

.section--tint {
  background: var(--paper-2);
}

.eyebrow {
  display: block;
  margin: 0 0 var(--s-4);
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber-600);
}

/* The hero is navy too, but it isn't a .section--dark — it's its own block. It
   was reading the light-surface amber off :root, which is 3.4:1 on that
   background and was 3.8:1 before. Both of them wrong; the dark amber is the
   one that belongs on navy. */
.section--dark .eyebrow,
.hero .eyebrow { color: var(--amber-400); }

.lead {
  font-size: var(--t-lead);
  line-height: 1.5;
  color: var(--ink-2);
  max-width: 54ch;
}

.section--dark .lead { color: var(--blue-300); }

/* Prose links on navy. `a` inherits --blue-700 from the base rule, which is
   tuned for paper and lands at 2.2:1 on navy — a dark blue link on a dark blue
   panel. It was already patched once at .section--dark .note a and once at
   .section--dark .form__fine a, each time the bug was noticed in one place;
   this is the same fix stated for the rest, which matters most on 404.html,
   where the three "most people are looking for" links were the page. Both of
   those rules are more specific and keep their own tuning. */
.section--dark p a,
.section--dark .lead a {
  color: #fff;
  text-decoration-color: var(--amber-500);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.section--dark p a:hover,
.section--dark .lead a:hover { color: var(--amber-400); }

.section__head {
  max-width: 62ch;
  margin-bottom: var(--s-7);
}

.section__head h2 + .lead,
.split__copy h2 + .lead { margin-top: var(--s-5); }

/* A value that must be impossible to miss — rates, clearances. */
.figure {
  font-size: clamp(2.2rem, 1.4rem + 3.2vw, 3.6rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1;
  color: var(--ink);
}

.section--dark .figure { color: #fff; }

.figure__unit {
  font-size: 0.4em;
  font-weight: 600;
  letter-spacing: -0.01em;
  color: var(--ink-3);
}

.section--dark .figure__unit { color: var(--blue-300); }

/* Anything not yet confirmed by the owner ships visible, never invented. */
.todo {
  display: inline-block;
  padding: 0.15em 0.5em;
  border: 2px dashed var(--amber-600);
  border-radius: 6px;
  background: #fff5e6;
  color: #8a4b00;
  font-size: max(0.42em, 0.72rem);
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  vertical-align: middle;
}

/* ---------- buttons ---------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--s-2);
  padding: 0.95em 1.6em;
  border: 2px solid transparent;
  border-radius: 999px;
  font: inherit;
  font-size: var(--t-small);
  font-weight: 700;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease,
              color 0.18s ease, transform 0.18s ease;
}

.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: var(--amber-500);
  border-color: var(--amber-500);
  color: var(--blue-950);
}

.btn--primary:hover {
  background: var(--amber-400);
  border-color: var(--amber-400);
}

.btn--ghost {
  background: transparent;
  border-color: currentColor;
  color: var(--paper);
}

.btn--ghost:hover {
  background: rgb(255 255 255 / 0.1);
}

.btn--dark {
  background: var(--blue-900);
  border-color: var(--blue-900);
  color: #fff;
}

.btn--dark:hover {
  background: var(--blue-800);
  border-color: var(--blue-800);
}

/* ---------- brandmark ---------- */

/* The wordmark is the client's artwork and stays a flat image; the town is
   real text stacked under it. That keeps it selectable and crawlable, lets it
   match "Top Gear Car Wash Innisfail" on the Google listing, and means it
   stays sharp at any size without a second raster. Used on both dark
   surfaces — the sticky header and the footer. */

.brandmark {
  display: inline-flex;
  flex-direction: column;
  align-items: stretch;
  gap: var(--s-2);
  text-decoration: none;
}

/* The rule is the span's own border, so it is exactly as wide as the logo
   sitting above it at every breakpoint — no magic width to keep in sync. */
.brandmark__place {
  border-top: 1px solid rgb(255 255 255 / 0.18);
  padding-top: var(--s-2);
  font-size: 0.6875rem;
  font-weight: 700;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  text-align: center;
  /* Tracking is added after every letter including the last, which hangs an
     empty 0.34em off the right and makes centred text look shifted left.
     Half of it back as indent puts the word optically centre again. */
  text-indent: 0.17em;
  line-height: 1;
  color: var(--blue-300);
}

/* ---------- header ---------- */

.site-header {
  position: sticky;
  top: 0;
  z-index: 50;
  background: var(--blue-950);
  color: var(--paper);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  column-gap: var(--s-4);
  row-gap: 0;
  padding-block: var(--s-3);
}

.site-header__logo {
  order: 1;
  flex: 0 0 auto;
}

.site-header__logo img {
  width: 150px;
  height: 44px;
  object-fit: contain;
}

@media (min-width: 40em) {
  .site-header__logo img { width: 178px; height: 52px; }
}

/* The toggle is two anchors, not a checkbox and not a script. The panel opens
   on :target, which means tapping any link inside it moves the target and
   closes the menu on its way to the section — the thing a checkbox hack
   cannot do without JavaScript.

   What :target costs is that following the link also scrolls the page to the
   target. So the burgers point at two empty sentinels pinned to the top of
   the sticky header instead of at the panel: the header is already at the top
   of the viewport, so the scroll the browser performs is zero, whether the
   visitor is at the hero or halfway down the page. Everything the target
   drives is inside .site-header__inner, one level down from the sentinels,
   which is why these selectors read `~ .site-header__inner …`. */

.nav-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: 0;
  height: 0;
  overflow: hidden;
}

.nav-burger {
  order: 2;
  margin-inline-start: auto;
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding: var(--s-2) var(--s-1);
  color: var(--paper);
  font-size: var(--t-small);
  font-weight: 700;
  text-decoration: none;
}

.nav-burger:hover { color: var(--amber-400); }

.nav-burger__box {
  position: relative;
  display: block;
  width: 22px;
  height: 14px;
}

.nav-burger__box::before,
.nav-burger__box::after,
.nav-burger__box span {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 2px;
  border-radius: 2px;
  background: currentColor;
}

.nav-burger__box::before { top: 0; }
.nav-burger__box span { top: 6px; }
.nav-burger__box::after { bottom: 0; }

.nav-burger--close .nav-burger__box::before { top: 6px; rotate: 45deg; }
.nav-burger--close .nav-burger__box::after { bottom: 6px; rotate: -45deg; }
.nav-burger--close .nav-burger__box span { opacity: 0; }

.nav-burger--close { display: none; }

#menu:target ~ .site-header__inner .nav-burger--open { display: none; }
#menu:target ~ .site-header__inner .nav-burger--close { display: inline-flex; }

/* The panel hangs off the bottom of the header rather than sitting in the
   header's own flow. In flow it pushed <main> down by its full height every
   time the menu opened, which moved whatever the visitor was reading. */
.site-nav-panel {
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  order: 3;
  flex-basis: 100%;
  display: grid;
  grid-template-rows: 0fr;
  background: var(--blue-950);
  transition: grid-template-rows 0.24s ease;
}

#menu:target ~ .site-header__inner .site-nav-panel {
  grid-template-rows: 1fr;
  /* Both only while open: a shadow or a rule on a collapsed panel is a smudge
     under the header, because a zero-height box still paints them. The rule is
     what says where the panel ends when it lands on a dark section and the
     shadow has nothing to fall on. */
  border-bottom: 1px solid rgb(255 255 255 / 0.13);
  box-shadow: var(--shadow-lg);
}

.site-nav-panel__inner {
  /* Also what collapses the panel: the 0fr row leaves this box no height. */
  overflow: hidden;
  min-height: 0;
  padding-inline: var(--gutter);
  /* A 0fr row clips the links but leaves them in the tab order and in the
     accessibility tree, so on a phone the five nav links were still reachable
     by keyboard while the menu read as closed — focus landing on nothing you
     can see. visibility takes them out of both, and unlike display it still
     animates, so it waits for the open transition rather than snapping. */
  visibility: hidden;
  transition: visibility 0s linear 0.24s;
}

#menu:target ~ .site-header__inner .site-nav-panel__inner {
  visibility: visible;
  transition-delay: 0s;
  /* Nothing pushes the page open any more, so a panel taller than the space
     under the header — a short landscape phone — has to scroll on its own. */
  max-height: calc(100vh - var(--header-h));
  max-height: calc(100dvh - var(--header-h));
  overflow-y: auto;
}

.site-nav {
  display: flex;
  flex-direction: column;
  padding-block: var(--s-3) 0;
  font-size: 1.05rem;
  font-weight: 600;
}

.site-nav a {
  color: #fff;
  text-decoration: none;
  padding-block: var(--s-3);
  border-bottom: 1px solid rgb(255 255 255 / 0.13);
}

.site-nav a:hover { color: var(--amber-400); }

.site-header__hours {
  display: inline-flex;
  align-items: center;
  gap: var(--s-2);
  padding-block: var(--s-4) var(--s-2);
  font-size: var(--t-micro);
  font-weight: 600;
  color: var(--blue-300);
  white-space: nowrap;
}

.site-header__hours::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: #39d98a;
}

@media (min-width: 52em) {
  .site-header__inner { row-gap: var(--s-2); }

  .nav-burger,
  #menu:target ~ .site-header__inner .nav-burger--close { display: none; }

  /* The wrappers vanish and the nav becomes a flex item of the header again.
     No box means the overlay positioning above is moot, but say it anyway so
     a deep link to #menu can never leave a stray box on a desktop.
     visibility has to come back explicitly: display:contents drops the box but
     not the inheritance, so the collapsed-panel hiding would follow the links
     onto the desktop header and take the whole nav with it. */
  .site-nav-panel,
  .site-nav-panel__inner {
    display: contents;
    position: static;
    visibility: visible;
  }

  .site-nav {
    order: 2;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: var(--s-2) var(--s-5);
    margin-inline-start: auto;
    padding-block: 0;
    font-size: var(--t-small);
    font-weight: 600;
  }

  .site-nav a {
    color: var(--blue-300);
    padding-block: var(--s-1);
    border-bottom: 2px solid transparent;
    transition: color 0.16s ease, border-color 0.16s ease;
  }

  .site-nav a:hover {
    color: #fff;
    border-bottom-color: var(--amber-500);
  }

  /* The nav comes back inline well before desktop; the hours pill needs the
     room a tablet doesn't have, so it waits. */
  .site-header__hours { display: none; }
}

@media (min-width: 64em) {
  .site-header__hours {
    order: 3;
    display: inline-flex;
    padding-block: 0;
  }
}

/* ---------- nav: which section am I in ---------- */

/* The hover underline now also means "you are here", and stays put whether the
   visitor clicked the link or scrolled past the section. Two mechanisms, and
   only ever one of them live:

   1. Browsers with scroll-driven animations get a real scroll-spy. Each
      section owns a view-timeline, and the matching link runs a one-frame
      animation for exactly as long as that section crosses a detection line
      below the header. Clicking is covered too, because a click is a scroll.
   2. Everything older falls back to :target through :has(). The header sits
      before <main>, so no sibling combinator can reach from a section back up
      to its link — :has() on a common ancestor is the only way to say it.
      That lights the link on a click or a deep link but cannot follow a
      scroll; it is the honest half of the feature, not a broken version.

   Both are scoped to the inline nav. Below 52em the links live in the :target
   panel, which is only on screen while it is open — and while it is open it
   covers the detection line, so there is nothing an active state could say.

   Sections with no nav link of their own (new ownership, why here, the FAQ)
   leave every link unlit while you are in them. That is deliberate: lighting
   the previous section's link would claim you are somewhere you are not. */

@media (min-width: 52em) {
  @keyframes nav-in-view {
    from, to {
      color: #fff;
      border-bottom-color: var(--amber-500);
    }
  }

  @supports (animation-timeline: view()) {
    /* The link and the section are in different subtrees, so the timeline
       names have to be published somewhere that covers both. */
    body {
      timeline-scope:
        --sec-rv-truck, --sec-self-serve, --sec-automatic,
        --sec-location, --sec-contact;
    }

    #rv-truck   { view-timeline-name: --sec-rv-truck; }
    #self-serve { view-timeline-name: --sec-self-serve; }
    #automatic  { view-timeline-name: --sec-automatic; }
    #location   { view-timeline-name: --sec-location; }
    #contact    { view-timeline-name: --sec-contact; }

    /* Shrink the scrollport to a 1px line. The sections are contiguous, so
       exactly one of them crosses that line at any scroll position — a taller
       band lights two links at once every time a boundary passes through it.
       3rem below the header is comfortably inside whatever a click just
       scrolled to, which lands its top at header + 1rem. */
    #rv-truck,
    #self-serve,
    #automatic,
    #location,
    #contact {
      --spy-line: calc(var(--header-h) + 3rem);
      view-timeline-inset: var(--spy-line) calc(100% - var(--spy-line) - 1px);
    }

    .site-nav a[href="#rv-truck"],
    .site-nav a[href="#self-serve"],
    .site-nav a[href="#automatic"],
    .site-nav a[href="#location"],
    .site-nav a[href="#contact"] {
      animation-name: nav-in-view;
      animation-timing-function: linear;
      /* Deliberately not `both`: a filled scroll-driven animation keeps
         painting outside its range, which lights every link at once. */
      animation-fill-mode: none;
      animation-range: cover;
    }

    .site-nav a[href="#rv-truck"]   { animation-timeline: --sec-rv-truck; }
    .site-nav a[href="#self-serve"] { animation-timeline: --sec-self-serve; }
    .site-nav a[href="#automatic"]  { animation-timeline: --sec-automatic; }
    .site-nav a[href="#location"]   { animation-timeline: --sec-location; }
    .site-nav a[href="#contact"]    { animation-timeline: --sec-contact; }

    /* The global reduced-motion reset clamps every animation to 0.001ms, which
       collapses a scroll-driven range to nothing. Nothing here moves — it is a
       scroll position read as a state — so it opts back out. */
    @media (prefers-reduced-motion: reduce) {
      .site-nav a { animation-duration: auto !important; }
    }
  }

  @supports not (animation-timeline: view()) {
    body:has(#rv-truck:target)   .site-nav a[href="#rv-truck"],
    body:has(#self-serve:target) .site-nav a[href="#self-serve"],
    body:has(#automatic:target)  .site-nav a[href="#automatic"],
    body:has(#location:target)   .site-nav a[href="#location"],
    body:has(#contact:target)    .site-nav a[href="#contact"] {
      color: #fff;
      border-bottom-color: var(--amber-500);
    }
  }
}

/* ---------- hero ---------- */

.hero {
  position: relative;
  background: var(--blue-950);
  color: var(--paper);
  overflow: hidden;
}

.hero__media {
  position: absolute;
  inset: 0;
}

.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 62% 42%;
}

.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right,
      rgb(6 24 43 / 0.94) 0%,
      rgb(6 24 43 / 0.86) 38%,
      rgb(6 24 43 / 0.52) 72%,
      rgb(6 24 43 / 0.44) 100%),
    linear-gradient(to bottom,
      rgb(6 24 43 / 0.55) 0%,
      rgb(6 24 43 / 0.15) 40%,
      rgb(6 24 43 / 0.75) 100%);
}

.hero__inner {
  position: relative;
  padding-block: clamp(3.5rem, 2rem + 9vw, 8.5rem);
}

.hero__copy {
  max-width: 40ch;
}

.hero h1 {
  color: #fff;
}

.hero h1 em {
  font-style: normal;
  color: var(--amber-400);
}

.hero__lead {
  margin-top: var(--s-5);
  font-size: var(--t-lead);
  line-height: 1.5;
  color: #d6e4f2;
  max-width: 46ch;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3);
  margin-top: var(--s-6);
}

.hero__strip {
  position: relative;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--s-4) var(--s-6);
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid rgb(255 255 255 / 0.18);
}

.hero__stat dt {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--blue-300);
}

.hero__stat dd {
  margin: var(--s-1) 0 0;
  font-size: 1.1rem;
  font-weight: 700;
  color: #fff;
}

/* ---------- three ways ---------- */

.ways {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
}

/* Three cards, so auto-fit's 2-across leaves one stranded on its own row
   through the whole tablet range. Go 1 -> 3 and skip it. */
@media (min-width: 62em) {
  .ways { grid-template-columns: repeat(3, 1fr); }
}

.way {
  display: flex;
  flex-direction: column;
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow);
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.way:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-lg);
}

.way__media {
  aspect-ratio: 4 / 3;
  background: var(--paper-3);
  /* A flex item's automatic minimum size is its content, so the one card that
     has a photo let a 3:4 portrait push the panel to 1.33x its width while the
     two empty ones sat at 0.75x — three cards, three different image heights.
     min-height: 0 hands the sizing back to aspect-ratio and object-fit crops. */
  min-height: 0;
  overflow: hidden;
}

/* Full-width card on a tablet: a 4:3 image would be 500px tall. */
@media (min-width: 40em) and (max-width: 61.999em) {
  .way__media { aspect-ratio: 16 / 9; }
}

.way__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* The touchless photo is a portrait whose subject, the gantry, sits in the top
   half. A centred crop keeps the floor drain and cuts the machine off. */
.way__media--high img {
  object-position: 50% 25%;
}

/* A photo the owner hasn't taken yet. Visible on purpose — it drives the shot
   list, and it can't be mistaken for finished work. */
.way__media--todo {
  display: grid;
  place-items: center;
  padding: var(--s-5);
  background:
    repeating-linear-gradient(-45deg,
      #fff5e6 0 12px, #ffeacc 12px 24px);
  border-bottom: 2px dashed var(--amber-600);
}

.way__media--todo p {
  margin: 0;
  color: #8a4b00;
  font-size: var(--t-small);
  font-weight: 700;
  text-align: center;
  text-wrap: balance;
}

.way__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--s-3);
  padding: var(--s-5);
}

.way__count {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber-600);
}

.way p {
  color: var(--ink-2);
  font-size: var(--t-small);
}

.way__price {
  margin-top: auto;
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  font-weight: 700;
}

.way__link {
  font-size: var(--t-small);
  font-weight: 700;
  text-decoration: none;
  color: var(--blue-700);
}

.way__link:hover { text-decoration: underline; }

/* ---------- split: media beside copy ---------- */

.split {
  display: grid;
  gap: var(--s-6);
  align-items: center;
}

@media (min-width: 55em) {
  .split {
    grid-template-columns: 1fr 1fr;
    gap: var(--s-8);
  }
  .split--flip .split__media { order: 2; }
}

.split__media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: var(--paper-3);
  box-shadow: var(--shadow);
}

.split__media img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}

@media (min-width: 55em) {
  .split__media img {
    aspect-ratio: 3 / 4;
    max-height: 640px;
  }
}

/* ---------- clearance: the numbers an RV owner needs ---------- */

.clearance {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: var(--s-5);
  margin: var(--s-7) 0;
  padding: var(--s-6);
  background: rgb(255 255 255 / 0.05);
  border: 1px solid rgb(255 255 255 / 0.16);
  border-radius: var(--radius-lg);
}

.clearance__item dt {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue-300);
}

.clearance__item dd {
  margin: var(--s-2) 0 0;
}

/* ---------- spec list ---------- */

.specs {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
  margin-top: var(--s-6);
}

@media (min-width: 34em) {
  .specs { grid-template-columns: repeat(2, 1fr); }
}

/* Explicit counts rather than auto-fit: auto-fit picked 3 for the 4-item grid
   and 4 for the 6-item grid, leaving an orphan in both. */
@media (min-width: 62em) {
  .specs--4 { grid-template-columns: repeat(4, 1fr); }
  .specs--6 { grid-template-columns: repeat(3, 1fr); }
}

.spec {
  padding-top: var(--s-4);
  border-top: 2px solid var(--line);
}

.section--dark .spec { border-top-color: rgb(255 255 255 / 0.22); }

.spec dt,
.spec h3 {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber-600);
  margin-bottom: var(--s-2);
}

.section--dark .spec dt,
.section--dark .spec h3 { color: var(--amber-400); }

.spec dd,
.spec p {
  margin: 0;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.section--dark .spec dd,
.section--dark .spec p { color: #cddced; }

.spec strong { color: var(--ink); }
.section--dark .spec strong { color: #fff; }

/* ---------- feature chips ---------- */

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-2);
  margin-top: var(--s-5);
}

.chips li {
  padding: 0.45em 0.9em;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: #fff;
  font-size: var(--t-small);
  font-weight: 600;
}

.section--dark .chips li {
  background: rgb(255 255 255 / 0.07);
  border-color: rgb(255 255 255 / 0.2);
  color: #fff;
}

/* ---------- numbered steps ---------- */

.steps {
  counter-reset: step;
  display: grid;
  gap: var(--s-5);
  margin-top: var(--s-6);
}

@media (min-width: 48em) {
  .steps { grid-template-columns: repeat(3, 1fr); gap: var(--s-6); }
}

.steps li {
  counter-increment: step;
  padding-top: var(--s-4);
  border-top: 2px solid var(--line);
}

.steps li::before {
  content: counter(step);
  display: block;
  margin-bottom: var(--s-2);
  font-size: 1.5rem;
  font-weight: 800;
  line-height: 1;
  color: var(--amber-600);
}

.steps h3 {
  font-size: 1.0625rem;
  margin-bottom: var(--s-2);
}

.steps p {
  font-size: var(--t-small);
  color: var(--ink-2);
}

/* ---------- packages ---------- */

.packages {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--s-5);
  margin-top: var(--s-7);
}

@media (min-width: 48em) {
  .packages { grid-template-columns: repeat(3, 1fr); }
}

.package {
  display: flex;
  flex-direction: column;
  gap: var(--s-3);
  padding: var(--s-6);
  background: #fff;
  border: 1px solid var(--line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}

.package--top {
  background: var(--blue-950);
  border-color: var(--blue-950);
  color: #fff;
}

.package__name {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--amber-600);
}

.package--top .package__name { color: var(--amber-400); }

.package__price {
  font-size: clamp(2.4rem, 1.8rem + 2vw, 3.2rem);
  font-weight: 800;
  letter-spacing: -0.035em;
  line-height: 1;
}

.package p {
  margin: 0;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.package--top p { color: #cddced; }

.package__steps {
  display: grid;
  gap: var(--s-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.package__steps li {
  position: relative;
  padding-left: 1.1em;
}

.package__steps li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.55em;
  width: 0.45em;
  height: 0.45em;
  border-radius: 50%;
  /* --amber-500 is the navy-surface amber: 2.3:1 on a white card. */
  background: var(--amber-600);
}

.package--top .package__steps { color: #cddced; }

/* "Everything in X, plus:" heads the list, so it reads as a label rather
   than as one more step: full ink, and a rule off the price above it. */
.package p.package__plus {
  padding-top: var(--s-3);
  border-top: 1px solid var(--line);
  color: var(--ink);
  font-weight: 700;
}

.package--top p.package__plus {
  border-top-color: rgb(255 255 255 / 0.16);
  color: #fff;
}
.package--top .package__steps li::before { background: var(--amber-400); }

/* A step the top package runs twice. The pill takes the dot's place. */
.package__steps .package__double { padding-left: 0; }
.package__steps .package__double::before { content: none; }

.package__x {
  display: inline-block;
  margin-right: 0.5em;
  padding: 0.1em 0.45em;
  border-radius: 999px;
  background: var(--amber-400);
  color: var(--blue-950);
  font-size: 0.8em;
  font-weight: 800;
  letter-spacing: 0.02em;
  line-height: 1.3;
}

/* Read by screen readers, invisible on screen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* A note that qualifies a claim — never decorative. */
.note {
  max-width: 78ch;
  margin-top: var(--s-6);
  padding: var(--s-4) var(--s-5);
  border-left: 4px solid var(--amber-500);
  background: var(--paper-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  font-size: var(--t-small);
  color: var(--ink-2);
}

.section--dark .note {
  background: rgb(255 255 255 / 0.06);
  color: #cddced;
}

/* The oversized-vehicle callout is the page's answer to the one question it
   can't print a number for, so its phone link has to be the most legible thing
   in the box. It was inheriting the light-surface --blue-700, which lands near
   1.6:1 on navy — a dark blue number on a dark blue panel. */
.section--dark .note a {
  color: #fff;
  font-weight: 700;
  text-decoration-color: var(--amber-500);
  text-decoration-thickness: 2px;
  text-underline-offset: 3px;
}

.section--dark .note a:hover { color: var(--amber-400); }

/* ---------- location ---------- */

.location {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}

@media (min-width: 55em) {
  .location {
    grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
    gap: var(--s-8);
  }
}

.location__map {
  border: 0;
  width: 100%;
  aspect-ratio: 4 / 3;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
  background: var(--paper-3);
}

.address {
  font-style: normal;
  font-size: var(--t-lead);
  line-height: 1.45;
  font-weight: 600;
}

.hours {
  margin-top: var(--s-6);
}

.hours dt {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber-600);
}

.hours dd {
  margin: var(--s-2) 0 0;
  font-size: var(--t-lead);
  font-weight: 700;
}

.hours dd span {
  display: block;
  font-size: var(--t-small);
  font-weight: 500;
  color: var(--ink-2);
}

/* The phone number sits in a .hours dd, so it was the one link on the page
   still wearing the browser default — generic blue, generic underline, beside
   hours set in ink. Same treatment as the callout on the dark section: read as
   the number first, as a link second. */
.hours dd a {
  color: var(--ink);
  text-decoration-color: var(--amber-500);
  text-decoration-thickness: 2px;
  text-underline-offset: 4px;
}

.hours dd a:hover { color: var(--blue-700); }

/* ---------- form ---------- */

.form {
  display: grid;
  gap: var(--s-5);
  margin-top: var(--s-6);
  /* A 1460px-wide textarea is nobody's idea of a form. */
  max-width: 820px;
}

@media (min-width: 42em) {
  .form__row {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: var(--s-5);
  }
}

.field {
  display: block;
}

.field > span {
  display: block;
  margin-bottom: var(--s-2);
  font-size: var(--t-small);
  font-weight: 700;
}

.field input,
.field textarea {
  width: 100%;
  padding: 0.8em 0.9em;
  border: 2px solid var(--line-input);
  border-radius: var(--radius);
  background: #fff;
  font: inherit;
  color: var(--ink);
  transition: border-color 0.16s ease;
}

.field input:focus,
.field textarea:focus {
  border-color: var(--blue-500);
}

.field textarea {
  min-height: 9rem;
  resize: vertical;
}

/* Honeypot. Hidden from people, visible to the bots that fill everything in. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form__submit {
  justify-self: start;
}

.form__fine {
  font-size: var(--t-micro);
  color: var(--ink-3);
  max-width: 60ch;
}

/* The form only ever renders on the dark section, where --ink-3 lands at about
   3.5:1 — under AA for text this small. Lift it, and make the privacy link
   visibly a link rather than a slightly different grey. */
.section--dark .form__fine { color: #a8bccf; }

.section--dark .form__fine a {
  color: var(--blue-300);
  text-decoration-thickness: 1px;
  text-underline-offset: 2px;
}

.section--dark .form__fine a:hover { color: var(--amber-400); }

/* ---------- faq ---------- */

.faq {
  max-width: var(--wrap-narrow);
  margin-top: var(--s-6);
}

.faq details {
  border-bottom: 1px solid var(--line);
}

.faq summary {
  padding: var(--s-5) var(--s-6) var(--s-5) 0;
  font-size: var(--t-h3);
  font-weight: 700;
  letter-spacing: -0.012em;
  line-height: 1.25;
  cursor: pointer;
  list-style: none;
  position: relative;
  transition: color 0.16s ease;
}

/* The row is a click target but the only thing that said so was the cursor. */
.faq summary:hover { color: var(--blue-700); }

.faq summary::-webkit-details-marker { display: none; }

.faq summary::after {
  content: "+";
  position: absolute;
  right: 0;
  top: 50%;
  translate: 0 -50%;
  font-size: 1.6rem;
  font-weight: 500;
  line-height: 1;
  color: var(--amber-600);
}

.faq details[open] summary::after { content: "\2013"; }

.faq details > *:not(summary) {
  margin-bottom: var(--s-5);
  color: var(--ink-2);
  max-width: 62ch;
}

/* ---------- footer ---------- */

.site-footer {
  background: var(--blue-950);
  color: var(--blue-300);
  padding-block: var(--s-8) var(--s-6);
  font-size: var(--t-small);
}

.site-footer__grid {
  display: grid;
  gap: var(--s-6);
  align-items: start;
}

@media (min-width: 48em) {
  .site-footer__grid {
    grid-template-columns: 1.2fr 1fr 1fr;
    gap: var(--s-7);
  }
}

.site-footer img {
  width: 178px;
  height: 52px;
  object-fit: contain;
}

/* Three tiers, and nothing outside them — the footer was picking white or
   blue-300 per element, so the address was white and the hours beside it were
   blue for no reason a reader could work out.
     amber   = the column label
     white   = a fact, or something you can click
     blue300 = supporting prose that isn't either
   White is doing two jobs, so links carry an underline as well; without it
   "Directions" and the street address were the same thing to look at. */

.site-footer h2 {
  font-size: var(--t-micro);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--amber-400);
  margin-bottom: var(--s-3);
}

.site-footer__fact {
  color: #fff;
  font-style: normal;
  font-weight: 600;
  line-height: 1.55;
}

.site-footer a {
  color: #fff;
  text-decoration: underline;
  text-decoration-color: rgb(255 255 255 / 0.32);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color 0.16s ease, text-decoration-color 0.16s ease;
}

.site-footer a:hover {
  color: var(--amber-400);
  text-decoration-color: var(--amber-400);
}

.site-footer__bar {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s-3) var(--s-5);
  justify-content: space-between;
  margin-top: var(--s-7);
  padding-top: var(--s-5);
  border-top: 1px solid rgb(255 255 255 / 0.15);
  font-size: var(--t-micro);
}

/* The sub-pages (privacy, thanks, sorry, 404) ship the bar on its own, where
   the rule was dividing the padding above it from the text below it. */
.site-footer__bar:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

/* ---------- small utilities ---------- */

.mt-5 { margin-top: var(--s-5); }
.mt-6 { margin-top: var(--s-6); }
.mt-4 { margin-top: var(--s-4); }
.mt-3 { margin-top: var(--s-3); }
.muted { color: var(--ink-2); }

/* ---------- thank-you page ---------- */

/* Short page, so give it enough height not to look like an error. */
.thanks {
  display: flex;
  align-items: center;
  min-height: 68vh;
}

.thanks__inner { max-width: 62ch; }

.thanks h1 {
  font-size: var(--t-h2);
  margin-bottom: var(--s-5);
}

.thanks .lead { color: #cddced; }
.thanks strong { color: #fff; }

.field span em {
  font-style: normal;
  font-weight: 500;
  color: var(--ink-3);
}

.section--dark .field span em { color: var(--blue-300); }

/* ---------- legal pages (privacy) ---------- */

/* Long-form prose, which nothing else on the site is. One narrow column, a
   measure that stays readable, and headings small enough that a policy doesn't
   shout like the hero does. */
.legal {
  max-width: 72ch;
}

/* h1 defaults to --t-hero, which is right for "Eleven bays for everything you
   drive" and absurd for "What we do with your information". Same treatment
   .thanks h1 gets. */
.legal-page h1 {
  font-size: var(--t-h2);
  max-width: 18ch;
}

.legal h2 {
  font-size: var(--t-h3);
  margin-top: var(--s-8);
  padding-top: var(--s-5);
  border-top: 1px solid var(--line);
}

.legal h2:first-of-type { margin-top: var(--s-7); }

.legal h3 {
  font-size: 1.0625rem;
  margin-top: var(--s-6);
  letter-spacing: 0;
}

.legal p,
.legal li {
  max-width: 68ch;
  color: var(--ink-2);
}

.legal p { margin-top: var(--s-4); }

/* The base rule strips list-style from every ul on the site, which is right
   everywhere but here: this is the one place a list is prose rather than a
   layout, and "your rights under PIPA" was rendering as four unmarked lines. */
.legal ul {
  margin-top: var(--s-4);
  padding-left: 1.15em;
  list-style: disc;
}

.legal li { margin-top: var(--s-3); }

.legal a { color: var(--blue-700); }
.legal a:hover { text-decoration: none; }

.legal strong { color: var(--ink); }

/* Who gets what, and where they are. A list rather than a table so it doesn't
   need horizontal scrolling on a phone. */
.legal__who {
  margin-top: var(--s-5);
  padding: var(--s-5);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  background: var(--paper-2);
}

.legal__who dt {
  font-weight: 700;
  color: var(--ink);
}

.legal__who dt + dd {
  margin: var(--s-2) 0 var(--s-5);
  color: var(--ink-2);
}

.legal__who dd:last-child { margin-bottom: 0; }

.legal__updated {
  margin-top: var(--s-6);
  font-size: var(--t-small);
  color: var(--ink-3);
}
